Example 1
This example shows the _DLL_InitTerm function from the IBM C and
C++ Compilers sample program for building DLLs.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* _CRT_init is the C run-time environment initialization function. */
/* It will return 0 to indicate success and -1 to indicate failure. */
extern int _IMPORT _CRT_init(void);
/* _CRT_term is the C run-time environment termination function. */
extern void _IMPORT _CRT_term(void);
size_t _Export nSize;
int *_Export pArray;
/* _DLL_InitTerm is the function that gets called by the operating system */
/* loader when it loads and frees this DLL for each process that accesses */
/* this DLL. However, it only gets called the first time the DLL is loaded */
/* and the last time it is freed for a particular process. The system */
/* linkage convention MUST be used because the operating system loader is */
/* calling this function. */
unsigned long __stdcall _DLL_InitTerm(unsigned long hModule, unsigned long
ulFlag, long * dummy)
{
size_t i;
int rc;
char namebuf[MAX_PATH];
/* If ulFlag is DLL_PROCESS_ATTACH then the DLL is being loaded so initialization should*/
/* be performed. If ulFlag is DLL_PROCESS_DETACH then the DLL is being freed so */
/* termination should be performed. */
switch (ulFlag) {
case DLL_PROCESS_ATTACH :
/*******************************************************************/
/* The C run-time environment initialization function must be */
/* called before any calls to C run-time functions that are not */
/* inlined. */
/*******************************************************************/
if (_CRT_init() == -1)
return 0UL;
if ((rc = GetModuleFileName((void *)hModule, namebuf, sizeof namebuf)) == 0)
printf("GetModuleFileName returned %lu\n", GetLastError());
else
printf("The name of this DLL is %s\n", namebuf);
srand(17);
nSize = (rand()%128)+32;
printf("The array size for this process is %u\n", nSize);
if ((pArray = malloc(nSize *sizeof(int))) == NULL) {
printf("Could not allocate space for unsorted array.\n");
return 0UL;
}
for (i = 0; i < nSize; ++i)
pArray[i] = rand();
break;
case DLL_PROCESS_DETACH :
printf("The array will now be freed.\n");
free(pArray);
_CRT_term();
break;
default :
printf("ulFlag = %lu\n", ulFlag);
return 0UL;
}
/* A non-zero value must be returned to indicate success. */
return 1UL;
}
Example 2
The following example shows the _DLL_InitTerm function from the
IBM C and C++ Compilers sample for building subsystem DLLs.
/******************************************************************************/
/* This example provides 5 external entrypoints of which 2 are exported for */
/* use by client processes. The entrypoints are: */
/* */
/* _DLL_InitTerm - Initialization/Termination function for the DLL that is */
/* invoked by the loader. When the /Ge- compile option is */
/* used the linker is told that this is the function to */
/* execute when the DLL is first loaded and last freed for */
/* each process. */
/* */
/* DLLREGISTER - Called by _DLL_InitTerm for each process that loads the */
/* DLL. */
/* */
/* DLLINCREMENT - Accepts a count from its client and adds this value to */
/* the process and system totals. */
/* */
/* DLLSTATS - Dumps process and system totals on behalf of its client. */
/* */
/* DLLDEREGISTER- Called by _DLL_InitTerm for each process that frees the */
/* DLL. */
/* */
/******************************************************************************/
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#include <stdio.h>
#include "sample05.h"
extern int _IMPORT _rmem_init(void);
extern void _IMPORT _rmem_term(void);
static unsigned long DLLREGISTER( void );
static unsigned long DLLDEREGISTER( void );
#define SHARED_SEMAPHORE_NAME "DLL.LCK"
/* The following data will be per-process data. It will not be shared among */
/* different processes. */
static HANDLE hmtxSharedSem; /* Shared semaphore */
static unsigned long ulProcessTotal; /* Total of increments for a process */
static DWORD pid; /* Process identifier */
/* This is the global data segment that is shared by every process. */
#pragma data_seg( GLOBAL_SEG )
static unsigned long ulProcessCount; /* total number of processes */
static unsigned long ulGrandTotal; /* Grand total of increments */
/* _DLL_InitTerm() - called by the loader for DLL initialization/termination */
/* This function must return a non-zero value if successful and a zero value */
/* if unsuccessful. */
unsigned long __stdcall _DLL_InitTerm( HINSTANCE hModule,
DWORD ulFlag, LPVOID dummy)
{
ULONG rc;
/* If ulFlag is DLL_PROCESS_ATTACH then initialization is required: */
/* If the shared memory pointer is NULL then the DLL is being loaded */
/* for the first time so acquire the named shared storage for the */
/* process control structures. A linked list of process control */
/* structures will be maintained. Each time a new process loads this */
/* DLL, a new process control structure is created and it is inserted */
/* at the end of the list by calling DLLREGISTER. */
/* */
/* If ulFlag is DLL_PROCESS_DETTACH then termination is required: */
/* Call DLLDEREGISTER which will remove the process control structure */
/* and free the shared memory block from its virtual address space. */
switch( ulFlag )
{
case DLL_PROCESS_ATTACH:
_rmem_init();
if ( !ulProcessCount )
{
/* Create the shared mutex semaphore. */
if (( hmtxSharedSem = CreateMutex(NULL,
FALSE,
SHARED_SEMAPHORE_NAME)) == NULL)
{
printf( "CreateMutex rc = %lu\n", GetLastError() );
return FALSE;
}
}
/* Register the current process. */
if ( DLLREGISTER( ) )
return FALSE;
break;
case DLL_PROCESS_DETACH:
/* De-register the current process. */
if ( DLLDEREGISTER( ) )
return 0;
_rmem_term();
break;
default:
return 0;
}
/* Indicate success. Non-zero means success!!! */
return TRUE;
}
/* DLLREGISTER - Registers the current process so that it can use this */
/* subsystem. Called by _DLL_InitTerm when the DLL is first */
/* loaded for the current process. */
static unsigned long DLLREGISTER( void )
{
unsigned long rc;
/* Get the process id */
pid = GetCurrentProcessId();
/* Open the shared mutex semaphore for this process. */
if ( ( hmtxSharedSem = OpenMutex(SYNCHRONIZE,
TRUE,
SHARED_SEMAPHORE_NAME ) ) == NULL)
{
printf( "OpenMutex rc = %lu\n", rc = GetLastError() );
return rc;
}
/* Acquire the shared mutex semaphore. */
if ( WaitForSingleObject( hmtxSharedSem,
INFINITE ) == 0xFFFFFFFF )
{
printf( "WaitFor SingleObject rc = %lu\n", rc = GetLastError() );
CloseHandle( hmtxSharedSem );
return rc;
}
/* Increment the count of processes registered. */
++ulProcessCount;
/* Initialize the per-process data. */
ulProcessTotal = 0;
/* Tell the user that the current process has been registered. */
printf( "\nProcess %lu has been registered.\n\n", pid );
/* Release the shared mutex semaphore. */
if ( ReleaseMutex( hmtxSharedSem ) == FALSE )
{
printf( "ReleaseMutex rc = %lu\n", rc = GetLastError() );
return rc;
}
return 0;
}
/* DLLINCREMENT - Increments the process and global totals on behalf of the */
/* calling program. */
int _Export DLLINCREMENT( int incount )
{
unsigned long rc; /* return code from DOS APIs */
/* Acquire the shared mutex semaphore. */
if ( WaitForSingleObject( hmtxSharedSem,
INFINITE ) == 0xFFFFFFFF )
{
printf( "WaitForSingleObject rc = %lu\n", rc = GetLastError());
return rc;
}
/* Increment the counts the process and grand totals. */
ulProcessTotal += incount;
ulGrandTotal += incount;
/* Tell the user that the increment was successful. */
printf( "\nThe increment for process %lu was successful.\n\n", pid );
/* Release the shared mutex semaphore. */
if ( ReleaseMutex( hmtxSharedSem ) == FALSE )
{
printf( "ReleaseMutex rc = %lu\n", rc = GetLastError() );
return rc;
}
return 0;
}
/* DLLSTATS - Prints process and grand totals. */
int _Export DLLSTATS( void )
{
unsigned long rc;
/* Acquire the shared mutex semaphore. */
if ( WaitForSingleObject( hmtxSharedSem,
INFINITE ) == 0xFFFFFFFF )
{
printf( "WaitForSingleObject rc = %lu\n", rc = GetLastError());
return rc;
}
/* Print out per-process and global information. */
printf( "\nCurrent process identifier = %lu\n", pid );
printf( "Current process total = %lu\n", ulProcessTotal );
printf( "Number of processes registered = %lu\n", ulProcessCount );
printf( "Grand Total = %lu\n\n", ulGrandTotal );
/* Release the shared mutex semaphore. */
if ( ReleaseMutex( hmtxSharedSem ) == FALSE )
{
printf( "ReleaseMutex rc = %lu\n", rc = GetLastError() );
return rc;
}
return 0;
}
/* DLLDEREGISTER - Deregisters the current process from this subsystem. */
/* Called by _DLL_InitTerm when the DLL is freed for the */
/* last time by the current process. */
static unsigned long DLLDEREGISTER( void )
{
unsigned long rc;
/* Acquire the shared mutex semaphore. */
if ( ( rc = WaitForSingleObject( hmtxSharedSem,
INFINITE ) ) == 0xFFFFFFFF )
{
printf( "WaitForSingleObject rc = %lu\n", GetLastError());
return rc;
}
/* Decrement the count of processes registered. */
--ulProcessCount;
/* Tell the user that the current process has been deregistered. */
printf( "\nProcess %lu has been deregistered.\n\n", pid );
/* Release the shared mutex semaphore. */
if ( ReleaseMutex( hmtxSharedSem ) == FALSE )
{
printf( "ReleaseMutex rc = %lu\n", rc= GetLastError() );
return rc;
}
/* Close the shared mutex semaphore for this process. */
if ( CloseHandle( hmtxSharedSem ) == FALSE )
{
printf( "CloseHandle rc = %lu\n", rc = GetLastError() );
return rc;
}
return 0;
}