Click here to Skip to main content
15,884,425 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I wrote an app that has been running on Windows XP for years with no issues.
Now I have to port it over to Win7.

The app includes a Windows Service that I wrote in C. The service runs under the LOCAL SYSTEM account and uses a DLL that is also used by some of my other apps.
Some of the apps are written in C and some in VB. The DLL creates a shared memory area for all clients using CreateFileMapping(). On Windows XP all clients can see the same copy of the shared memory area so that one app can change a variable's value and all other apps can see the new value.

Now with Windows 7 the clients don't seem to be able to see the same shared memory area that the ServiceApp sees. It is as if the ServiceApp has its own private copy of the shared memory.

Could this be related to the way Microsoft changed the "Session ID" behavior for Vista and Win7? My ServiceApp has Session ID=0 and the clients are Session ID=1.
On XP they were all Session ID=0.

Is there an easy way around this restriction.
Posted
Updated 11-Jan-11 22:14pm
v5
Comments
Dalek Dave 12-Jan-11 4:15am    
Edited for Readability.

What name are you using for the call to CreateFileMapping? Have you used the "Global\" prefix to force it into the global namespace?

See also http://msdn.microsoft.com/en-us/library/aa382954.aspx[^] for a discussion about the SeCreateGlobalPrivilege that you will need.
 
Share this answer
 
Comments
Dalek Dave 12-Jan-11 4:15am    
Good Call, Leccy.
Sauro, from what I have read, what you say is TRUE for memory mapped files AND shared data segments. Correct? MSDN Article on Shared Memory[^]
 
Share this answer
 
The other thing I suspect you would need to do, if you wanted to use memory-mapped files, would be to call CreateFileMapping with a NULL DACL for the security attributes (not the same as passing NULL in as the parameter value).
 
Share this answer
 
I have the same problem.

The SNMP service and my application use an extension dll that has a shared memory area defined by "#pragma data_seg ...". This works perfectly under XP but not under Windows 7. The session ids are different like described in the first posting.

Has someone some more ideas or a solution for this problem?
 
Share this answer
 
I do this in that way and had never a problem:
#define MY_SHARE  "{5D895D73-81FF-41b3-B1F5-11B1CCAAC17A}" // use GUIDGen

template <class TS>
class tShareMem : protected TS
{
public:
  tShareMem(const TCHAR* id=MY_SHARE)
  {
    SECURITY_ATTRIBUTES  secure = { sizeof(SECURITY_ATTRIBUTES),0,1 };

    memset((TS*)this,0,sizeof(TS));
    _hobject = CreateFileMapping((HANDLE)0xFFFFFFFF, &secure, PAGE_READWRITE|SEC_COMMIT, 0, sizeof(TS), id );
    switch((unsigned int)_hobject)
    {
      case 0: case INVALID_HANDLE_VALUE:
        _hobject = OpenFileMapping(FILE_MAP_ALL_ACCESS,1,id);
      break;
    }

    _pointer = (TS*)Lock();
    if(_pointer) memcpy(_pointer,(TS*)this,sizeof(TS));
  }
  ~tShareMem()
  {
    _pointer = (TS*)UnLock(_pointer);
    if(_hobject) CloseHandle(_hobject);
  }
  
  TS*  operator -> (){ return _pointer?_pointer:this; }

protected:
  void*    Lock()
  {
    return _hobject?MapViewOfFile(_hobject,FILE_MAP_ALL_ACCESS,0,0,0):0;
  }
  void*    UnLock(void* p)
  {
    if(p) UnmapViewOfFile(p);
    return 0;
  }
private:
  HANDLE  _hobject;
  TS*      _pointer;
};
 
Share this answer
 
Comments
Member 2976936 31-Aug-12 5:39am    
How to use your tShareMem class ?

tShareMem <cstring> ShareString;
ShareString = _T("Hello world !");
AfxMessageBox(ShareString );

Is it right ?
Problem solved!!!

Thanks to everyone for their input. It was through your combined efforts that I got to the point where I could see what I was doing wrong.

I was using a debug version of my service app and DLL to work through this problem. My debug versions pop up message boxes to alert me to certain things. I was aware that a service in Windows 7 cannot display message boxes but I thought that the code that calls the MessageBox() function would just be ignored. Now I know different. My MessageBox() calls were stopping the service dead in its tracks (before it could execute the MapViewofFile() function) waiting for someone to dismiss the message that was never actually displayed.

As soon as I ran my RELEASE versions with no MessageBox() calls everything worked fine. Of course I still needed to get the right DACL and add the "Global\\" prefix to the file name, but now it all works. I replaced all MessageBox() calls with WTSSendMessage() calls. So now I can see (and dismiss) the debug messages.

Thanks again to everyone.
chiselca
 
Share this answer
 
