file.c
来自「一个类似windows」· C语言 代码 · 共 1,422 行 · 第 1/4 页
C
1,422 行
ok( UnlockFile( handle, 90, 0, 10, 0 ), "UnlockFile 90,10 failed\n" );
!ok( UnlockFile( handle, 100, 0, 10, 0 ), "UnlockFile 100,10 failed\n" );
ok( UnlockFile( handle, 100, 0, 0, 0 ), "UnlockFile 100,0 failed\n" );
CloseHandle( handle );
DeleteFileA( filename );
}
static inline int is_sharing_compatible( DWORD access1, DWORD sharing1, DWORD access2, DWORD sharing2 )
{
if (!access1 || !access2) return 1;
if ((access1 & GENERIC_READ) && !(sharing2 & FILE_SHARE_READ)) return 0;
if ((access1 & GENERIC_WRITE) && !(sharing2 & FILE_SHARE_WRITE)) return 0;
if ((access2 & GENERIC_READ) && !(sharing1 & FILE_SHARE_READ)) return 0;
if ((access2 & GENERIC_WRITE) && !(sharing1 & FILE_SHARE_WRITE)) return 0;
return 1;
}
static void test_file_sharing(void)
{
static const DWORD access_modes[4] = { 0, GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE };
static const DWORD sharing_modes[4] = { 0, FILE_SHARE_READ, FILE_SHARE_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE };
int a1, s1, a2, s2;
int ret;
HANDLE h, h2;
/* make sure the file exists */
h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
if (h == INVALID_HANDLE_VALUE)
{
ok(0, "couldn't create file \"%s\" (err=%ld)\n", filename, GetLastError());
return;
}
CloseHandle( h );
for (a1 = 0; a1 < 4; a1++)
{
for (s1 = 0; s1 < 4; s1++)
{
h = CreateFileA( filename, access_modes[a1], sharing_modes[s1],
NULL, OPEN_EXISTING, 0, 0 );
if (h == INVALID_HANDLE_VALUE)
{
ok(0,"couldn't create file \"%s\" (err=%ld)\n",filename,GetLastError());
return;
}
for (a2 = 0; a2 < 4; a2++)
{
for (s2 = 0; s2 < 4; s2++)
{
SetLastError(0xdeadbeef);
h2 = CreateFileA( filename, access_modes[a2], sharing_modes[s2],
NULL, OPEN_EXISTING, 0, 0 );
if (is_sharing_compatible( access_modes[a1], sharing_modes[s1],
access_modes[a2], sharing_modes[s2] ))
{
ret = GetLastError();
ok( ERROR_SHARING_VIOLATION == ret || 0 == ret,
"Windows 95 sets GetLastError() = ERROR_SHARING_VIOLATION and\n"
" Windows XP GetLastError() = 0, but now it is %d.\n"
" indexes = %d, %d, %d, %d\n"
" modes =\n %lx/%lx/%lx/%lx\n",
ret,
a1, s1, a2, s2,
access_modes[a1], sharing_modes[s1],
access_modes[a2], sharing_modes[s2]
);
}
else
{
ok( h2 == INVALID_HANDLE_VALUE,
"open succeeded for modes %lx/%lx/%lx/%lx\n",
access_modes[a1], sharing_modes[s1],
access_modes[a2], sharing_modes[s2] );
if (h2 == INVALID_HANDLE_VALUE)
ok( GetLastError() == ERROR_SHARING_VIOLATION,
"wrong error code %ld\n", GetLastError() );
}
if (h2 != INVALID_HANDLE_VALUE) CloseHandle( h2 );
}
}
CloseHandle( h );
}
}
SetLastError(0xdeadbeef);
h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, 0 );
ok( h != INVALID_HANDLE_VALUE, "CreateFileA error %ld\n", GetLastError() );
SetLastError(0xdeadbeef);
h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
ok( h2 == INVALID_HANDLE_VALUE, "CreateFileA should fail\n");
ok( GetLastError() == ERROR_SHARING_VIOLATION, "wrong error code %ld\n", GetLastError() );
h2 = CreateFileA( filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 );
ok( h2 != INVALID_HANDLE_VALUE, "CreateFileA error %ld\n", GetLastError() );
CloseHandle(h);
CloseHandle(h2);
DeleteFileA( filename );
}
static char get_windows_drive(void)
{
char windowsdir[MAX_PATH];
GetWindowsDirectory(windowsdir, sizeof(windowsdir));
return windowsdir[0];
}
static void test_FindFirstFileA(void)
{
HANDLE handle;
WIN32_FIND_DATAA search_results;
int err;
char buffer[5] = "C:\\";
/* try FindFirstFileA on "C:\" */
buffer[0] = get_windows_drive();
handle = FindFirstFileA(buffer,&search_results);
err = GetLastError();
ok ( handle == INVALID_HANDLE_VALUE , "FindFirstFile on root directory should Fail\n");
if (handle == INVALID_HANDLE_VALUE)
ok ( err == ERROR_FILE_NOT_FOUND, "Bad Error number %d\n", err);
/* try FindFirstFileA on "C:\*" */
strcat(buffer, "*");
handle = FindFirstFileA(buffer,&search_results);
ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on %s should succeed\n", buffer );
ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
}
static void test_FindNextFileA(void)
{
HANDLE handle;
WIN32_FIND_DATAA search_results;
int err;
char buffer[5] = "C:\\*";
buffer[0] = get_windows_drive();
handle = FindFirstFileA(buffer,&search_results);
ok ( handle != INVALID_HANDLE_VALUE, "FindFirstFile on C:\\* should succeed\n" );
while (FindNextFile(handle, &search_results))
{
/* get to the end of the files */
}
ok ( FindClose(handle) == TRUE, "Failed to close handle\n");
err = GetLastError();
ok ( err == ERROR_NO_MORE_FILES, "GetLastError should return ERROR_NO_MORE_FILES\n");
}
static int test_Mapfile_createtemp(HANDLE *handle)
{
SetFileAttributesA(filename,FILE_ATTRIBUTE_NORMAL);
DeleteFile(filename);
*handle = CreateFile(filename, GENERIC_READ|GENERIC_WRITE, 0, 0,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (*handle != INVALID_HANDLE_VALUE) {
return 1;
}
return 0;
}
static void test_MapFile(void)
{
HANDLE handle;
HANDLE hmap;
ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0x1000, "named_file_map" );
ok( hmap != NULL, "mapping should work, I named it!\n" );
ok( CloseHandle( hmap ), "can't close mapping handle\n");
/* We have to close file before we try new stuff with mapping again.
Else we would always succeed on XP or block descriptors on 95. */
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
ok( hmap != NULL, "We should still be able to map!\n" );
ok( CloseHandle( hmap ), "can't close mapping handle\n");
ok( CloseHandle( handle ), "can't close file handle\n");
handle = NULL;
ok(test_Mapfile_createtemp(&handle), "Couldn't create test file.\n");
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0, 0, NULL );
ok( hmap == NULL, "mapped zero size file\n");
ok( GetLastError() == ERROR_FILE_INVALID, "not ERROR_FILE_INVALID\n");
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x1000, 0, NULL );
ok( hmap == NULL, "mapping should fail\n");
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
hmap = CreateFileMapping( handle, NULL, PAGE_READWRITE, 0x1000, 0x10000, NULL );
ok( hmap == NULL, "mapping should fail\n");
/* GetLastError() varies between win9x and WinNT and also depends on the filesystem */
/* On XP you can now map again, on Win 95 you cannot. */
ok( CloseHandle( handle ), "can't close file handle\n");
ok( DeleteFileA( filename ), "DeleteFile failed after map\n" );
}
static void test_GetFileType(void)
{
DWORD type;
HANDLE h = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
ok( h != INVALID_HANDLE_VALUE, "open %s failed\n", filename );
type = GetFileType(h);
ok( type == FILE_TYPE_DISK, "expected type disk got %ld\n", type );
CloseHandle( h );
h = CreateFileA( "nul", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0 );
ok( h != INVALID_HANDLE_VALUE, "open nul failed\n" );
type = GetFileType(h);
ok( type == FILE_TYPE_CHAR, "expected type char for nul got %ld\n", type );
CloseHandle( h );
DeleteFileA( filename );
}
static int completion_count;
static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
{
/* printf("(%ld, %ld, %p { %ld, %ld, %ld, %ld, %p })\n", dwError, dwBytes, ovl, ovl->Internal, ovl->InternalHigh, ovl->Offset, ovl->OffsetHigh, ovl->hEvent);*/
ReleaseSemaphore(ovl->hEvent, 1, NULL);
completion_count++;
}
static void test_async_file_errors(void)
{
char szFile[MAX_PATH];
HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
HANDLE hFile;
LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
OVERLAPPED ovl;
ovl.Offset = 0;
ovl.OffsetHigh = 0;
ovl.hEvent = hSem;
completion_count = 0;
szFile[0] = '\0';
GetWindowsDirectoryA(szFile, sizeof(szFile)/sizeof(szFile[0])-1-strlen("\\win.ini"));
strcat(szFile, "\\win.ini");
hFile = CreateFileA(szFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
ok(hFile != NULL, "CreateFileA(%s ...) failed\n", szFile);
while (TRUE)
{
BOOL res;
while (WaitForSingleObjectEx(hSem, INFINITE, TRUE) == WAIT_IO_COMPLETION)
;
res = ReadFileEx(hFile, lpBuffer, 4096, &ovl, FileIOComplete);
/*printf("Offset = %ld, result = %s\n", ovl.Offset, res ? "TRUE" : "FALSE");*/
if (!res)
break;
ovl.Offset += 4096;
/* i/o completion routine only called if ReadFileEx returned success.
* we only care about violations of this rule so undo what should have
* been done */
completion_count--;
}
ok(completion_count == 0, "completion routine should only be called when ReadFileEx succeeds (this rule was violated %d times)\n", completion_count);
/*printf("Error = %ld\n", GetLastError());*/
}
static void test_read_write(void)
{
DWORD bytes, ret;
HANDLE hFile;
char temp_path[MAX_PATH];
char filename[MAX_PATH];
static const char prefix[] = "pfx";
ret = GetTempPathA(MAX_PATH, temp_path);
ok(ret != 0, "GetTempPathA error %ld\n", GetLastError());
ok(ret < MAX_PATH, "temp path should fit into MAX_PATH\n");
ret = GetTempFileNameA(temp_path, prefix, 0, filename);
ok(ret != 0, "GetTempFileNameA error %ld\n", GetLastError());
hFile = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_RANDOM_ACCESS, 0);
ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA: error %ld\n", GetLastError());
SetLastError(12345678);
bytes = 12345678;
ret = WriteFile(hFile, NULL, 0, &bytes, NULL);
ok(ret && GetLastError() == 12345678,
"ret = %ld, error %ld\n", ret, GetLastError());
ok(!bytes, "bytes = %ld\n", bytes);
SetLastError(12345678);
bytes = 12345678;
ret = WriteFile(hFile, NULL, 10, &bytes, NULL);
ok((!ret && GetLastError() == ERROR_INVALID_USER_BUFFER) || /* Win2k */
(ret && GetLastError() == 12345678), /* Win9x */
"ret = %ld, error %ld\n", ret, GetLastError());
ok(!bytes || /* Win2k */
bytes == 10, /* Win9x */
"bytes = %ld\n", bytes);
SetLastError(12345678);
bytes = 12345678;
ret = ReadFile(hFile, NULL, 0, &bytes, NULL);
ok(ret && GetLastError() == 12345678,
"ret = %ld, error %ld\n", ret, GetLastError());
ok(!bytes, "bytes = %ld\n", bytes);
SetLastError(12345678);
bytes = 12345678;
ret = ReadFile(hFile, NULL, 10, &bytes, NULL);
ok(!ret && (GetLastError() == ERROR_NOACCESS || /* Win2k */
GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
"ret = %ld, error %ld\n", ret, GetLastError());
ok(!bytes, "bytes = %ld\n", bytes);
ret = CloseHandle(hFile);
ok( ret, "CloseHandle: error %ld\n", GetLastError());
ret = DeleteFileA(filename);
ok( ret, "DeleteFileA: error %ld\n", GetLastError());
}
START_TEST(file)
{
test__hread( );
test__hwrite( );
test__lclose( );
test__lcreat( );
test__llseek( );
test__llopen( );
test__lread( );
test__lwrite( );
test_GetTempFileNameA();
test_CopyFileA();
test_CopyFileW();
test_CreateFileA();
test_CreateFileW();
test_DeleteFileA();
test_DeleteFileW();
test_MoveFileA();
test_MoveFileW();
test_FindFirstFileA();
test_FindNextFileA();
test_LockFile();
test_file_sharing();
test_offset_in_overlapped_structure();
test_MapFile();
test_GetFileType();
test_async_file_errors();
test_read_write();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?