1

I am using the tutorial on this MSDN link to implement a way of transferring data from one process to another. Although I was advised in an earlier question to use the Pipe methods, due to certain constraints I have no choice but to use the CreateFileMapping method.

Now, i've succesfully managed to make two seperate window form projects within the same solution and by editing some properties both of the forms load at the same time.

Furthermore I have managed to implement the code given in the MSDN sample into the first (Producer) and second (Consumer) program without any compilation errors.

The problem I am having now is when I run the first program and try to create the handle to the mapped file, I am given an error saying it was unsuccesful and I do not understand why this is happening.

I have added both the Producer and Consumer code files to demonstrate what I am trying to do.

Producer:

#include <windows.h>
#include <stdio.h>
#include <conio.h>


//File header definitions
#define IDM_FILE_ROLLDICE 1
#define IDM_FILE_QUIT 2
#define BUF_SIZE 256

TCHAR szName[]=TEXT("Global\\MyFileMappingObject");
    TCHAR szMsg[]=TEXT("Message from first process!");

void AddMenus(HWND);
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);

////Standard windows stuff - omitted to save space.

//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{
    WCHAR buffer[256];
    LPCTSTR pBuf;

    struct DiceData storage;
    HANDLE hMapFile;

    switch(message)    
    {
    case WM_CREATE:
        {

            // Create Menus
            AddMenus(hMainWindow);
        }

        break;
    case WM_COMMAND:
        // Intercept menu choices
        switch(LOWORD(wParam))
        {
        case IDM_FILE_ROLLDICE:
            {
                //Roll dice and store results in variable
                //storage = RollDice();

                ////Copy results to buffer
                //swprintf(buffer,255,L"Dice 1: %d, Dice 2: %d",storage.dice1,storage.dice2);

                ////Show via message box
                //MessageBox(hMainWindow,buffer,L"Dice Result",MB_OK);

                hMapFile = CreateFileMapping(
                 (HANDLE)0xFFFFFFFF,    // 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) 
   { 
      MessageBox(hMainWindow,L"Could not create file mapping object",L"Error",NULL);
      return 1;
   }
   pBuf = (LPTSTR) MapViewOfFile(hMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,                   
                        0,                   
                        BUF_SIZE);           

   if (pBuf == NULL) 
   { 
      MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL);

       CloseHandle(hMapFile);

      return 1;
   }


   CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
    _getch();

   UnmapViewOfFile(pBuf);

   CloseHandle(hMapFile);

            }
            break;

        case IDM_FILE_QUIT:
            SendMessage(hMainWindow, WM_CLOSE, 0, 0);
            break;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }
    return DefWindowProc(hMainWindow, message, wParam, lParam);
}

//
//Setup menus
//

Consumer:

#include <windows.h>
#include <stdio.h>
#include <conio.h>

//File header definitions
#define IDM_FILE_QUIT 1
#define IDM_FILE_POLL 2

#define BUF_SIZE 256
TCHAR szName[]=TEXT("Global\\MyFileMappingObject");


//Prototypes
void AddMenus(HWND);
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM);

//More standard windows creation, again omitted.

//////////////////////
// WINDOWS FUNCTION //
//////////////////////
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
                            WPARAM wParam, LPARAM lParam)
{


    HANDLE hMapFile;
    LPCTSTR pBuf;

    switch(message)    
    {
    case WM_CREATE:
        {

            // Create Menus
            AddMenus(hMainWindow);
            break;
        }

    case WM_COMMAND:
        {
            // Intercept menu choices
            switch(LOWORD(wParam))
            {
            case IDM_FILE_POLL:
                {
                    hMapFile = OpenFileMapping(
                        FILE_MAP_ALL_ACCESS,   // read/write access
                        FALSE,                 // do not inherit the name
                        szName);               // name of mapping object 

                    if (hMapFile == NULL) 
                    { 
                        MessageBox(hMainWindow,L"Could not open file mapping object",L"Error",NULL);
                        return 1;
                    } 

                    pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object
                        FILE_MAP_ALL_ACCESS,  // read/write permission
                        0,                    
                        0,                    
                        BUF_SIZE);                   

                    if (pBuf == NULL) 
                    { 
                        MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL); 

                        CloseHandle(hMapFile);

                        return 1;
                    }

                    MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK);

                    UnmapViewOfFile(pBuf);

                    CloseHandle(hMapFile);

                    break;
                }




            case IDM_FILE_QUIT:
                SendMessage(hMainWindow, WM_CLOSE, 0, 0);
                break;
            }
            break;
        }

    case WM_DESTROY:
        {
            PostQuitMessage(0);
            break;
        }
    }
    return DefWindowProc(hMainWindow, message, wParam, lParam);
}

