2012-08-30 2 views
3

Mon problème n'est pas de savoir comment lire/écrire en mémoire partagée (MemoryMappedFiles) en C++/C#, mais plutôt comment régler correctement l'option de sécurité du MemoryMappedFile en C# (et I ' m assez nouveau à C#, alors pardonnez-moi si la question est stupide).Comment définir correctement les options de sécurité MemoryMappedFile en C#

J'ai un processus s'exécutant en tant que service (sous le compte SYSTEM) qui configure un espace de mémoire partagée. Ensuite, j'ai un autre processus, exécuté en tant que service (sous le compte SYSTEM), qui accède à cet espace mémoire partagé.

La première version de deux d'entre eux est écrit en C++, le serveur (le « écrivain ») ne principalement (laisse supposer que je veux un 1024 octets segment de mémoire dont le nom est mondial \ mySegment):

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); 

et le lecteur:

HANDLE m_memoryHandle = OpenFileMappingA(FILE_MAP_ALL_ACCESS, FALSE, "Global\\mySegment"); 
LPVOID m_pSharedMemorySegment = MapViewOfFile(m_memoryHandle, FILE_MAP_ALL_ACCESS, 0, 0, 0); 

Ce code fonctionne bien, à savoir l'espace de mémoire partagée créé par l'écrivain est accessible au lecteur en aucun cas (si l'auteur est exécuté en tant que service ou sous le courant (connecté -in) compte d'utilisateur (qui a des droits d'administrateur) et si le lecteur est exécuté en tant que service ou sous le même compte utilisateur (connecté) actuel).

Maintenant, je traduis ce code (l'auteur seulement) à C#, en faisant principalement ceci:

MemoryMappedFile mappedFile = MemoryMappedFile.CreateNew(@"Global\mySegment", 1024, MemoryMappedFileAccess.ReadWrite); 

Avec cet écrivain, il ne fonctionne que si l'auteur est exécuté par l'utilisateur en cours. Lorsqu'il est lancé en tant que service (et donc géré par un utilisateur "SYSTEM"), le lecteur n'a plus accès à l'espace mémoire partagé ("Accès refusé", dans les deux cas, lorsque le lecteur est exécuté par l'utilisateur courant ou un service par SYSTEM).

J'ai donc essayé de traduire le C++ ligne

SetSecurityInfo(m_memoryHandle, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, 0, 0, (PACL) NULL, NULL); 

à C#. La mise en œuvre le plus proche que j'ai trouvé est:

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); 

Mais le résultat est que maintenant le lecteur ne peut pas accéder à l'espace de mémoire partagée à tous, sous toutes les 4 combinaisons susmentionnées de service sans service

Étant donné que ce comportement est complètement contre-intuitif par rapport au code C#, je suis un peu perdu ...

Quelqu'un a une bonne implémentation ou des idées sur la façon de résoudre ce problème?

Merci beaucoup.

+0

Le lecteur utilise OpenExisting avec les mêmes données MemoryMappedFileRights http://msdn.microsoft.com/en-us/library/dd267590.aspx –

+0

Non, le lecteur est toujours l'ancien code C++ indiqué dans ma question. Je voudrais éviter de le modifier uniquement dans le but de le rendre compatible avec l'auteur C# (sauf si je trouve un moyen de le garder compatible avec mon auteur C++ et mon écrivain C#) –

Répondre

0

Essayez d'ajouter Global\ au début du nom utilisé pour le fichier mappé en mémoire. J'avais exactement le même problème que vous avez décrit, cependant avec un service qui fonctionnait sous le compte NETWORK, et ceci l'a résolu.

+0

Sauf si j'ai raté un autre endroit où je besoin de faire cela, c'est déjà fait par cette ligne, non? 'MemoryMappedFile mappedFile = MemoryMappedFile.CreateNew (@" Global \ mySegment ", 1024, MemoryMappedFileAccess.ReadWrite);' –

Questions connexes