Tech Support > Microsoft Windows > Development Resources > Shared memory area is not really shared on Windows 2003?
Shared memory area is not really shared on Windows 2003?
Posted by Jim Henry on July 7th, 2005



We have a set of applications which use a shared memory
area to provide status information to a managing service
running on the same machine, and to a managing application
running on another machine via SNMP. The management service,
each of our applications, and our SNMP extension agent
all include code to create a certain shared memory area if
it doesn't exist yet, or find it and map it if it does
already exist. Each application has certain variables
in the shared memory area that it writes to, while our
SNMP extension agent reads the shared memory area
and makes its contents available to remote apps for querying.

All this has been working fine on Windows NT and Windows 2000.
We recently started testing this code for the first time
on Windows 2003, and find that:

1. The management service gets one "shared" memory area.
2. The SNMP extension agent gets another "shared" memory area.
3. Each application which is started from a command prompt
gets the same shared memory area, different from those
obtained by #1 and #2.

The result is that the SNMP agent can't see the shared
memory that's being written to by the other service
and the applications, and our management app on the other
machine can't tell that any apps are running or what their
status is. It also can't tell that the management service
is running.

Both the SNMP Service and our management service are running
as a domain user - the same user who is logged in and starting
applications from the command prompt (or shortcut links, etc.).

The problem code is:

BOOL fInit;

// Set the access control list to everyone accessible.

SECURITY_INFORMATION SecurityInformation;
BYTE byACLBuffer[4096];
DWORD swACLSize = sizeof(byACLBuffer);
SECURITY_DESCRIPTOR SecurityDescriptor;
SECURITY_ATTRIBUTES SecurityAttributes;
BYTE bySIDBuffer[1024];
DWORD dwSIDSize = sizeof(bySIDBuffer);
SecurityInformation = DACL_SECURITY_INFORMATION;
InitializeSecurityDescriptor(&SecurityDescriptor,
SECURITY_DESCRIPTOR_REVISION);
InitializeAcl((PACL)byACLBuffer, sizeof(byACLBuffer), ACL_REVISION);
if (NameToSID("Everyone", (PSID) bySIDBuffer, &dwSIDSize)) {
AddAccessAllowedAce((PACL) byACLBuffer, ACL_REVISION, GENERIC_ALL,
bySIDBuffer);
}
if (!SetSecurityDescriptorDacl(&SecurityDescriptor, TRUE, (PACL)
byACLBuffer, FALSE)) {
;
}
SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
SecurityAttributes.lpSecurityDescriptor = & SecurityDescriptor;
SecurityAttributes.bInheritHandle = FALSE;

// Create a named file mapping object.
// Using the above security attribute variable.

hMapObject = CreateFileMapping(
(HANDLE) 0xFFFFFFFF, // use paging file
&SecurityAttributes,
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
DBB_PERF_SHMEMSIZE, // size: low 32-bits
DBB_PERF_MEM_OBJ_NAME ); // name of map object

m_LastError = ::GetLastError();
// The first process to attach initializes memory.
fInit = ( m_LastError != ERROR_ALREADY_EXISTS);