//
//Setup menus
//

It's by no means tidy and final but it's just a start, thanks for any help.

Edit: Error

Error Image

Edit2: Output

Output Image

Community
  • 1
  • 1
Jamie Keeling
  • 9,806
  • 17
  • 65
  • 102
  • One additional thing to watch for: it looks like your producer creates the mapping, maps, writes, then unmaps+closes. File map objects exists only while some process holds an open handle to it, so once producer closes its handle, *poof!* - the mapping is gone, and there won't be anything for consumer to open later. To use shared memory this way, at least one process needs to hold onto the memory long-term. For example, have the producer open and map the memory at the start of the process, and unmap/close at the end of the process: that way it will exist whenever the client looks for it. – BrendanMcK May 02 '12 at 09:27

4 Answers4

3

Ensure the Global name is unique; this can be done with a tool named Process Explorer.

If not unique, this would typically fail with Error code 6 (The handle is invalid) upon calling CreateFileMappinng

  1. Download Process Explorer from SysInternals
  2. Run Process Explorer
  3. Run your application up to a break point just prior to the CreateFileMapping() failure
  4. Search for MyFileMappingObject using Find (Ctrl-F)
  5. If anything comes up such as another FileMap, Mutex, etc.. consider a more unique name, and ensure your application is not the one creating it.

Note: Consider naming your FileMapping using a GUID (File -> Tools > Create GUID) within Visual Studio

Saxar
  • 474
  • 5
  • 5
3

Your code for the producer works for me. What version of Windows are you using? In newer versions (like Vista and 7) there are additional security restrictions placed on accessing shared memory. There is a note about this in the MSDN article you referenced above, saying that you must be an Administrator to create global shared memory objects in Windows Vista/7.

You should also make a call to GetLastError() to see which error code is actually returned from CreateFileMapping(), that may be helpful in determining the root cause of the problem.

