PicLan DOS/Windows Software Developers Kit

(C) Copyright 1992-1995 Modular Software Corporation. All rights reserved.

March 14, 1995

This document describes the PicLan client interface library. This library is intended for developers writing applications for DOS and Windows in C, although the interfaces described may be callable from other languages. This documentation is provided AS-IS. No warranty of any kind is made.

MODULAR SOFTWARE DOES NOT PROVIDE TECHNICAL SUPPORT FOR THIS PROGRAMMING LIBRARY. IF YOU ARE NOT A DOS OR WINDOWS PROGRAMMER WITH EXPERIENCE INTERFACING WITH THIRD-PARTY LIBRARIES, THEN THIS SDK IS NOT INTENDED FOR YOU.

Version Information

This documentation was prepared in conjunction with PicLan version 1.1.0.11. Most of the DOS functions listed should operate with previous versions of PicLan all the way back to version 0.7. Windows functions require at least PicLan version 1.0.1.0.

Windows Callbacks

PicLan version 1.1.0.2 introduced a new set of APIs called Windows Callbacks. These functions are designed to allow Windows applications to operate without having to continually poll the network connections. Unfortunately, Windows Callbacks are not yet completely stable and their use is not recommended.

Future Directions

The PicLan driver library is subject to on-going changes and enhancements. This version marks the addition of support for Microsoft Windows as well as enhanced memory management options. Possible future enhancements include support for OS/2, Macintosh, and other client platforms. Also possible are support for peer-to-peer Pick functions, Pick file access through the PicLan SERVER-PROCESS, and other issues. Most of these enhancements are developer driven, so your input is invited.

Modular Software is also developing stub layers for the PLAN.DLL Microsoft Windows support DLL. Initially, these are being developed as Visual Basic custom controls (VBXs), but support for OLE custom controls is anticipated. At this time two VBXs are included with the PicLan package, but because there interface is not yet solidified, their use is undocumented here.

Issues Relating to Third-Party Developers

The DOS client version of the PicLan SDK is designed for DOS workstations running the PicLan PL-DEV.EXE driver TSR. The use of this TSR allows Modular Software to make periodic changes to the PicLan network protocols without requiring that third-party developers produce new versions of their products to stay in sync. As such, third-party developers should not ship PicLan supplied drivers like PL-DEV.EXE and/or PLAN.DLL with their products. Users should be advised to use the copies of these files that were included with PicLan instead.

Memory Management Issues

The PLLIB system allocates memory for control structures on a client-by-client basis. Memory can be allocated from real memory under application control, or from EMS or XMS memory under the control of the PL-DEV.EXE TSR. Parameters passed to the initialization functions allow the application to control aspects of how memory is allocated.

The choice of where to allocate memory can be rather complicated, and is certainly very application-dependent. For absolute maximum performance, control structures should be allocated in real memory ("very fast") in preference to EMS ("fairly fast"), and in EMS in preference to XMS ("rather slow"). To maximize available real memory, control structures should be allocated in either EMS or XMS in preference to real memory. Finally, some problems have been observed with using the Microsoft HIMEM.SYS memory manager and XMS memory. Modular Software recommends that users be given at least some degree of control over how the control structures are allocated, since a non-flexible application running into an incompatible memory allocate strategy might prove to be completely unusable in some cases.

In those cases where PLCB's and BUF's are allocated in real memory, the PLLIB system requires that for open connections the control structures always be resident in non-movable memory. If PLCB's or BUF's must be unloaded (for example, the program wants to minimize memory use when spawning another program), then the connection must be closed. Alternatively, plan_save() and plan_restore() may be used to put the connection "on hold". Note that plan_save() and plan_restore() only work with terminal connections - connections to the PicLan Server Process (which is not yet supported for third-party developers) can not be placed on hold using plan_save(). Also note that before calling plan_restore(), the PLCB's and BUF's must be reloaded (intact) into the exact same memory locations which they previously occupied.

In cases where applications must share a connection between multiple executables, the PLCB's and BUF's must again always be in memory while the connection is open. The application can either close and re-open the connection, or can guarantee that the PLCB's and BUF's never move while the applications load and unload (perhaps by placing them in a TSR, device driver, or high-memory location). Also, the same program which calls plan_init() should be the program which calls plan_term().