Comments
mgoldblat 27-Sep-12 8:35am    
chiselca, could you please show how you solved the problem?
I have the same problem and my program don't run on Windows 7 (XP is no problem).
CreateFileMapping returns ERROR_ACCESS_DENIED.
Global\\" prefix to the file name is set, the DACL is set too.
Nevertheless, the code don't run on Windows 7.
Is there any additional things I have to do?
Any help is appreciated.
chiselca 27-Sep-12 8:57am    
It's been 2 years but I remember that my main problem was I had MessageBox calls that were executing and stopping the thread before the code that sets up the file mapping even ran. You can't use MessageBox calls in the process that is running in Session 0 because the user will not see them and therefore cannot dismiss them, so they pause the thread forever. Other than that I followed the advice on this forum thread and got it working. Here is some of my code, hope it helps:

// Attempt to create a named file mapping object.
hMapObject = CreateFileMapping(
(HANDLE) 0xFFFFFFFF, // use paging file
&sa, // specific security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
sizeof(TsharedMem), // size: low 32-bits
"Global\\MyFileMap"); // name of map object

sa is defined as --

TCHAR * szSD = TEXT("D:") // Discretionary ACL
TEXT("(D;OICI;GA;;;BG)") // Deny access to built-in guests
TEXT("(A;OICI;GA;;;BA)") // Allow SDDL_GENERIC_ALL (GA) to administrators (BA)
TEXT("(A;OICI;FA;;;BU)"); // Allow FILE_ALL_ACCESS (FA) to built-in Users (BU)


ConvertStringSecurityDescriptorToSecurityDescriptor(
szSD,
SDDL_REVISION_1,
&(sa->lpSecurityDescriptor),
NULL);
mgoldblat 27-Sep-12 10:29am    
Unfortunately, it don't work for me...
Are you sure, it works for a regular user (without admin rights) under Windows 7?
Did you try it as a normal user?
If so, I am completely stumped...
chiselca 27-Sep-12 10:41am    
Yes it works as a regular user in XP, Win7 32 bit and Win7 64 bit, that was a requirement. I wish I could help you more. I will tell you that I never had a problem that frustrated me so much. I fought it for weeks and was very close to giving up and redesigning my app when I figured out the MessageBox issue. My advice would be, keep plugging away. It works. It's very easy to convince yourself that it works for everyone but you. It doesn't. It works for everybody if you do everything right. You're probably missing something simple.
I think I have resolved my problem another way. I went back to a method I used years ago before I decided to use the memory file mapping solution for shared memory:
C#
#pragma data_seg (".shared")
    int     var1 = 0;
    long    var2 = 0;
    int     var3 = 169;
#pragma data_seg ()


This seems to work. I know that I should not use pointers in this shared memory area so I will have to do some re-writing but this change will also work in XP so it is worth a try.

Thanks "Electron Shepherd" for your help!
 
Share this answer
 
Comments
Sauro Viti 12-Nov-10 14:47pm    
Be aware that if you use a shared section on a DLL, all the clients of the DLL will share that section as long as the library doesn't get relocated while loaded. In other words, if your service loads the DLL at address x and another of your app loads the library at address y, the two applications will really share the data only if x == y.
UPDATE: I thought using "pragma" to create a shared memory area solved my problem but it did not. I was doing something wrong and getting false results.

At this stage I have spent days Googling, and trying every suggestion I can find and I still cannot get memory mapping to work between my service and my application.

What I have learned is that services are much more complex in Vista and Win7 than they were in XP which almost makes me want to redesign my application to not use a service at all just to make my life easier, but some of the things my service does cannot be done under the user's account so I really would like to keep it.

Really frustrated right now......
 
Share this answer
 
I just read the article you referenced and I added "Global\\" to my file mapping name but it made no difference. The article also implies that SeCreateGlobalPrivilege is only needed if the client is going to create the file. My ServiceApp ALWAYS creates the file first (Session 0). The clients only have to open it.
 
Share this answer
 
Electron, it is interesting that you should point out the DACL value. When I first created this app 5 years ago I was passing NULL as the DACL value. But I later found that when non-admins were running the app, their instance of the app could not see the shared memory from the Service app. Only admins couuld see it. So I set up a DACL string as follows-

MIDL
TCHAR * szSD = TEXT("D:")       // Discretionary ACL
    TEXT("(D;OICI;GA;;;BG)")    // Deny access to built-in guests
    TEXT("(A;OICI;GA;;;BA)")    // Allow SDDL_GENERIC_ALL (GA) to administrators (BA)
    TEXT("(A;OICI;FA;;;BU)");   // Allow FILE_ALL_ACCESS (FA) to built-in Users (BU)


This has worked for 5 years but now it is not working in Windows 7. Is there a way I could modify the string to work properly in Windows 7?

Also, you said using a NULL DACL value is "not the same as passing NULL in as the parameter value". Can you explain this? Previous to using the DACL that is exactly what I did-

VB
hMapObject = CreateFileMapping(
    (HANDLE) 0xFFFFFFFF, // use paging file
    <big>NULL</big>,                // no security attributes
    PAGE_READWRITE,      // read/write access
    0,                   // size: high 32-bits
    sizeof(TsharedMem),  // size: low  32-bits
    "Global\\FileMapName");    // name of map object


So I basically have the same problem now that I had 5 years ago, except the DACL isn't working for any users, including admins.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900