Click here to Skip to main content
16,016,306 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
Hi,

I need to share data between a windows service and another process.
I've tried doing it using file mapping.

I wrote a small program which works well on WindowsXP, a small time service, which writes the time to shared memory every second.

I can read this memory in another process without a problem (on XP).

I've tried the same program on windows 7, and the service itself can read the last written time, but when trying to read the shared memory from another process, the mapping is done to another file - I can read/write from/to this file and got values unrelated to the file with the same name I'm using on the windows service.

I've tried using "Global\" prefix, It works well on XP (after granting permission to create global objects), but still the same behavior on Windows 7.

bool SharedMemoryManager::GetSecurityDescriptor(SECURITY_DESCRIPTOR& sd, SECURITY_ATTRIBUTES& sa)
{
	if (!::InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION))
		return false;

	if (!::SetSecurityDescriptorDacl(&sd, TRUE, (PACL) NULL, FALSE))
		return false;

	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = &sd;

	return true;
}

bool SharedMemoryManager::OpenSharedMemory(bool& wasMemoryAlreadyExist, DWORD sizeOfSharedMemory)
{	
	SECURITY_DESCRIPTOR sd;
	SECURITY_ATTRIBUTES sa;
	SECURITY_ATTRIBUTES* pSecurityAttributes = &sa;
	if (!GetSecurityDescriptor(sd, sa))
	{		
		DTK_ERROR("SharedMemoryManager::OpenSharedMemory: failed to get security descriptor (error code %0)") 
			<< PdkString::fromWindowLastError();
		pSecurityAttributes = NULL;
	}

    // Create a named file mapping
    fileMapping_ = ::CreateFileMapping(
		INVALID_HANDLE_VALUE, 
		pSecurityAttributes, 
		PAGE_READWRITE, 
		0, 
		sizeOfSharedMemory, 
		sharedMemoryName_.c_str());
	
	if (fileMapping_ == NULL)
	{
		DTK_ERROR("SharedMemoryManager::OpenSharedMemory: Shared memory cannot be opened: %0")
			<< PdkString::fromWindowLastError();
		return false;
	}
	
	wasMemoryAlreadyExist = (::GetLastError() == ERROR_ALREADY_EXISTS);//see usage below	
	
	
	//genearte the shared memory view 
    sharedMemoryAdress_ = ::MapViewOfFile(fileMapping_, FILE_MAP_WRITE, 0, 0, 0);

	if (sharedMemoryAdress_ == NULL)
	{
		DTK_ERROR("SharedMemoryManager::OpenSharedMemory: Failed to generate a view of the shared memory: %0")
			<< PdkString::fromWindowLastError();
		return false;
	}        

	return true;
}


void SharedMemoryManager::CloseSharedMemory()
{
	if (sharedMemoryAdress_) 
	{
		::UnmapViewOfFile(sharedMemoryAdress_);
		sharedMemoryAdress_ = NULL;
	}

	if (fileMapping_) 
	{
		::CloseHandle(fileMapping_);
		fileMapping_ = NULL;
	}
}
Posted
Comments
strogg 6-May-11 5:52am    
Strange, try passing NULL to the Security Descriptor (to use default security) - Also did you forget to put a double-backslash for global (Global\\Name)?
Also, you have not shown the OpenFileMapping() code (in other process)

You need to create and access that file/memory with the lowest rights of any process who use it.
 
Share this answer
 
strogg was right, Global\\ was missing, since we use \\ as a separator, so when passing the "Global\\name" the \\ was removed.

Thanks
 
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