Note that these restrictions apply when the PLCB and BUF structures for a client are allocated in real memory. However, since the memory allocation strategy is fairly well hidden from the application, the above guidelines should be followed even when the structures have been allocated in EMS or XMS memory.

Windows applications also use PLCB and BUF memory, but this memory is always allocated in an XMS "heap" that is owned by the PL-DEV.EXE TSR. This global size of the XMS heap is set with the WinHeapSize=xxx line in the PL-CFG.INI file.

Using the Libraries

Overview

The PLLIB.H file contains all of the definitions and prototypes for the PicLan workstation software library. It must be included into any source file which is performing calls into the library. PLLIB.H contains prototypes for all of the functions under all of the platforms - check the documentation for each function to determine whether it is actually available under the platform being used.

Use the plan_init_mem() function to allocate a client handle, and use plan_term_mem() to free the client handle. Failure to call plan_term_mem() can cause the system to crash - always call plan_term_mem() for any client handle which has been allocated.

A single communication channel is controlled by a PicLan control block (PLCB). Use the plan_alloc_plcb() and plan_dealloc_plcb() functions to allocate and deallocate PLCB's from the pool created by plan_init_mem(). PLCB's use buffers (BUF's) which were also allocated by plan_init_mem().

To establish a communication session, the plan_find_servers() function is used to find all of the servers on the network. plan_get_server() retrieves information from the replies buffered by plan_find_servers(), and the application examines the capabilities flags for each server to determine if it is appropriate to continue. plan_open() is used to connect to the remote system. plan_read() and plan_write() are used to send data over the channel. plan_break() and plan_xoff() are used to send special control information over terminal channels. plan_close() is used to terminate communications and close the channel.

A number of the functions in the library require a dialogue with another system on the network for the function to complete. These functions are supplied in both "no wait" and "wait" versions - when calling the "no wait" version, you must continue to call it in a loop with the same parameters until it returns non-zero. The "wait" versions of each function are implemented simply as a spin-loop calling the respective "no wait" version. Note that "wait" versions of functions are not available under Windows - they may take up to several seconds to complete (if network error conditions arise), and a "wait" version would prevent the Windows message queue from being serviced.

DOS Applications

The files PLS_S.LIB, PLS_M.LIB, and PLS_L.LIB are the library files for programs built in small, medium, and large model, respectively. These same library files are used regardless of the compiler: they support Turbo C++, Borland C++ 2.0, Borland C++ 3.0, Borland C++ 3.1, Borland C++ 4.0, Microsoft C 5.1, Microsoft C 6.0, and Microsoft C++ 7.0. The librarys may also support other compilers, but these have not been tested at MSC. Each of these libraries assume that PL-DEV will be loaded as a TSR. For some versions of some compilers, during linking the symbols __fmemcpy, __fmemset, __fstrcpy, and _fstrlen may be unresolved - in this case, you should compile and link the file FMEM.C (supplied with this SDK) into your application to resolve those symbols.

Windows Applications

In order to provide memory access to the PicLan buffers at all times under Windows Enhanced Mode, PicLan allocates XMS memory during Windows' initialization. It then suballocates this memory for clients running within Windows (whether a DOS app or a Win app). Since the memory is allocated from outside of a Windows VM, the XMS handle is global and is accessible to any VM. The PL-DEV.EXE program is loaded before Windows and is global to all VM's - it's interrupt service routines will be called in the context of whatever VM happens to be running when the event occurs, and PL-DEV.EXE can use the global XMS memory handle to access any client's buffers. (For DOS TSR clients loaded before Windows starts, the buffers will obviously be in global address space as well, regardless of whether it was allocated in real, EMS, or XMS memory.) Due to these memory management issues, PicLan services are only available in Windows under Standard Mode and Enhanced Mode - Real Mode is not supported.

Win apps use PicLan services by invoking functions in the PL-DEV.EXE TSR just as DOS apps do. However, Win apps require an API translation layer to convert protected mode addresses to real mode addresses, and to actually transfer control to the TSR. A PLAN.DLL file is provided which performs this translation - PLAN.DLL exports a set of PicLan API functions, and translates those functions into calls to the TSR.

When including the PLLIB.H file in a Windows program, define the symbol PLAN_WIN_LIB to use the functions under Windows. The most likely effect of not defining this symbol is the generation of "general protection fault" traps due to calling convention mismatches between the client program and PLAN.DLL.

For Windows applications, the file PLAN.LIB is an import library for the exported symbols for PLAN.DLL. However, it is recommended that you not link to PLAN.LIB - if you do so, then your application will not be able to load if PLAN.DLL is not present. Rather, you should use run-time dynamic linking to call the functions in PLAN.DLL. The file PLANLINK.C contains a fully-functional example of how to do this - you can statically link PLANLINK.C in your application and call the functions in it just as if you were calling PLAN.DLL.

Bugs in PLAN.DLL:

The PicLan PLAN.DLL program and the underlying PL-DEV.EXE TSR have been undergoing considerable in-house testing. If you are using Windows without callbacks, your application should check for PicLan version 1.1.0.4 or later. Windows Callbacks should not be used with the 1.1.0.11 release. Check with Modular Software to see if Windows Callbacks have been stabalized.

Structures and Constants

#define PLAN_CAP_TERM_HOST  0x01
#define PLAN_CAP_FILE_XFR  0x02
#define PLAN_CAP_PRINT   0x04
#define PLAN_CAP_FILE_DSG  0x20
#define PLAN_CAP_DSG   0x10

These are the constants for bit-values in the PLAN_SERVER_STRUCT.capabilities field. If (PLAN_SERVER_STRUCT.capabilities & PLAN_CAP_TERM_HOST) != 0, then the server is capable of hosting terminal connections.

#define PLAN_PLCB_TERM_NODE 2
#define PLAN_PLCB_FILE_NODE 11

These are the constants for connections established through the plan_open() function. PLAN_PLCB_TERM_NODE means "open a terminal connection with this end as the node".

#define PLAN_STATUS_OPEN 0x01
#define PLAN_STATUS_BUSY 0x02
#define PLAN_STATUS_MORE_IN 0x04
#define PLAN_STATUS_XOFF_OUT 0x08
#define PLAN_STATUS_SLEEPQ 0x10
#define PLAN_STATUS_RUNQ 0x20
#define PLAN_STATUS_MSG 0x40

These constants are bit-fields within the status returned by plan_status(). PLAN_STATUS_OPEN signals that the PLCB is open. PLAN_STATUS_BUSY signals that the PLCB awaiting an ACK from the remote system. PLAN_STATUS_MORE_IN signals that the PLCB is expecting additional data from the remote system. PLAN_STATUS_XOFF_OUT signals that the PLCB has sent an XOFF to prevent the remote system from generating more data. PLAN_STATUS_SLEEPQ signals that the PLCB is on the sleep queue (waiting to run until a certain time). PLAN_STATUS_RUNQ signals that the PLCB is ready to run. PLAN_STATUS_MSG signals that the PLCB has a message queued to be sent.#define PLAN_OPEN_TERM_WILD 0xffff

This constant is used for the port parameter of the plan_open() function when the application wants to perform "port seeking" to the first available terminal port.

#define PLAN_ALLOC_FAST 0x01
#define PLAN_ALLOC_NOEMS 0x02
#define PLAN_ALLOC_NOXMS 0x04
#define PLAN_ALLOC_XMSHEAP 0x08
#define PLAN_ALLOC_NOREAL 0x10

These constants are passed in the alloc_flag parameter to plan_init_mem() and control how memory allocate occurs. PLAN_ALLOC_FAST signals that a "fast" strategy (speed is more important than optimising usage of real memory) should be used - otherwise, a "slow" strategy is used. PLAN_ALLOC_NOEMS prevents EMS memory from being used. PLAN_ALLOC_NOXMS prevents XMS memory from being used. PLAN_ALLOC_NOREAL prevents real memory from being used. PLAN_ALLOC_XMSHEAP is used internally, and should never be passed in alloc_flag. Note that these are bitfield values which can be logically OR'ed together to produce the desired behavior.

typedef struct _PLAN_SERVER_STRUCT {
                  unsigned char immediate[6];
                  unsigned char net[4];
                  unsigned char node[6];
                  unsigned char socket[2];
                  unsigned char capabilities;
                  char dummy;
                  char name[10];
                  unsigned long sn;
                  unsigned long version;
                                    } PLAN_SERVER_STRUCT;

A PLAN_SERVER_STRUCT describes a PicLan server. The immediate, net, node, and socket fields desribe the network addressing used to communicate with the server - they are in MSB-first order, and are used internally to PicLan. The capabilities field is a bit-mask of the server's capabilities - only PLAN_CAP_TERM_HOST is currently defined. The name field contains the NULL-terminated name of the server. The sn field contains the serial number of the server. The version field contains a version number for the low-level packet protocol used by the server - it must match the return value from plan_version(), or plan_open() will return PLAN_ERR_OPEN_BAD_VERSION.

typedef struct _PLAN_CONNECT_STRUCT {
                  unsigned char class; // no longer used
                  char dummy;
                  unsigned short port;
                  char name[10];
                                    } PLAN_CONNECT_STRUCT;

A PLAN_CONNECT_STRUCT describes a PicLan connection. The port field is the port number connected to. The name field is the name of the server connected to.

typedef void far * (*REALMEMALLOCFUNC)(unsigned long); typedef void (*REALMEMFREEFUNC)(void far *);

These two pointer-to-function type definitions are for the callback functions used for allocating real memory. They are designed to be compatible with standard farmalloc() and farfree() functions from the C library.

Function Calls

short pascal WINDEF plan_init_mem(unsigned short plcb_cnt,
                                  unsigned short buf_cnt,
                                  unsigned short plcb_start_no,
                                  unsigned short alloc_flag,
                                  REALMEMALLOCFUNC palloc);

Allocate a client handle for PicLan operations. The plcb_cnt parameter specifies the number of PLCB's desired. The buf_cnt parameter specifies the number of BUF's needed. The plcb_start_no parameter controls the number assigned to the first PLCB for this client - this client will have PLCB's numbered from plcb_start_no through plcb_start_no+plcb_cnt-1. The alloc_flag parameter controls how memory allocate is performed - see the PLAN_ALLOC_... constant definitions. The palloc parameter is a pointer to the function to be called for allocating real memory. Under Windows, or any time that real memory allocation should be disallowed, palloc should be NULL. Generally, farmalloc() will be passed in palloc for real memory allocation.

The return value is as follows:
<<0 = error code
>>=0 = handle for this instance

[MS-DOS] [Windows] [NLM]

short pascal WINDEF plan_term_mem(unsigned short handle,
                                  REALMEMFREEFUNC pfree);

Free a client handle. The handle parameter is the handle to be released. The pfree parameter is a pointer to the function to be called for deallocating real memory - under Windows, this should be NULL. In general, farfree() will be passed in pfree for real memory deallocation. This function must be called prior to program termination for every handle allocated by the program - failure to do so can cause a system crash. This function will call plan_close() for all open PLCB's. (Since this function closes any open PLCB's, it may take some time to execute. Programs should call plan_close() themselves, since doing so gives them the ability to display additional information to the user as each connection is closed.)

