Example (_rmem_term -- Terminate Memory Functions for Subsystem DLL)

This example shows the _DLL_InitTerm function from the IBM C and C++ Compilers sample program for building subsystem DLLs, which calls _rmem_term to terminate the library memory functions.

/******************************************************************************/
/* 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;
   }