shared memory creation failure: I can not create global shared memory with createFIleMapping

yuji suda 20 Reputation points
2024-12-02T05:37:07.8833333+00:00

Recently I tried to use shared memory of windows OS. I followed Creating Named Shared Memory section. In order to create global shared memory, SeCreateGlobalPrivilege must be needed. But I could not find how to do it.

Given source is as follows. How can I set the SeCreateGloblPrivilege in this source?

#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <tchar.h>
#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
TCHAR szMsg[]=TEXT("Message from first process.");
int _tmain()
{
   HANDLE hMapFile;
   LPCTSTR pBuf;
   hMapFile = CreateFileMapping(
                 INVALID_HANDLE_VALUE,    // use paging file
                 NULL,                    // default security
                 PAGE_READWRITE,          // read/write access
                 0,                       // maximum object size (high-order DWORD)
                 BUF_SIZE,                // maximum object size (low-order DWORD)
                 szName);                 // name of mapping object
   if (hMapFile == NULL)
   {
      _tprintf(TEXT("Could not create file mapping object (%d).\n"),
             GetLastError());
      return 1;
   }
   pBuf = (LPTSTR) MapViewOfFile(hMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,
                        0,
                        BUF_SIZE);
   if (pBuf == NULL)
   {
      _tprintf(TEXT("Could not map view of file (%d).\n"),
             GetLastError());
       CloseHandle(hMapFile);
      return 1;
   }
   CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();
   UnmapViewOfFile(pBuf);
   CloseHandle(hMapFile);
   return 0;
}

Best regards

Yuji Suda

Windows development Windows API - Win32
{count} votes

Accepted answer
  1. RLWA32 49,536 Reputation points
    2024-12-02T12:39:38.5866667+00:00

    I suspect the error you experienced was access denied (5) instead of file not found (2). This would be because the default security descriptor created by the process running as an Administrator does not grant access to the account under which your second process (the client) is running.

    I modified your first posted code to adjust the default security descriptor to grant Full Control to the Everyone group. Now your client process should produce the expected results. I only used the Everyone group and Full Control to illustrate how to modify the security descriptor. In real life you would probably want to make a more restrictive modification.

    #include <windows.h>
    #include <AclAPI.h> // Added by RLWA32
    #include <stdio.h>
    #include <conio.h>
    #include <tchar.h>
    #define BUF_SIZE 256
    TCHAR szName[] = TEXT("Global\\MyFileMappingObject");
    TCHAR szMsg[] = TEXT("Message from first process.");
    int _tmain()
    {
        HANDLE hMapFile;
        LPCTSTR pBuf;
        EXPLICIT_ACCESS ea{}; // Added by RLWA32
        PSECURITY_DESCRIPTOR pSD{}; // Added by RLWA32
        PACL pDacl{}, pNewDacl{}; // Added by RLWA32
    
        hMapFile = CreateFileMapping(
            INVALID_HANDLE_VALUE,    // use paging file
            NULL,                    // default security
            PAGE_READWRITE,          // read/write access
            0,                       // maximum object size (high-order DWORD)
            BUF_SIZE,                // maximum object size (low-order DWORD)
            szName);                 // name of mapping object
        if (hMapFile == NULL)
        {
            _tprintf(TEXT("Could not create file mapping object (%d).\n"),
                GetLastError());
            return 1;
        }
    
        // Add permission for Everyone Group to access shared memory
        ea.grfAccessMode = SET_ACCESS;
        ea.grfAccessPermissions = GENERIC_ALL;
        ea.grfInheritance = NO_INHERITANCE;
        ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
        ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
        ea.Trustee.ptstrName = (LPTSTR) TEXT("Everyone");
    
        DWORD result = GetNamedSecurityInfo(szName, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD);
        if (result != ERROR_SUCCESS)
        {
            _tprintf(TEXT("GetNamedSecurityInfo failed with %d.\n"), result);
            return 1;
        }
    
        result = SetEntriesInAcl(1, &ea, pDacl, &pNewDacl);
        if (result != ERROR_SUCCESS)
        {
            _tprintf(TEXT("SetEntriesInAcl failed with %d.\n"), result);
            return 1;
        }
    
        result = SetNamedSecurityInfo(szName, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewDacl, NULL);
        if (result != ERROR_SUCCESS)
        {
            _tprintf(TEXT("SetNamedSecurityInfo failed with %d.\n"), result);
            return 1;
        }
    
        LocalFree(pNewDacl);
        LocalFree(pSD);
    
        // End of Additions by RLWA32
    
        pBuf = (LPTSTR)MapViewOfFile(hMapFile,   // handle to map object
            FILE_MAP_ALL_ACCESS, // read/write permission
            0,
            0,
            BUF_SIZE);
        if (pBuf == NULL)
        {
            _tprintf(TEXT("Could not map view of file (%d).\n"),
                GetLastError());
            CloseHandle(hMapFile);
            return 1;
        }
        CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
        _getch();
        UnmapViewOfFile(pBuf);
        CloseHandle(hMapFile);
        return 0;
    }
    

2 additional answers

Sort by: Most helpful
  1. Jeanine Zhang-MSFT 11,356 Reputation points Microsoft External Staff
    2024-12-02T07:19:51.3766667+00:00

    Hi

    Welcome to Microsoft Q&A!

    According to the Doc:Creating Named Shared Memory

    Prefixing the file mapping object names with "Global" allows processes to communicate with each other even if they are in different terminal server sessions. This requires that the first process must have the SeCreateGlobalPrivilege privilege.

    I suggest you could try to use OpenProcessToken() and AdjustTokenPrivileges() to enable the SeCreateGlobalPrivilege privilege for the calling process before calling CreateFileMapping().

    For more details you could refer to the Doc: Enabling and Disabling Privileges in C++

    SE_CREATE_GLOBAL_NAME TEXT("SeCreateGlobalPrivilege"): Required to create named file mapping objects in the global namespace during Terminal Services sessions. This privilege is enabled by default for administrators, services, and the local system account.

    I suggest you need to make sure your application has the necessary permissions and is running with appropriate privileges.

    Jeanine

    Thank you

    1 person found this answer helpful.

  2. yuji suda 20 Reputation points
    2024-12-03T07:39:14.2166667+00:00

    Hi RLWA32

    I have noticed in your console screen shot that one is administrator console running globaltest.exe and the other is user console running globalclient.exe showing process2 message box.

    The very point is that GlobalTest.exe must be running through out servicing the shared memory that created!

    I have just repeated a similar condition on my desktop!

    Now I've got the idea on how to use shared memory with CreateFileMapping!

    Thanks a lot.

    Yuji Suda


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.