The return value is as follows:
<<0 = error code
>>=0 = handle for this instance

[MS-DOS] [Windows] [NLM]

unsigned long pascal plan_version(void);

This function returns the version number for the low-level packet protocol used by this library.

[MS-DOS] [Windows] [NLM]

short pascal plan_alloc_plcb(unsigned short handle,
                             unsigned short ibufs,
                             unsigned short obufs);

Allocate a PLCB from the pool. handle is the instance handle returned by plan_init(). ibufs is the number of buffers which should be allocated to the PLCB for input buffering. obufs is the number of buffers which should be allocated to the PLCB for output buffering. Both the PLCB and the BUF's are allocated from the pool created by the plan_init() function. The function returns a PLCB number (which may be any positive number, regardless of the number of PLCB's in the pool - the application must not make any assumptions about the range of numbers returned.)

The return value is as follows:
<<0 = error code
>>=0 = PLCB number

[MS-DOS] [Windows] [NLM]

void pascal plan_dealloc_plcb(unsigned short p_no);

Deallocate a PLCB back to the pool. p_no is the PLCB number returned by the plan_alloc_plcb() functions. If the PLCB is open, this function calls plan_close() to close the connection - in this case, this function may take some time to execute.

[MS-DOS] [Windows] [NLM]

short pascal plan_find_servers(unsigned short p_no,
                               const char far *server,
                               unsigned short far *cnt);