// Get a pointer to the file-mapped shared memory.
if (hMapObject != NULL) {
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 ( hMapObject ) {
writelog( "got map object" );
}
if ( lpvMem ) {
writelog( "got mapped view of file" );
}
if (hMapObject == NULL || lpvMem == NULL) {
lpvMem = malloc( DBB_PERF_SHMEMSIZE );
fInit = true;
writelog("Get Shared memory failed, using heap memory\n");
}

// Initialize memory if this is the first process.
bool bfirst = true;
bool useHeap = false;
if (fInit) {
memset(lpvMem, '\0', DBB_PERF_SHMEMSIZE);
}
else {
SharedTableHeader * pHeader = (SharedTableHeader *) lpvMem;
if (pHeader->SharedMemorySize != DBB_PERF_SHMEMSIZE) {
writelog( "shared memory is wrong size so use heap" );
useHeap = true;
}
}
HANDLE hMutex = ::CreateMutex(&SecurityAttributes, false,
"DBB_PERF_MEMORY_CLEAR_MUTEX");
assert(hMutex);
if (!useHeap && !fInit) {
if (::GetLastError() != ERROR_ALREADY_EXISTS){
memset(lpvMem, '\0', DBB_PERF_SHMEMSIZE);
}
else {
bfirst = false;
SMemRegion = (SharedMemoryRegion *) lpvMem;
if (SMemRegion->header.SharedMemorySize != DBB_PERF_SHMEMSIZE ||
SMemRegion->header.HeaderSize != sizeof(SharedTableHeader) ||
SMemRegion->header.PerfSize != sizeof(dbbPerf) ||
SMemRegion->header.TraceSize != sizeof(dbbTrace))
{
writelog( "set useHeap because one or more size vars don't match" );
useHeap = true;
}
}
}
if (useHeap) {
writelog( "useHeap [2]" );
lpvMem = malloc( DBB_PERF_SHMEMSIZE );
memset(lpvMem, '\0', DBB_PERF_SHMEMSIZE);
bfirst = true;

MessageBox(NULL, "Instance versions are different, can't use shared
memory.",
"Version Conflict", MB_ICONWARNING | MB_OK);
}
SMemRegion = new (lpvMem) SharedMemoryRegion();
m_pTheOne = &(SMemRegion->perf);
m_pTheOne->m_bNotFirst = !bfirst;
// The snmp variables will be reset by the 'memset' above.


// ..............


static inline BOOL NameToSID(LPTSTR lpName, PSID pSID, LPDWORD dd)
{
TCHAR szDomain[256];
DWORD dwDomainSize = sizeof(szDomain);
SID_NAME_USE SidNameUse;
if (!LookupAccountName(NULL, lpName, pSID, dd, szDomain,
&dwDomainSize, &SidNameUse))
{
return FALSE;
}
return TRUE;
}

Posted by SteveR on July 10th, 2005


Jim Henry <jimhenry@pobox.com> writes:
Almost certainly (I don't have immediate access to up-to-date docs for
CreateFileMapping()), this is caused by each "pool" of processes (1, 2,
3 in your list above) existing in a different <something> (Terminal
Server session, Window Station, something else), and each <something>
having its own kernel object name space. For Terminal Server sessions,
you can use Global\name instead of name to put the name in the global
name space.

Use GetVersionEx and other items to determine whether the Global\name
notation will be necessary, and only use it if so, as, in the absence of
separate name spaces, backslashes are not allowed in kernel object
names.

HTH
--
SteveR
(throw away the dustbin, send to stever@... instead)

Humans are way too stupid to be dumb animals.
http://www.accidentalcreditor.org.uk/

Posted by Jim Henry on July 11th, 2005



SteveR wrote:
OK, that makes sense.

The MSDN documentation says this about GetVersionEx():

The linked article contained a reference to GetSystemMetrics(),
but that function doesn't seem to have a way to tell you if the OS uses
separate namespaces. It also suggested:

Is there a particular library and function I could test for
that would indicate whether the OS uses separate namespaces?
For now, I'll try just testing for the OS version.


Posted by Jim Henry on July 12th, 2005


Prepending "Global\\" to the shared memory object name string
when GetVersionEx() shows Windows XP or later seems to work
(at least on Windows 2003; I haven't actually had a chance
to test on Windows XP yet, but my reading seems to suggest
that these namespaces first appeared in XP). The processes
are able to see the same shared memory now.
Thanks.

Posted by Tim Kannel on July 12th, 2005


In article <1121177944.389051.265710@g47g2000cwa.googlegroups .com>,
jimhenry@pobox.com says...
As you mentioned earlier in this thread, checking the version number is
usually not the best way. An alternative is simply to try it one way
(with the Global prefix) and then handle any failures (by repeating the
call without the Global prefix in the object name). That is, you can
test for the presense of the feature in this case simply by trying
to use it and letting the OS validate the object name.
See the following page for more info:

http://msdn.microsoft.com/library/en-
us/termserv/termserv/kernel_object_namespaces.asp?frame=true

If you would still prefer having a separate check in your code, then
checking for Terminal Services would probably be better than checking
the version number:
http://msdn.microsoft.com/library/en-
us/termserv/termserv/detecting_if_terminal_services_is_installed.asp?
frame=true


--
Tim Kannel

TCAP - Captures console I/O to a file (DOS,Win9x)
http://www.simtel.net/pub/pd/11141.shtml


Similar Posts