DosExitList

Keeps a list of routines that run when the current process ends.

Syntax
DosExitList (ordercode, pfn)

Parameters

 * ordercode (ULONG) - input : DosExitList action and invocation order.
 * ordercode contains two one-byte fields in the low-order word. The high-order word is zero.
 * The low-order byte of the low-order word indicates which action DosExitList performs. This function can update the list of routines or transfer to the next address on the termination list at the completion of a routine. The values of the byte and their meanings are as follows:
 * 1 EXLST_ADD Add an address to the termination list.
 * 2 EXLST_REMOVE Remove an address from the termination list.
 * 3 EXLST_EXIT When termination processing completes, transfer to the next address on the termination list.

The high-order byte of the low-order word indicates the invocation order. This value is valid only when the low-order byte is 1 (add an address). For the other low-order byte values, the high-order byte of the low-order word must be set to zero.

The invocation order indicates where the routine address is to be placed in an ordered list. This list determines the order in which the exit list routines are invoked. Routines with a value of 0 are invoked first, and routines with a value of 255 are invoked last. If more than one routine is added with the same invocation order value, the last routine to be added is invoked first. The following values are used by OS/2 components: 0x80 - 0x88       OS/2 Extended Edition Database Manager 0x90 - 0x98       OS/2 Extended Edition Communications Manager 0xA0 - 0xA8       OS/2 Presentation Manager 0xB0              OS/2 Keyboard (KBD) component 0xC0              OS/2 Video (VIO) component 0xD0              OS/2 Interprocess Communication (IPC) Queues component
 * pfn (PFNEXITLIST) - input : The address of a routine to be run.

Return Code
ulrc (APIRET) - returns DosExitList returns one of the following values:
 * 0  NO_ERROR
 * 1  ERROR_INVALID_FUNCTION
 * 8  ERROR_NOT_ENOUGH_MEMORY
 * 13 ERROR_INVALID_DATA

Remarks
DosExitList is issued to define a routine that is to be given control when a process completes its execution. Multiple routines may be defined to receive control when a process is ending. For each process, the operating system maintains a list of addresses of defined exit list routines.

When the process is ending, the operating system transfers control to each address in this list. If there are multiple addresses in the list, they will each get control in numerical order by function invocation order, that is, low (0) will be first, and high (0xFF) will be last. In case of duplicate entries for the same value, the routines will be run in LIFO (last in, first out) order.

Library modules can issue DosExitList to free resources or to clear flags and semaphores in case the client process ends without notifying them.

Before transferring control to the routines in the termination list, the operating system resets the stack to its initial value. The routine must be in the address space of the ending process. The termination routine should perform its processing and then issue DosExitList with a value of 3 (EXLST_EXIT) for ordercode. The termination routine should be as short as possible.

Most system functions are allowed in an exit list routine. However, DosCreateThread and DosExecPgm are not.

An exit list routine must not call functions that have a better function order priority (that is, a lower value for ordercode) than itself. For example, an exit list routine with a function order value of 0x9A can use Presentation Services functions but not Communications Manager functions.

When the exit list routine receives control, the first parameter on the stack (located at ESP+4) contains a termination code that describes why the process ended. The values of the termination codes are as follows: 0 TC_EXIT       Normal exit 1 TC_HARDERROR  Hard-error halt 2 TC_TRAP       Trap operation for a 16-bit child process 3 TC_KILLPROCESS Unintercepted DosKillProcess 4 TC_EXCEPTION  Exception operation for a 32-bit child process When the exit list routine receives control, all system semaphores owned by the process have their ownership transferred to the thread that performs exit list processing. This allows the thread to request serialization semaphores without danger of blocking in case the semaphore was held by another thread in the process that has already ended.

Note: All exit list routines must be declared as VOID APIENTRY. This ensures the integrity of the stack.

Example Code
This example adds an exit routine named "ExitRtn1" to the exit-list sequence. Routines in this sequence must use DosExitList instead of DosExit to end. 
 * 1) define INCL_DOSPROCESS             /* Process and thread values */
 * 2) define INCL_DOSERRORS              /* DOS error values          */
 * 3) include 
 * 4) include 

VOID APIENTRY ExitRtn1(VOID);       /* Our exit routine */

int main(VOID) {

APIRET rc = NO_ERROR;

rc = DosExitList(EXLST_ADD            /* Add to exit-list sequence     */                     | 0x00002A00,         /* Invocation order is 42 (0x2A) */                     (PFNEXITLIST) ExitRtn1); /* Specify added exit routine */

if (rc != NO_ERROR) { printf("DosExitList error: return code = %u\n", rc); return 1; }

printf("Routine main ends...\n");

return NO_ERROR; }

/* All exit list routines must be declared as VOID APIENTRY. This ensures the integrity of the stack. */

VOID APIENTRY ExitRtn1(VOID) {   APIRET  erc = NO_ERROR;                     /* Return code */

printf("... but ExitRtn1 runs last.\n");

/* Might want to save data or close files here */

erc = DosExitList(EXLST_EXIT,              /* Exit         */                      (PFNEXITLIST) NULL);

if (erc != NO_ERROR) { printf("DosExitList error: return code = %u\n", erc); }

return; } 

Related Functions

 * DosCreateThread
 * DosExecPgm
 * DosExit
 * DosKillProcess
 * DosKillThread