Query the network for a list of servers with certain capabilities, and buffer the responses. The PLCB p_no will be used for the query, and must be allocated but not in use. If server is NULL or points to a null string, all servers will be found; otherwise, only the server with the requested name will be found. (plan_find_servers() does not convert the string to uppercase, but current PicLan server naming conventions only allow uppercase letters to be used in server names.) The number of servers found will be copied to the location pointed to by cnt.

plan_find_servers() operates using an internal state machine, allowing the application to continue processing while the function performs the query. The function must be called until it returns a non-zero result code. Failure to continue calling it until a non-zero result code (even if plan_term() is used to closedown the PicLan workstation software) may leave other processes on the network in an unstable state. The PLCB used for the query may not be used for any other function call until this function returns a non-zero result.

plan_find_servers() operates most quickly when searching for a server with a specific name. If the application knows the name of the server, it should search for the server by name - this will be faster than searching for all servers, and then looking through the list of servers for the desired one.

Return values:
<<0 = error code
0 = not yet complete - continue calling
1 = query has finished; cnt has been filled in

[MS-DOS] [Windows] [NLM]

short pascal plan_find_servers_wait(unsigned short p_no,
                                    const char far *server,
                                    unsigned short far *cnt);

This function is identical to the plan_find_servers() function, except that it does not return until the funtion is entirely complete. That is, a single call may take some time to execute, and the return code will always be non-zero.

