WindowsでWindowsサービスとアプリケーションの間の共有メモリによるデータのやり取りを確認していた。
まずは簡単に,共有メモリの使い方を学習する。
参考にするページはこのページ。
とりあえず,CreateFileMappingとMapViewOfFileを使用することでメモリの共有ができる。しかし,これができるのは同じユーザの場合。
Windowsサービスとユーザアプリケーション間のやり取りに苦労する。
そこで次の例を読み込む。
CreateFileMappingの2つ目の引数をNULLではなく設定するのだ。
ここまでできるとサービス側で読み書きできて,アプリケーション側では読み取り専用で開かせたい。
アプリケーション側
#include "stdafx.h"
int main()
{
TCHAR name[] = _T("Global\\somename");
DWORD dwSize = sizeof(int);
HANDLE hSharedMemory = OpenFileMapping(
FILE_MAP_READ,//FILE_MAP_ALL_ACCESS,
FALSE,
name
);
int* pMemory = (int*)MapViewOfFile(hSharedMemory, FILE_MAP_READ/*FILE_MAP_ALL_ACCESS*/, NULL, NULL, dwSize);
for (int i = 0; i < 40; i++)
{
//(*pMemory)--;
_tprintf_s(_T("memory: %d\n"), *pMemory);
Sleep(500);
}
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
return 0;
}
サービス側 試行錯誤してみました。
#include "stdafx.h"
int main()
{
TCHAR name[] = _T("Global\\somename");
DWORD dwSize = sizeof(int);
SECURITY_DESCRIPTOR secDesc;
SECURITY_ATTRIBUTES secAttr;
InitializeSecurityDescriptor(&secDesc, SECURITY_DESCRIPTOR_REVISION);
DWORD dwAclSize = 1024;
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_LOCAL_SID_AUTHORITY; // SECURITY_WORLD_SID_AUTHORITY (Everyone)でもよい
PSID pSid = NULL;
if (!AllocateAndInitializeSid(&SIDAuth, 1,
SECURITY_WORLD_RID,
0, 0, 0, 0, 0, 0, 0,
&pSid))
{
return 1;
}
PACL pDacl = (PACL)HeapAlloc(GetProcessHeap(), 0, dwAclSize);
if (pDacl == NULL) {
return 1;
}
// 随意アクセス制御リストを初期化
InitializeAcl(pDacl, dwAclSize, ACL_REVISION);
// ACE(アクセス制御エントリ)をDACLに追加
AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_READ, pSid);
AddAccessDeniedAce(pDacl, ACL_REVISION, GENERIC_WRITE, pSid);
SetSecurityDescriptorDacl(&secDesc, TRUE, pDacl, FALSE);
secAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
secAttr.bInheritHandle = TRUE;
secAttr.lpSecurityDescriptor = &secDesc;
HANDLE hSharedMemory = CreateFileMapping(INVALID_HANDLE_VALUE, &secAttr, PAGE_READWRITE, NULL, dwSize, name);
LocalFree(pDacl);
FreeSid(pSid);
int* pMemory = (int*)MapViewOfFile(hSharedMemory, FILE_MAP_ALL_ACCESS, NULL, NULL, dwSize);
*pMemory = 0; // Only the administrators process can handle it as fully accessible variable.
for (int i = 0; i < 40; i++)
{
(*pMemory)++;
_tprintf_s(_T("src_memory: %d\n"), *pMemory);
Sleep(1000);
}
UnmapViewOfFile(pMemory);
CloseHandle(hSharedMemory);
return 0;
}
特に
AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_READ, pSid);
AddAccessDeniedAce(pDacl, ACL_REVISION, GENERIC_WRITE, pSid);
の周辺を入れていました。
[参考]
- C++で複数プロセスから読み書き可能な共有メモリを作る
- 【共有メモリ】アクセスが拒否されました。