2010-03-16 19 views
7

Sto cercando di utilizzare MapViewOfFile in un processo a 64 bit su un file già mappato in memoria di un altro processo a 32 bit. Fallisce e mi dà un errore di "accesso negato". Si tratta di una limitazione nota di Windows o sto facendo qualcosa di sbagliato? Lo stesso codice funziona bene con 2 processi a 32 bit.MapViewOfFile condiviso tra processi a 32 bit e 64 bit

Il codice sorta di assomiglia a questo:

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

Hai controllato se il percorso viene reindirizzato alla directory di VirtualStore? Process Monitor potrebbe aiutare. – bk1e

risposta

9

Quando si chiama CreateFile nella applicazione a 32 bit, si sta passando 0 per il parametro di condivisione, il che significa che nessuna condivisione è permesso. Cambiarlo in FILE_SHARE_READ | FiLE_SHARE_WRITE sarebbe probabilmente un passo nella giusta direzione.

Edit: Ho appena frustato insieme una demo che funziona (almeno per me):

#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; 
} 

Qualsiasi combinazione di eseguibili a 32 o 64 bit sembra funzionare bene.

Edit2: nota, tuttavia, che si tratta di un codice a livello di demo. Ad esempio, il nome di ciascun oggetto condiviso dovrebbe normalmente contenere una stringa GUID per garantire la collisione accidentale con altri programmi. Ho anche saltato un bel po 'di controllo degli errori, per non parlare dei piccoli dettagli che questo codice non porta a nulla di utile.

+0

Grazie Jerry, è interessante che funzioni per te. Non penso che sia un mio problema, anche perché il flag no sharing è passato solo a CreateFile; quel file viene chiuso immediatamente, quindi non dovrebbe essere applicato. Funziona anche bene per la condivisione tra più applicazioni a 32 bit, si interrompe solo quando una di esse è a 64 bit. Proverò comunque a eseguire il tuo codice. –

+1

Penso di aver capito. La dimensione del file è stata determinata in base alla dimensione di una struttura che è più grande sul sistema a 64 bit perché time_t è a 64 bit e stiamo forzando i nostri time_ts a essere ancora a 32 bit su build a 32 bit. Per qualche motivo, specificare la dimensione della regione più grande di quella esistente su MapViewOfFile non riesce con Access Denied. Grazie! –

Problemi correlati