tags:

views:

285

answers:

2

Hello,

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

+1  A: 

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.

bde
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
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.
bde
I've tried using "FILE_MAP_ALL_ACCESS" but it doesn't make any difference.
Jamie Keeling
Is it the call to CreateFileMapping() that fails or MapViewOfFile()? What code did you get back from GetLastError()?
bde
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
It looks like that number is just garbage, you have to actually step over the GetLastError() function to see the real value.
bde
My mistake, It's 998 (ERROR_NOACCESS - Invalid access to memory location.)
Jamie Keeling
I bet that the problem is the security restriction on global shared memory in Windows 7 then. Does your user have administrator privileges?
bde
Yes I am the only user and I am running it as admin, I have disabled UAC.
Jamie Keeling
I am running the 64-bit edition of Windows 7 though, would it make much of a difference?
Jamie Keeling
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.
bde
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
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
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.
bde
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
Try changing LPTSTR to LPTWSTR when you cast the return value from MapViewOfFile.
bde
Changing that still results in the same result "M", very strange =S
Jamie Keeling
That is strange, I'm not sure what the problem is then.
bde
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 <tchar.h>, oops! Works fine now.
Jamie Keeling
+1  A: 

In the code for producer, is _getch() intended for non-console application as well?

ideamonk
Well spotted, no idea how that got in there. I think the sample I was basing it off from the MSDN article was to be used with a console application and I must of forgotten to remove it.
Jamie Keeling