[MS-DOS] [NLM]

void pascal plan_get_server(unsigned short p_no,
                            unsigned short idx,
                            PLAN_SERVER_STRUCT far *pss);

Get one buffered server information structure. This function is called one or more times to retrieve the data found by plan_find_servers(). p_no is the PLCB used by the plan_find_servers() function - this PLCB must have been unused fromt the time of the completion of the plan_find_servers() function. idx is the zero-based index of the server information to be retrieved, and must be within the range of servers found by plan_find_servers(). The server information will be placed at the address pointer to by pss.

[MS-DOS] [Windows] [NLM]

short pascal plan_open(unsigned short p_no,
                       unsigned char p_type,
                       const PLAN_SERVER_STRUCT far *pss,
                       unsigned short host_channel_no,
                       unsigned short local_channel_no,
                       PLAN_CONNECT_STRUCT far *pcs);

Open a PLCB connection of a specified type. p_no is the PLCB number returned by a call to plan_alloc_plcb(). p_type is the type of connection desired - only PLAN_PLCB_TERM_NODE is currently supported. pss is the address of a PLAN_SERVER_STRUCT that contains information on the server being connected to - it is presumed that the structure was.initialized by the plan_get_server() function. host_channel_no is the port on the host on which a connection is desired - this is only defined for PLAN_PLCB_TERM_NODE connections; the value PLAN_OPEN_TERM_WILD may be used to open the first available port. local_channel_no will appear in status displays as the channel number on the workstation. pcs points to a structure which will be filled in with information on the connection.

plan_open() operates using an internal state machine, allowing the application to continue processing while the function performs the open. The function must be called until it returns a non-zero result code. Failure to continue calling it until a non-zero result code (even if plan_term() is used to closedown the PicLan workstation software) may leave other processes on the network in an unstable state. The PLCB used for the open may not be used for any other function call until this function returns a non-zero result.

Return values:
<<0 = error code
0 = not yet complete; continue calling
1 = success; pcs has been filled in

[MS-DOS] [Windows] [NLM]

short pascal plan_open_wait(unsigned short p_no,
                            unsigned char p_type,
                            const PLAN_SERVER_STRUCT far *pss,
                            unsigned short host_channel_no,
                            unsigned short local_channel_no,
                            PLAN_CONNECT_STRUCT far *pcs);

This function is identical to the plan_open() function, except that it does not return until the funtion is entirely complete. That is, a single call may take some time to execute, and the return code will always be non-zero.

[MS-DOS] [NLM]

short pascal plan_close(unsigned short p_no);

Close a PLCB connection. p_no is the PLCB for the connection being closed.

plan_close() operates using an internal state machine, allowing the application to continue processing while the function performs the close. The function must be called until it returns a non-zero result code. Failure to continue calling it until a non-zero result code (even if plan_term() is used to closedown the PicLan workstation software) may leave other processes on the network in an unstable state. The PLCB being closed may not be used for any other function call until this function returns a non-zero result.

Return values:
<<0 = error code
0 = not yet complete; continue calling
1 = success

[MS-DOS] [Windows] [NLM]

short pascal plan_close_wait(unsigned short p_no);

This function is identical to the plan_close() function, except that it does not return until the funtion is entirely complete. That is, a single call may take some time to execute, and the return code will always be non-zero.

[MS-DOS] [NLM]

