Search code examples
delphiwinapidelphi-7

CreateFileMapping fails with hFile other than INVALID_HANDLE_VALUE


update - solved and answered, offending lines have been commented out

Brief description

I am having a problem linking CreateFile with CreateFileMapping even though I use (GENERIC_WRITE or GENERIC_WRITE) for CreateFile, with PAGE_READWRITE for CreateFileMapping

Detailed description

I am using CreateFileMapping to share memory between proceses. the actual mechanics of that is working fine, assuming I don't map to a physical file and instead use INVALID_HANDLE_VALUE for the first parameter to CreateFileMapping. This is fine, however what I'd like to achieve is for the main process that creates this map to use a disk based file, and flush it to the drive, periodically, and when it shuts down, so the data is automatically saved.

Code follows... (when i run this, i get "Error 5 : Access is Denied" as the ShowMessage)

const MaximumMapSize = 256 * 1024;
var virtualMemoryPath : string = '';

function getFileHandle(mapname : string; maxSize  : dword) :THandle;
var diskfilename : string;

  lpFileName: PChar;
  dwDesiredAccess: DWORD;
  dwShareMode: DWORD;
  lpSecurityAttributes: PSecurityAttributes;
  dwCreationDisposition : dword;
  dwFlagsAndAttributes: DWORD;
  hTemplateFile : THandle ;

  temp : pointer;
begin
    Result := INVALID_HANDLE_VALUE;
    if (maxSize <= MaximumMapSize) and (Length(virtualMemoryPath) > 0) then
    begin

            diskfilename := virtualMemoryPath+mapname+'.bin';

            if FileExists(diskfilename) then
               Sysutils.DeleteFile(diskfilename);

            lpFileName              := PChar(diskfilename);
            //dwDesiredAccess         := GENERIC_WRITE or GENERIC_WRITE;//<<<wrong
            dwDesiredAccess         := GENERIC_READ or GENERIC_WRITE;
            dwShareMode             := 0;//FILE_SHARE_READ or FILE_SHARE_WRITE;//<<wrong
            lpSecurityAttributes    := nil;
            dwCreationDisposition   := CREATE_ALWAYS;
            dwFlagsAndAttributes    := 0;
            hTemplateFile           := 0 ;


            Result := CreateFile(
                lpFileName,
                dwDesiredAccess,
                dwShareMode,
                lpSecurityAttributes,
                dwCreationDisposition,
                dwFlagsAndAttributes,
                hTemplateFile);

           if (Result <> INVALID_HANDLE_VALUE) then
           begin
             GetMem(temp,maxsize);
             ZeroMemory(temp,maxsize);
             FileWrite(result,temp^,maxSize);
             FreeMem (temp,maxsize);
             FlushFileBuffers(result);
             SetFilePointer(result,0,0,FILE_BEGIN);
           end;
    end;
end;

function createMap (mapname : string ; maxSize: dword; var hFile: THandle) : THandle;
var
    lpFileMappingAttributes: PSecurityAttributes;
    flProtect           : DWORD;
    dwMaximumSizeHigh   : DWORD;
    dwMaximumSizeLow    : DWORD;
    lpName              : PChar;

    LastError : dword;
begin

    Result := INVALID_HANDLE_VALUE;

    if (maxSize > MaximumMapSize) then
        exit;

     // create a disk the file or return INVALID_HANDLE_VALUE if settings have not defined a path to folder
     hFile     :=  getFileHandle(mapname,maxSize);

     lpFileMappingAttributes := nil;
     flProtect          := PAGE_READWRITE;
     dwMaximumSizeHigh  := 0;
     dwMaximumSizeLow   := maxSize;
     lpName := PChar(mapname);

     Result := CreateFileMapping(
        hfile,
        lpFileMappingAttributes,
        flProtect,
        dwMaximumSizeHigh,
        dwMaximumSizeLow,
        lpName);

     if (Result = 0) then
     begin

         if (not (hFile = INVALID_HANDLE_VALUE) ) then
            CloseHandle(hFile);

         hFile := 0;
         LastError := GetLastError();
         ShowMessage( Format('Error %d : %s',[LastError,SysErrorMessage(LastError)]) );

     end
     else
     begin

        ShowMessage(Format('Returing handle %d',[result]));
        if (hFile = INVALID_HANDLE_VALUE) then
            hFile := 0;

     end;

end;

Solution

  • The mistake is here:

    GENERIC_WRITE or GENERIC_WRITE
    

    You meant:

    GENERIC_READ or GENERIC_WRITE
    

    Fix that and your file mapping can be created.

    I agree with Hans that you should not be sharing the file handle.