WildCrustacean
  • 5,896
  • 2
  • 31
  • 42
  • I'm using Windows 7 at the moment, in terms of looking at the GetLastError could I simply create a buffer, call the GetLastError and then display that to the MessageBox? – Jamie Keeling Apr 15 '10 at 18:18
  • GetLastError() just returns a DWORD status code (that you can look up in the System Error Code list on MSDN to find the message). You could either display it with a MessageBox or if you have a debugger set up you could view the value by stepping through the program. – WildCrustacean Apr 15 '10 at 18:25
  • I've tried using "FILE_MAP_ALL_ACCESS" but it doesn't make any difference. – Jamie Keeling Apr 15 '10 at 18:54
  • Is it the call to CreateFileMapping() that fails or MapViewOfFile()? What code did you get back from GetLastError()? – WildCrustacean Apr 15 '10 at 19:27
  • The error code returned from GetLastError is "3435973836". Looking at the list of errors on MSDN doesn't even go up that high which is very strange, I've added a screenshot of how I'm getting it. – Jamie Keeling Apr 15 '10 at 19:41
  • It looks like that number is just garbage, you have to actually step over the GetLastError() function to see the real value. – WildCrustacean Apr 15 '10 at 20:25
  • My mistake, It's 998 (ERROR_NOACCESS - Invalid access to memory location.) – Jamie Keeling Apr 15 '10 at 22:00
  • I bet that the problem is the security restriction on global shared memory in Windows 7 then. Does your user have administrator privileges? – WildCrustacean Apr 15 '10 at 22:25
  • Yes I am the only user and I am running it as admin, I have disabled UAC. – Jamie Keeling Apr 15 '10 at 22:49
  • I am running the 64-bit edition of Windows 7 though, would it make much of a difference? – Jamie Keeling Apr 16 '10 at 11:49
  • I wouldn't think 64-bit would make a difference. You may have to read up on the LPSECURITY_ATTRIBUTES parameter to CreateFileMapping, maybe that needs to be configured. The only other thing I can think of would be to see if you can use Local\\ or Session\\ instead of Global\\, if that would work for your purposes. – WildCrustacean Apr 16 '10 at 13:25
  • Hmm, I've tried Local and Session instead but with no success. Also for some reason I occasionally get an error saying "Access violation reading location" when I try to create the CreateFileMapping, it points to the DispatchMessage() of the Producer message loop. – Jamie Keeling Apr 16 '10 at 13:39
  • After changing the attribute to NULL it works, at first I encountered an error on the consumer side but that was because I was accidentally closing the file after it worked passed the if statements. Now when the consumer reads it the message displayed is "M" and not the message originally created in producer. Is it some sort of conversion issue? – Jamie Keeling Apr 16 '10 at 14:18
  • Yeah, that sounds like a char/wchar conversion issue with MessageBox and pBuf. Maybe try using LPCWSTR? I am not totally sure what the right thing to do there is. You could probably verify that the data in pBuf is right with the debugger too. – WildCrustacean Apr 16 '10 at 14:47
  • I changed both of the buffers to LPCWSTR and there is no affect on the output on the message box. I'm not sure the correct data is being given though, I've attatched another image. – Jamie Keeling Apr 16 '10 at 15:44
  • Try changing LPTSTR to LPTWSTR when you cast the return value from MapViewOfFile. – WildCrustacean Apr 16 '10 at 16:23
  • Changing that still results in the same result "M", very strange =S – Jamie Keeling Apr 16 '10 at 16:33
  • That is strange, I'm not sure what the problem is then. – WildCrustacean Apr 16 '10 at 17:25
  • I've decided to make another question as it seems to be a separate issue, thank you very much for the help! Edit: Forgot to add #include , oops! Works fine now. – Jamie Keeling Apr 17 '10 at 21:02
1

Maybe we learned from the same material/examples in the past. I had the same problem after migrating from XP to Windows 7:

NULL Handle return value and GetLastError() = 5.

ERROR_ACCESS_DENIED
    5 (0x5)
    Access is denied.

System Error Codes (0-499): http://msdn.microsoft.com/en-us/library/ms681382.aspx

I used a lpName with backslashes like in the Microsoft example from http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx that you posted above. After changing the name of the file mapping object (lpName) from "Global\MyFileMappingObject" to "GlobalMyFileMappingObject", the CreateFileMapping function works again under Windows 7 with no other changes.

"The name can have a "Global\" or "Local\" prefix to explicitly create the object in the global or session namespace. The remainder of the name can contain any character except the backslash character ('\'). Creating a file mapping object in the global namespace from a session other than session zero requires the SeCreateGlobalPrivilege privilege. For more information, see Kernel Object Namespaces".

This is not just a name-change! If you need access to the global namespace, then you have to go the SeCreateGlobalPrivilege way.

Jedzia
  • 116
  • 1
  • 6
0

Under Windows 7 I found:

OpenFileMapping(FILE_MAP_ALL_ACCESS, ...);

Causes issues with:

CreateFileMapping(
                 (HANDLE)0xFFFFFFFF,    // use paging file

Try:

OpenFileMappingA(SECTION_MAP_WRITE | SECTION_MAP_READ,...);