short pascal plan_read(unsigned short p_no,
                       void far *buf,
                       unsigned short len);

Read from an open PLCB connection. p_no is the PLCB for the open connection being read from. buf is the address of the buffer where the data should be placed. len is the number of bytes requested. The function return value is the number of bytes actually read - this may be less than the number of bytes requested. If no data is available, the function returns immediately.

Return values:
<<0 = error code
>>=0 = number of bytes read

[MS-DOS] [Windows] [NLM]

short pascal plan_write(unsigned short p_no,
                        const void far *buf,
                        unsigned short len);

Write to an open PLCB connection. p_no is the PLCB for the open connection being written to. buf is the address of the data being written. len is the number of bytes to write. This function returns the number of bytes actually written - this may be less than the requested amount if the communications buffers become full.

Return values:
<<0 = error code
>>=0 = number of bytes written

[MS-DOS] [Windows] [NLM]

void pascal plan_break(unsigned short p_no);

Send a <<BREAK>> signal on an open PLCB terminal connection. p_no is the PLCB for the terminal connection on which the <<BREAK>> signal is sent. The results of sending a <<BREAK>> signal on a non-terminal connection are undefined.

[MS-DOS] [Windows] [NLM]

void pascal plan_xoff(unsigned short p_no,
                      short stop_flow);

Set the flow control state on an open PLCB terminal connection. p_no is the PLCB whose flow control is being set. stop_flow is the new flow control state: if it is zero, then the remote end of the connection is allowed to send data to this end; if it is non-zero, then the remote end of the connection may not send data to this end. If data flow is stopped, it will not be restarted except by the application again calling plan_xoff(), with a stop_flow value of zero. The results of using this function on a non-terminal connection are undefined.

[MS-DOS] [Windows] [NLM]

const char far * pascal plan_error_message(short error_code);

This function returns a pointer to a message string for the error code. error_code is the error code returned by another PicLan function.

Return value:
a pointer to a message string describing the error

[MS-DOS]

void pascal plan_error_message_win(short error_code,
                                   char far *error_message);

This function returns an error message string for the error code. error_code is the error code returned by another PicLan function, while error_message is the location the message should be stored. The error message will not exceed 255 characters in length.

[Windows]

short pascal plan_status(unsigned short p_no);

This function returns the status bit-field for the PLCB. p_no is the PLCB whose status is requested. The currently defined bit-fields are PLCB_STATUS_OPEN, PLCB_STATUS_BUSY, PLCB_STATUS_MORE_IN, and PLCB_STATUS_XOFF_OUT.

[MS-DOS] [Windows] [NLM]

short pascal plan_error_code(unsigned short p_no);

This function returns the error bit field for the PLCB. p_no is the PLCB whose error is requested. The particular return values are undefined.

[MS-DOS] [Windows] [NLM]

void pascal plan_save(unsigned short handle);

Save the state of the network system. This should be called prior to executing a DOS command - this will prevent network traffic from arriving while another command is shelled. It will also prevent the network system's timer ISR from being called.

[MS-DOS]

void pascal plan_restore(unsigned short handle);

Restore the state of the network system. This should be called after plan_save() has been used to stop network traffic.

[MS-DOS]

short pascal plan_read_avail(unsigned short p_no);

Returns the number of bytes available for reading.

Return value:
<<0 = error code
>>=0 = number of bytes

[MS-DOS] [Windows] [NLM]

short pascal plan_write_avail(unsigned short p_no);

Returns the number of bytes which will be accepted for writing.

Return value:
<<0 = error code
>>=0 = number of bytes

[MS-DOS] [Windows] [NLM]

short pascal plan_install_callback_win(unsigned short handle,
                                       unsigned short flags,
                                       HWND hwnd,
                                       unsigned short msg);

Installs or de-installs a windows callback message for this PicLan handle. 'handle' is the PicLan client handle returned from plan_init_mem(). 'flags' are bits that specify the types of callback events that are desired. The flags are defined in pllib.h. Most applications will use CALLBACK_ALL. 'hwnd' is the Windows handle where the callback message is to be directed. If 'hwnd' is null, then an existing callback assignment will be deleted. 'msg' is the Windows message that you wish to send and is usually a user-defined message number.

This routine is used to install an event-driven architechure for running PicLan without requiring that the application continually poll. The application's window proceedure will be called with messages indicating that network activity has occurred. The 'wp' parameter in the window's routine will indicate the PicLan 'p_no' that caused the activity. There is no indication of what type of activity caused the message.

