Incompatibility in Kernel32

Ben Peddell klightspeed at netspace.net.au
Sat Jun 23 04:21:45 CDT 2012


On 22/06/2012 7:23 PM, robert.van.herk at serioustoys.com wrote:
>>> Is there any reason that you call DeleteFile() on a still being opened file?
>>
>> That's the whole point of this test. The observed behavior is that you can pass a
>> filename to MsiRecordSetStream, successfully delete the file, and keep on using the
>> stream.
> 
> I think DeleteFile on a opened file is officially allowed in Windows. Although the MS documentation is vague:
> 
> <QUOTE>
> The DeleteFile function fails if an application attempts to delete a file that is open for normal I/O or as a memory-mapped file.
> 
> The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.
> </QUOTE>

The first statement is true under the DOS-based Windows systems -
DeleteFile fails with ERROR_ACCESS_DENIED when that file has one or more
open file handles.

The second statement is true under the NT Windows systems - DeleteFile
will fail with ERROR_SHARING_VIOLATION if at least one handle to it
isn't opened with FILE_SHARE_DELETE, and ERROR_ACCESS_DENIED if it has a
memory mapping.

Results from the attached test under Windows 7 x64:

Testing with no sharing, same process and no file mapping
DeleteFile: Failed : 00000020
Done

Testing with FILE_SHARE_DELETE, same process and no file mapping
DeleteFile: OK
Done

Testing with no sharing, separate process and no file mapping
DeleteFile: Failed : 00000020
Done

Testing with FILE_SHARE_DELETE, separate process and no file mapping
DeleteFile: OK
Done

Testing with no sharing, same process and file mapping
DeleteFile: Failed : 00000020
Done

Testing with FILE_SHARE_DELETE, same process and file mapping
DeleteFile: Failed : 00000005
Done

Testing with no sharing, separate process and file mapping
DeleteFile: Failed : 00000020
Done

Testing with FILE_SHARE_DELETE, separate process and file mapping
DeleteFile: Failed : 00000005
Done

Results from the attached test under Windows 98 SE:

Testing with no sharing, same process and no file mapping
DeleteFile: Failed : 00000005
Done

Testing with FILE_SHARE_DELETE, same process and no file mapping
CreateFile failed : 00000057
DeleteFile: OK
Done

Testing with no sharing, separate process and no file mapping
DeleteFile: Failed : 00000005
Done

Testing with FILE_SHARE_DELETE, separate process and no file mapping
CreateFile failed : 00000057
DeleteFile: OK
Done

Testing with no sharing, same process and file mapping
DeleteFile: Failed : 00000005
Done

Testing with FILE_SHARE_DELETE, same process and file mapping
CreateFile failed : 00000057
DeleteFile: OK
Done

Testing with no sharing, separate process and file mapping
DeleteFile: Failed : 00000005
Done

Testing with FILE_SHARE_DELETE, separate process and file mapping
CreateFile failed : 00000057
DeleteFile: OK
Done

-- 
Ben Peddell
IT Support Bowen, Collinsville and Proserpine Catholic schools
http://klightspeed.killerwolves.net/

-------------- next part --------------
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <process.h>

#define dbgprint(...) \
    fprintf(stdout, __VA_ARGS__); \
    fflush(stdout)

#define dbgerror(...) \
    fprintf(stdout, __VA_ARGS__); \
    fprintf(stdout, " : %08X\n", GetLastError()); \
    fflush(stdout)

void TestDeleteFile(char *infilename, BOOL do_open, BOOL do_share, BOOL do_map, char *progname){
  DWORD n;
  static char filename[MAX_PATH];
  static char readback[MAX_PATH];
  void *fileview = NULL;
  HANDLE h = 0;
  HANDLE hmap = 0;

  if (infilename != NULL){
    strncpy(filename, infilename, MAX_PATH);
    filename[MAX_PATH - 1] = 0;
  } else {
    GetTempFileNameA(".", "test", 0, filename);
  }

  if (do_open){
    h = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, do_share ? FILE_SHARE_DELETE : 0, NULL, OPEN_EXISTING, 0, 0);
    if (h == 0 || h == INVALID_HANDLE_VALUE){
      dbgerror("CreateFile failed");
    }

    if (h != 0 && h != INVALID_HANDLE_VALUE){
      if (!WriteFile(h, filename, sizeof(filename), &n, NULL)){
        dbgerror("WriteFile failed after writing %d bytes", n);
      }

      SetFilePointer(h, 0, NULL, FILE_BEGIN);

      if (do_map){
        hmap = CreateFileMapping(h, NULL, PAGE_READWRITE, 0, 0, NULL);
        if (hmap == 0 || hmap == INVALID_HANDLE_VALUE){
          dbgerror("CreateFileMapping failed");
        }

        if (hmap != 0 && hmap != INVALID_HANDLE_VALUE){
          fileview = MapViewOfFile(hmap, FILE_MAP_WRITE, 0, 0, 0);
          if (fileview == NULL){
            dbgerror("MapViewOfFile failed");
          }
        }
      }
    }
  }
  
  if (progname != NULL){
    _spawnl(_P_WAIT, progname, progname, filename, NULL);
  } else {
    dbgprint("DeleteFile: ");
    if (!DeleteFile(filename)) {
      dbgerror("Failed");
    } else {
      dbgprint("OK\n");
    }
  }

  if (h != 0 && h != INVALID_HANDLE_VALUE){
    if (!ReadFile(h, readback, sizeof(readback), &n, NULL)){
      dbgerror("ReadFile failed after reading %d bytes", n);
    }

    if (memcmp(filename, readback, n)){
      dbgprint("Readback did not match data originally written\n");
    }
  }

  if (fileview != NULL){
    UnmapViewOfFile(fileview);
  }

  if (hmap != 0 && hmap != INVALID_HANDLE_VALUE){
    CloseHandle(hmap);
  }

  if (h != 0 && h != INVALID_HANDLE_VALUE){
    CloseHandle(h);
  }

  if (infilename == NULL){
    DeleteFile(filename);
  }
}

int main (int argc, char **argv){
  if (argc == 2){
    TestDeleteFile(argv[1], FALSE, FALSE, FALSE, NULL);
  } else {
    int i;
    for (i = 0; i < 8; i++){
      dbgprint(
          "Testing with %s, %s and %s\n", 
          (i & 1) ? "FILE_SHARE_DELETE" : "no sharing",
          (i & 2) ? "separate process": "same process",
          (i & 4) ? "file mapping" : "no file mapping"
      );
      TestDeleteFile(
          NULL,
          TRUE,
          (i & 1) ? TRUE : FALSE,
          (i & 4) ? TRUE : FALSE,
          (i & 2) ? argv[0] : NULL
      );
      dbgprint("Done\n\n");
    }
  }

  return 0;
}



More information about the wine-devel mailing list