2010-03-16 7 views
7

J'essaie d'utiliser MapViewOfFile dans un processus 64 bits sur un fichier qui est déjà mappé à la mémoire d'un autre processus 32 bits. Il échoue et me donne une erreur "accès refusé". Est-ce une limitation connue de Windows ou est-ce que je fais quelque chose de mal? Le même code fonctionne correctement avec 2 processus 32bit.MapViewOfFile partagé entre les processus 32 bits et 64 bits

Le code ressemble un peu comme ceci:

hMapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, szShmName); 
if (NULL == hMapFile) 
{ /* failed to open - create new (this happens in the 32 bit app) */ 
    SECURITY_ATTRIBUTES sa; 
    sa.nLength = sizeof(SECURITY_ATTRIBUTES); 
    sa.bInheritHandle = FALSE; 
    /* give access to members of administrators group */ 
    BOOL success = ConvertStringSecurityDescriptorToSecurityDescriptor(
      "D:(A;OICI;GA;;;BA)", 
      SDDL_REVISION_1, 
      &(sa.lpSecurityDescriptor), 
      NULL); 
    HANDLE hShmFile = CreateFile(FILE_XXX_SHM, 
      FILE_ALL_ACCESS, 0, 
      &sa, 
      OPEN_ALWAYS, 0, NULL); 

    hMapFile = CreateFileMapping(hShmFile, &sa, PAGE_READWRITE, 
      0, 
      SHM_SIZE, 
      szShmName); 

    CloseHandle(hShmFile); 
} 

// this one fails in 64 bit app 
pShm = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, SHM_SIZE); 
+0

Avez-vous vérifié si le chemin est redirigé vers le répertoire VirtualStore? Process Monitor peut vous aider. – bk1e

Répondre

9

Lorsque vous appelez CreateFile dans l'application 32 bits, vous passez 0 pour le paramètre de partage, ce qui signifie pas de partage est autorisé. Changer cela à FILE_SHARE_READ | FiLE_SHARE_WRITE serait probablement un pas dans la bonne direction.

Edit: Je viens fouetté ensemble une démo qui fonctionne (au moins pour moi):

#include <windows.h> 
#include <iostream> 

static const char map_name[] = "FileMapping1"; 
static const char event1_name[] = "EventName1"; 
static const char event2_name[] = "EventName2"; 

int main() { 
    HANDLE mapping = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, map_name); 

    if (NULL == mapping) { 
     std::cout << "Calling CreateFile\n"; 
     HANDLE file = CreateFile("MappedFile", 
      FILE_ALL_ACCESS, 
      FILE_SHARE_READ | FILE_SHARE_WRITE, 
      NULL, 
      OPEN_ALWAYS, 
      0, 
      NULL); 
     std::cout << "Creating File mapping\n"; 
     mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0, 65536, map_name); 

     std::cout << "Closing file handle\n"; 
     CloseHandle(file); 
    } 

    std::cout << "Mapping view of file\n"; 
    char *memory = (char *)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 65536); 
    if (memory == NULL) { 
     std::cerr << "Mapping Failed.\n"; 
     return 1; 
    } 
    std::cout << "Mapping succeeded\n"; 

    HANDLE event = CreateEvent(NULL, false, false, event1_name); 

    if (GetLastError()==ERROR_ALREADY_EXISTS) { 
     std::cout <<"Waiting to receive string:\n"; 
     WaitForSingleObject(event, INFINITE); 
     std::cout << "Received: " << memory; 
     HANDLE event2 = CreateEvent(NULL, false, false, event2_name); 
     SetEvent(event2); 
    } 
    else { 
     char string[] = "This is the shared string"; 
     std::cout << "Sending string: " << string << "\n"; 
     strncpy(memory, string, sizeof(string)); 
     SetEvent(event); 
     HANDLE event2 = CreateEvent(NULL, false, false, event2_name); 
     WaitForSingleObject(event2, INFINITE); 
    } 
    return 0; 
} 

Toute combinaison de 32- ou 64 bits executables semble fonctionner très bien.

Édition2: Notez cependant qu'il s'agit d'un code de niveau purement démo. Juste par exemple, le nom de chaque objet partagé devrait normalement contenir une chaîne GUID pour éviter toute collision accidentelle avec d'autres programmes. J'ai également sauté un peu de vérification d'erreur, sans mentionner le détail mineur que ce code n'atteint rien d'utile.

+0

Merci Jerry, c'est intéressant que ça marche pour toi. Je ne pense pas que ce soit mon problème parce que le drapeau de non-partage est seulement passé à CreateFile; ce fichier est fermé immédiatement, il ne devrait donc pas s'appliquer. En outre, il fonctionne très bien pour le partage entre plusieurs applications 32 bits, ne tombe en panne lorsque l'un d'eux est de 64 bits. Je vais essayer d'exécuter votre code si. –

+1

Je pense que je l'ai compris. La taille du fichier a été déterminée en fonction de la taille d'une structure qui est plus grande sur le système 64 bits car time_t est en 64bit et nous forçons nos time_ts à être encore 32bit sur les versions 32bit. Pour une raison quelconque, la spécification de la taille de la région qui est plus grande que celle existant sur MapViewOfFile échoue avec Access Denied. Merci! –

Questions connexes