When PicLan posts a message to Windows, it is not able to post a seperate message for each network event. To do so would swamp the Windows message queue and hang the Windows environment. For this reason, when PicLan posts a message it sets a flag that must be reset by the application before another message can be posted. This allows PicLan and your application to guarantee that only a single message will be posted at any one time preventing the Windows message queue from being swamped. Writing an event-driven application with PicLan involves a number of concepts that may be new to you.

The psuedo proceedure for handling events in a terminal emulator reading from a network connection would be:

static in_event_flag = 0;

plan_reset_callback_flag(hWnd);
if ( !in_event_flag ) {
  in_event_flag = 1;
  loop {
    res = plan_read(p_no,buf,sizeof(buf));
    if ( res << 0 ) {
      ... process error condition
    }
    if ( !res ) {
      break;
    }
    ... process data
    PeekMessage(&msg,hWnd,0,0,PM_NOREMOVE);
  }
}

If is the application's responsibility to install and de-install PicLan callbacks correctly. If you install a callback more than once for a particular PicLan handle, you will corrupt the data structure within PLAN.DLL. You must also de-install any callbacks prior to calling plan_term_mem().

Returns a success code:

Return value:
<<0 = error code

[Windows]

short pascal plan_reset_callback_flag(HWND hwnd);

This function is used to clear the callback "flag" maintained within PLAN.DLL that prevents PicLan from posting multiple messages to a window. You should call this function at the beginning of your Windows callback function so that additional callbacks can be processed.

Returns a success code:

Return value:
<<0 = error code

[Windows]

Error Codes

All error codes are returned as negative result codes from functions. The plan_error_msg() function may be used to retrieve a pointer to an error message string. These are the currently defined error results:

PLAN_ERR_INIT_NAME_CONFLICT   The name conflicts with another name.
PLAN_ERR_INIT_NO_ENET         No IPX.COM or ethernet adapter found.
PLAN_ERR_INIT_PLCB_MEM        Not enough memory to allocate PLCB's.
PLAN_ERR_INIT_BUF_MEM         Not enough memory to allocate BUF's.
PLAN_ERR_INIT_IPX_FAIL        Failed to initialize IPX subsystem.
PLAN_ERR_INIT_ENET_FAIL       Failed to initialize ethernet subsystem.
PLAN_ERR_ALLOC_NO_PLCB        No free PLCB's left.
PLAN_ERR_ALLOC_BUF_MEM        Not enough free BUF's left.
PLAN_ERR_INTERNAL             An internal error has occurred.
PLAN_ERR_INVALID_PARAM        An invalid parameter was passed to the function.
PLAN_ERR_OPEN_INTERNAL_OK     Internal Error condition.
PLAN_ERR_OPEN_INTERNAL_UNABLE Destination system is unable to host this type of connection
PLAN_ERR_OPEN_UNAVAILABLE     Destination port unavailable.
PLAN_ERR_OPEN_DENIED          Destination port unavailable due to PicLan licensing limits.
PLAN_ERR_OPEN_INTERNAL_OTHER  Internal Error condition.
PLAN_ERR_OPEN_NO_RESPONSE     The server is not responding.
PLAN_ERR_OPEN_BAD_VERSION     The server packet protocol version is different from the library's protocol version.
PLAN_ERR_OPEN_INSUF_BUFS      At least two inbound buffers must be allocated for terminal sessions.
PLAN_ERR_INIT_BAD_VERSION     Version conflict with resident PL-DEV.EXE
PLAN_ERR_INIT_CONFLICT        PLCB  number conflict with another PL-DEV.EXE client
PLAN_ERR_INIT_OVERFLOW        Too many PL-DEV.EXE clients
PLAN_ERR_INIT_NOT_PRESENT     PL-DEV.EXE is not present
PLAN_ERR_INIT_EMS             Error initializing EMS support code
PLAN_ERR_ALREADY_OPEN         The PLCB is already open

Example Programs

The DEMO.C program demonstrates a terminal session using the PicLan workstation library. It has been tested with all supported compilers and memory models. To create DEMO.EXE, simply compile DEMO.C, and link it with the appropriate PLLIB library. The example program built by DEMO.C, like all programs built with this SDK, requires that the PL-DEV.EXE TSR be loaded in order to run.