2010-03-16 41 views
7

Estoy tratando de usar MapViewOfFile en un proceso de 64 bits en un archivo que ya está asignado a la memoria de otro proceso de 32 bits. Falló y me da un error de "acceso denegado". ¿Es esta una limitación conocida de Windows o estoy haciendo algo mal? El mismo código funciona bien con 2 procesos de 32 bits.MapViewOfFile compartido entre procesos de 32 bits y 64 bits

El código de tipo de parece a esto:

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

¿Ha comprobado si la ruta se redirecciona al directorio de la VirtualStore? Process Monitor podría ayudar. – bk1e

Respuesta

9

Cuando se llama a CreateFile en la aplicación de 32 bits, estás pasando 0 para el parámetro de uso compartido, lo que significa que no se permite el uso compartido. Cambiar eso a FILE_SHARE_READ | FiLE_SHARE_WRITE probablemente sea un paso en la dirección correcta.

Editar: Sólo azotado juntos una demo que funciona (al menos para mí):

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

Cualquier combinación de los ejecutables de 32 o 64 bits parece funcionar bien.

Edit2: Tenga en cuenta, sin embargo, que este es un código puramente de nivel de demostración. Solo por ejemplo, el nombre de cada objeto compartido normalmente debería contener una cadena GUID para evitar colisiones accidentales con otros programas. También me salté un poco la comprobación de errores, sin mencionar el pequeño detalle de que este código no logra nada útil.

+0

Gracias Jerry, es interesante que te funcione. No creo que sea mi problema, porque la bandera de no compartir solo se pasa a CreateFile; ese archivo se cierra inmediatamente, por lo que no debería aplicarse. También funciona bien para compartir entre múltiples aplicaciones de 32 bits, solo se descompone cuando una de ellas es de 64 bits. Aunque intentaré ejecutar tu código. –

+1

Creo que lo descubrí. El tamaño del archivo se determinó en función del tamaño de una estructura que es más grande en el sistema de 64 bits porque time_t tiene 64 bits allí y estamos forzando a nuestro time_ts a seguir siendo de 32 bits en las compilaciones de 32 bits. Por alguna razón, especificar el tamaño de la región que es más grande que el existente en MapViewOfFile falla con Acceso denegado. Gracias! –

Cuestiones relacionadas