私の問題は、C++/C# で共有メモリ (MemoryMappedFiles) を読み書きする方法ではなく、C# で MemoryMappedFile のセキュリティ オプションを正しく設定する方法についてです (私は C# にまったく慣れていないので、質問があれば許してくださいばかです)。
共有メモリ スペースを設定するサービスとして (SYSTEM アカウントで) プロセスを実行しています。次に、その共有メモリ空間にアクセスするサービスとして (SYSTEM アカウントで) 実行されている別のプロセスもあります。
両方の最初のバージョンは C++ で書かれており、主にサーバー (「ライター」) が行います (Global\mySegment という名前の 1024 バイトのメモリ セグメントが必要だとします):
HANDLE m_memoryHandle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, "Global\\mySegment");
SetSecurityInfo(m_memoryHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, (PACL) NULL, NULL);
LPVOID m_pSharedMemorySegment = MapViewOfFile(m_memoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, 1024);
そして読者:
HANDLE m_memoryHandle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "Global\\mySegment");
LPVOID m_pSharedMemorySegment = MapViewOfFile(m_memoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
このコードはうまく機能します。つまり、ライターによって作成された共有メモリ スペースは、どのような状況でもリーダーからアクセスできます (つまり、ライターがサービスとして実行されている場合、または現在の (ログインしている) ユーザー アカウント (管理者権限を持つユーザー) で実行されている場合) およびリーダーがサービスとして実行されている場合、または同じ現在の (ログインしている) ユーザー アカウントで実行されている場合)。
今、私はこのコード (ライターのみ) を C# に変換し、主に次のことを行いました。
MemoryMappedFile mappedFile = MemoryMappedFile.CreateNew(@"Global\mySegment", 1024, MemoryMappedFileAccess.ReadWrite);
このライターでは、ライターが現在のユーザーによって実行されている場合にのみ機能します。それがサービスとして起動されると (したがって「SYSTEM」ユーザーによって実行されると)、リーダーは共有メモリ空間にアクセスできなくなります (どちらの場合も、リーダーが現在のユーザーによって実行されるか、またはSYSTEMによるサービス)。
だから私はC++行を翻訳しようとしました
SetSecurityInfo(m_memoryHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, (PACL) NULL, NULL);
C#に。私が見つけた最も近い実装は次のとおりです。
var security = new MemoryMappedFileSecurity();
// Create a SecurityIdentifier object for "everyone".
SecurityIdentifier everyoneSid = new SecurityIdentifier(WellKnownSidType.WorldSid, null);
security.AddAccessRule(new AccessRule<MemoryMappedFileRights>(everyoneSid, MemoryMappedFileRights.FullControl, AccessControlType.Allow));
MemoryMappedFile mappedFile = MemoryMappedFile.CreateNew(_memoryRegionName, _memRegionSize, MemoryMappedFileAccess.ReadWrite, MemoryMappedFileOptions.None, security, HandleInheritability.Inheritable);
しかし、その結果、前述の 4 つの service-no service の組み合わせのすべての下で、リーダーは共有メモリ空間にまったくアクセスできなくなります。
この動作が C# コードに関して完全に直感に反していることを考えると、私は少し迷っています...
誰かがこの問題を解決する方法について良い実装またはアイデアを持っていますか?
どうもありがとう。