Windows Dynamic-Link Libraries 9

 

 

 

 

 

Using Shared Memory in a Dynamic-Link Library Example

 

The following example demonstrates how the DLL entry-point function can use a file-mapping object to set up memory that can be shared by processes that load the DLL. The shared DLL memory persists only as long as the DLL is loaded. Applications can use the SetSharedMem() and GetSharedMem() functions to access the shared memory.

 

DLL that Implements the Shared Memory

 

The example uses file mapping to map a block of named shared memory into the virtual address space of each process that loads the DLL. To do this, the entry-point function must:

 

  1. Call the CreateFileMapping() function to get a handle to a file-mapping object. The first process that loads the DLL creates the file-mapping object. Subsequent processes open a handle to the existing object.
  2. Call the MapViewOfFile() function to map a view into the virtual address space. This enables the process to access the shared memory.

 

Note that while you can specify default security attributes by passing in a NULL value for the lpAttributes parameter of CreateFileMapping(), you may choose to use a SECURITY_ATTRIBUTES structure to provide additional security.

Create a new empty Win32 console application project. Give a suitable project name and change the project location if needed.

 

Using Shared Memory in a Dynamic-Link Library Example: Creating new Win32 C++ console application project in Visual C++ .NET

 

Then, add the source file and give it a suitable name.

 

Using Shared Memory in a Dynamic-Link Library Example: Adding new C++ source file for C++ source code to the existing C++ project

 

Next, add the following source code.

 

// The DLL code

#include <windows.h>

#include <memory.h>

 

#define SHMEMSIZE 4096

 

static LPVOID lpvMem = NULL;      // pointer to shared memory

static HANDLE hMapObject = NULL;  // handle to file mapping

 

// The DLL entry-point function sets up shared memory using a

// named file-mapping object.

BOOL WINAPI DllMain(HINSTANCE hinstDLL,  // DLL module handle

    DWORD fdwReason,              // reason called

    LPVOID lpvReserved)           // reserved

{

    BOOL fInit, fIgnore;

 

    switch (fdwReason)

    {

          // DLL load due to process initialization or LoadLibrary

          case DLL_PROCESS_ATTACH:

 

            // Create a named file mapping object

            hMapObject = CreateFileMapping(

                INVALID_HANDLE_VALUE,   // use paging file

                NULL,                   // default security attributes

                PAGE_READWRITE,         // read/write access

                0,                      // size: high 32-bits

                SHMEMSIZE,              // size: low 32-bits

                L"dllmemfilemap"); // name of map object

            if (hMapObject == NULL)

                return FALSE;

 

            // The first process to attach initializes memory

            fInit = (GetLastError() != ERROR_ALREADY_EXISTS);

 

            // Get a pointer to the file-mapped shared memory

            lpvMem = MapViewOfFile(

                hMapObject,     // object to map view of

                FILE_MAP_WRITE, // read/write access

                0,              // high offset:  map from

                0,              // low offset:   beginning

                0);             // default: map entire file

            if (lpvMem == NULL)

                return FALSE;

 

            // Initialize memory if this is the first process

            if (fInit)

                memset(lpvMem, '\0', SHMEMSIZE);

 

            break;

 

        // The attached process creates a new thread

        case DLL_THREAD_ATTACH:

            break;

 

        // The thread of the attached process terminates

        case DLL_THREAD_DETACH:

            break;

 

        // DLL unload due to process termination or FreeLibrary

        case DLL_PROCESS_DETACH:

 

            // Unmap shared memory from the process's address space

            fIgnore = UnmapViewOfFile(lpvMem);

 

            // Close the process's handle to the file-mapping object

            fIgnore = CloseHandle(hMapObject);

 

            break;

 

        default:

          break;

     }

 

    return TRUE;

    UNREFERENCED_PARAMETER(hinstDLL);

    UNREFERENCED_PARAMETER(lpvReserved);

}

 

// The export mechanism used here is the __declspec(export)

// method supported by Microsoft Visual Studio, but any

// other export method supported by your development

// environment may be substituted.

#ifdef __cplusplus    // If used by C++ code,

extern "C" {          // we need to export the C interface

#endif

 

// SetSharedMem sets the contents of the shared memory

__declspec(dllexport) void SetSharedMem(LPWSTR lpszBuf)

{

    LPWSTR lpszTmp;

    DWORD dwCount=1;

 

    // Get the address of the shared memory block

    lpszTmp = (LPWSTR) lpvMem;

 

    // Copy the null-terminated string into shared memory

    while (*lpszBuf && dwCount<SHMEMSIZE)

    {

        *lpszTmp++ = *lpszBuf++;

        dwCount++;

    }

    *lpszTmp = '\0';

}

 

// GetSharedMem gets the contents of the shared memory

__declspec(dllexport) void GetSharedMem(LPWSTR lpszBuf, DWORD cchSize)

{

    LPWSTR lpszTmp;

 

    // Get the address of the shared memory block

    lpszTmp = (LPWSTR) lpvMem;

 

    // Copy from shared memory into the caller's buffer

    while (*lpszTmp && --cchSize)

        *lpszBuf++ = *lpszTmp++;

    *lpszBuf = '\0';

}

#ifdef __cplusplus

}

#endif

 

Build and run the project. The generated DLL is ready to be used as shown in the following screenshot.

 

Using Shared Memory in a Dynamic-Link Library Example: The generated DLL and LIB file

 

Shared memory can be mapped to a different address in each process. For this reason, each process has its own instance of lpvMem, which is declared as a global variable so that it is available to all DLL functions. The example assumes that the DLL global data is not shared, so each process that loads the DLL has its own instance of lpvMem. Note that the shared memory is released when the last handle to the file-mapping object is closed. To create persistent shared memory, you would need to ensure that some process always has an open handle to the file-mapping object.

 

 

 

 

< Windows Dynamic Link Library 8 | Windows Dynamic Link Library | Win32 Programming | Windows Dynamic Link Library 10 >