From 160ab19ace0e595f20969ade8a9c9c5ba111bec2 Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Tue, 27 Aug 2002 01:56:08 +0000 Subject: [PATCH] Added a bunch of new regression tests. --- dlls/kernel/tests/.cvsignore | 1 + dlls/kernel/tests/Makefile.in | 1 + dlls/kernel/tests/directory.c | 90 ++++++++++++++++- dlls/kernel/tests/drive.c | 173 +++++++++++++++++++++++++++++++++ dlls/kernel/tests/file.c | 175 ++++++++++++++++++++++++++++++++++ dlls/kernel/tests/path.c | 164 +++++++++++++++++++++++++++++++ 6 files changed, 603 insertions(+), 1 deletion(-) create mode 100644 dlls/kernel/tests/drive.c diff --git a/dlls/kernel/tests/.cvsignore b/dlls/kernel/tests/.cvsignore index e4eb6390df1..4b9295b954a 100644 --- a/dlls/kernel/tests/.cvsignore +++ b/dlls/kernel/tests/.cvsignore @@ -2,6 +2,7 @@ Makefile alloc.ok atom.ok directory.ok +drive.ok environ.ok file.ok format_msg.ok diff --git a/dlls/kernel/tests/Makefile.in b/dlls/kernel/tests/Makefile.in index 515f2b47d5c..c6c4ea0032e 100644 --- a/dlls/kernel/tests/Makefile.in +++ b/dlls/kernel/tests/Makefile.in @@ -9,6 +9,7 @@ CTESTS = \ alloc.c \ atom.c \ directory.c \ + drive.c \ environ.c \ file.c \ format_msg.c \ diff --git a/dlls/kernel/tests/directory.c b/dlls/kernel/tests/directory.c index 70b8ae89cc8..e0e41bdfaad 100644 --- a/dlls/kernel/tests/directory.c +++ b/dlls/kernel/tests/directory.c @@ -20,7 +20,7 @@ #include "wine/test.h" #include "winbase.h" - +#include "winerror.h" /* If you change something in these tests, please do the same * for GetSystemDirectory tests. @@ -119,10 +119,98 @@ static void test_GetSystemDirectoryW(void) ok(len == (len_with_null - 1), "should return length without terminating 0"); } +static void test_CreateDirectoryA(void) +{ + char tmpdir[MAX_PATH]; + BOOL ret; + + ret = CreateDirectoryA(NULL, NULL); + ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create NULL path"); + + ret = CreateDirectoryA("", NULL); + ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create empty path"); + + ret = GetSystemDirectoryA(tmpdir, MAX_PATH); + ok(ret < MAX_PATH, "System directory should fit into MAX_PATH"); + + ret = SetCurrentDirectoryA(tmpdir); + ok(ret == TRUE, "could not chdir to the System directory"); + + ret = CreateDirectoryA(".", NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + ret = CreateDirectoryA("..", NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + GetTempPathA(MAX_PATH, tmpdir); + tmpdir[3] = 0; /* truncate the path */ + ret = CreateDirectoryA(tmpdir, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "should deny access to the drive root"); + + GetTempPathA(MAX_PATH, tmpdir); + lstrcatA(tmpdir, "Please Remove Me"); + ret = CreateDirectoryA(tmpdir, NULL); + ok(ret == TRUE, "CreateDirectoryA should always succeed"); + + ret = CreateDirectoryA(tmpdir, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + ret = RemoveDirectoryA(tmpdir); + ok(ret == TRUE, "RemoveDirectoryA should always succeed"); +} + +static void test_CreateDirectoryW(void) +{ + WCHAR tmpdir[MAX_PATH]; + BOOL ret; + static const WCHAR empty_strW[] = { 0 }; + static const WCHAR tmp_dir_name[] = {'P','l','e','a','s','e',' ','R','e','m','o','v','e',' ','M','e',0}; + static const WCHAR dotW[] = {'.',0}; + static const WCHAR dotdotW[] = {'.','.',0}; + + ret = CreateDirectoryW(NULL, NULL); + ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create NULL path"); + + ret = CreateDirectoryW(empty_strW, NULL); + ok(ret == FALSE && GetLastError() == ERROR_PATH_NOT_FOUND, "should not create empty path"); + + ret = GetSystemDirectoryW(tmpdir, MAX_PATH); + ok(ret < MAX_PATH, "System directory should fit into MAX_PATH"); + + ret = SetCurrentDirectoryW(tmpdir); + ok(ret == TRUE, "could not chdir to the System directory"); + + ret = CreateDirectoryW(dotW, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + ret = CreateDirectoryW(dotdotW, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + GetTempPathW(MAX_PATH, tmpdir); + tmpdir[3] = 0; /* truncate the path */ + ret = CreateDirectoryW(tmpdir, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ACCESS_DENIED, "should deny access to the drive root"); + + GetTempPathW(MAX_PATH, tmpdir); + lstrcatW(tmpdir, tmp_dir_name); + ret = CreateDirectoryW(tmpdir, NULL); + ok(ret == TRUE, "CreateDirectoryW should always succeed"); + + ret = CreateDirectoryW(tmpdir, NULL); + ok(ret == FALSE && GetLastError() == ERROR_ALREADY_EXISTS, "should not create existing path"); + + ret = RemoveDirectoryW(tmpdir); + ok(ret == TRUE, "RemoveDirectoryW should always succeed"); +} + START_TEST(directory) { test_GetWindowsDirectoryA(); test_GetWindowsDirectoryW(); + test_GetSystemDirectoryA(); test_GetSystemDirectoryW(); + + test_CreateDirectoryA(); + test_CreateDirectoryW(); } diff --git a/dlls/kernel/tests/drive.c b/dlls/kernel/tests/drive.c new file mode 100644 index 00000000000..a6cc42b2e7b --- /dev/null +++ b/dlls/kernel/tests/drive.c @@ -0,0 +1,173 @@ +/* + * Unit test suite for drive functions. + * + * Copyright 2002 Dmitry Timoshkov + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "wine/test.h" +#include "winbase.h" +#include "winerror.h" + +void test_GetDriveTypeA(void) +{ + char drive[] = "?:\\"; + DWORD logical_drives; + UINT type; + + logical_drives = GetLogicalDrives(); + ok(logical_drives != 0, "GetLogicalDrives error %ld", GetLastError()); + + for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) + { + type = GetDriveTypeA(drive); + ok(type > 0 && type <= 6, "not a valid drive %c: type %u", drive[0], type); + + if (!(logical_drives & 1)) + ok(type == DRIVE_NO_ROOT_DIR, + "GetDriveTypeA should return DRIVE_NO_ROOT_DIR for a not existing drive %c: but not %u", + drive[0], type); + + logical_drives >>= 1; + } +} + +void test_GetDriveTypeW(void) +{ + WCHAR drive[] = {'?',':','\\',0}; + DWORD logical_drives; + UINT type; + + logical_drives = GetLogicalDrives(); + ok(logical_drives != 0, "GetLogicalDrives error %ld", GetLastError()); + + for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) + { + type = GetDriveTypeW(drive); + ok(type > 0 && type <= 6, "not a valid drive %c: type %u", drive[0], type); + + if (!(logical_drives & 1)) + ok(type == DRIVE_NO_ROOT_DIR, + "GetDriveTypeW should return DRIVE_NO_ROOT_DIR for a not existing drive %c: but not %u", + drive[0], type); + + logical_drives >>= 1; + } +} + +void test_GetDiskFreeSpaceA(void) +{ + BOOL ret; + DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters; + char drive[] = "?:\\"; + DWORD logical_drives; + + ret = GetDiskFreeSpaceA(NULL, NULL, NULL, NULL, NULL); + ok(ret, "GetDiskFreeSpaceA error %ld", GetLastError()); + + ret = GetDiskFreeSpaceA(NULL, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceA error %ld", GetLastError()); + + ret = GetDiskFreeSpaceA("", §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "GetDiskFreeSpaceA should return ERROR_PATH_NOT_FOUND for \"\""); + + ret = GetDiskFreeSpaceA("\\", §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceA error %ld", GetLastError()); + + ret = GetDiskFreeSpaceA("/", §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceA error %ld", GetLastError()); + + ret = GetDiskFreeSpaceA(".", §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_INVALID_NAME, "GetDiskFreeSpaceA should return ERROR_INVALID_NAME for \".\""); + + ret = GetDiskFreeSpaceA("..", §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_INVALID_NAME, "GetDiskFreeSpaceA should return ERROR_INVALID_NAME for \"..\""); + + logical_drives = GetLogicalDrives(); + ok(logical_drives != 0, "GetLogicalDrives error %ld", GetLastError()); + + for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) + { + ret = GetDiskFreeSpaceA(drive, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + if (!(logical_drives & 1)) + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, + "GetDiskFreeSpaceA should return ERROR_PATH_NOT_FOUND for a not existing drive %c", + drive[0]); + else + ok(ret, "GetDiskFreeSpaceA error %ld", GetLastError()); + + logical_drives >>= 1; + } +} + +void test_GetDiskFreeSpaceW(void) +{ + BOOL ret; + DWORD sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters; + WCHAR drive[] = {'?',':','\\',0}; + DWORD logical_drives; + static const WCHAR empty_pathW[] = { 0 }; + static const WCHAR root_pathW[] = { '\\', 0 }; + static const WCHAR unix_style_root_pathW[] = { '/', 0 }; + static const WCHAR cur_dirW[] = { '.', 0 }; + static const WCHAR upper_dirW[] = { '.','.', 0 }; + + ret = GetDiskFreeSpaceW(NULL, NULL, NULL, NULL, NULL); + ok(ret, "GetDiskFreeSpaceW error %ld", GetLastError()); + + ret = GetDiskFreeSpaceW(NULL, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceW error %ld", GetLastError()); + + ret = GetDiskFreeSpaceW(empty_pathW, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, "GetDiskFreeSpaceW should return ERROR_PATH_NOT_FOUND for \"\""); + + ret = GetDiskFreeSpaceW(root_pathW, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceW error %ld", GetLastError()); + + ret = GetDiskFreeSpaceW(unix_style_root_pathW, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(ret, "GetDiskFreeSpaceW error %ld", GetLastError()); + + ret = GetDiskFreeSpaceW(cur_dirW, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_INVALID_NAME, "GetDiskFreeSpaceW should return ERROR_INVALID_NAME for \".\""); + + ret = GetDiskFreeSpaceW(upper_dirW, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + ok(!ret && GetLastError() == ERROR_INVALID_NAME, "GetDiskFreeSpaceW should return ERROR_INVALID_NAME for \"..\""); + + logical_drives = GetLogicalDrives(); + ok(logical_drives != 0, "GetLogicalDrives error %ld", GetLastError()); + + for (drive[0] = 'A'; drive[0] <= 'Z'; drive[0]++) + { + ret = GetDiskFreeSpaceW(drive, §ors_per_cluster, &bytes_per_sector, &free_clusters, &total_clusters); + if (!(logical_drives & 1)) + ok(!ret && GetLastError() == ERROR_PATH_NOT_FOUND, + "GetDiskFreeSpaceW should return ERROR_PATH_NOT_FOUND for a not existing drive %c", + drive[0]); + else + ok(ret, "GetDiskFreeSpaceW error %ld", GetLastError()); + + logical_drives >>= 1; + } +} + +START_TEST(drive) +{ + test_GetDriveTypeA(); + test_GetDriveTypeW(); + + test_GetDiskFreeSpaceA(); + test_GetDiskFreeSpaceW(); +} diff --git a/dlls/kernel/tests/file.c b/dlls/kernel/tests/file.c index 95c3dcd7e92..ef14e63388e 100644 --- a/dlls/kernel/tests/file.c +++ b/dlls/kernel/tests/file.c @@ -463,6 +463,176 @@ static void test__lwrite( void ) ok( DeleteFileA( filename ) != 0, "DeleteFile failed (%ld)", GetLastError( ) ); } +void test_CopyFileA(void) +{ + char temp_path[MAX_PATH]; + char source[MAX_PATH], dest[MAX_PATH]; + static const char prefix[] = "pfx"; + DWORD ret; + + ret = GetTempPathA(MAX_PATH, temp_path); + ok(ret != 0, "GetTempPathA error %ld", GetLastError()); + ok(ret < MAX_PATH, "temp path should fit into MAX_PATH"); + + ret = GetTempFileNameA(temp_path, prefix, 0, source); + ok(ret != 0, "GetTempFileNameA error %ld", GetLastError()); + + ret = GetTempFileNameA(temp_path, prefix, 0, dest); + ok(ret != 0, "GetTempFileNameA error %ld", GetLastError()); + + ret = CopyFileA(source, dest, TRUE); + ok(!ret && GetLastError() == ERROR_FILE_EXISTS, + "CopyFileA: unexpected error %ld\n", GetLastError()); + + ret = CopyFileA(source, dest, FALSE); + ok(ret, "CopyFileA: error %ld\n", GetLastError()); + + ret = DeleteFileA(source); + ok(ret, "DeleteFileA: error %ld\n", GetLastError()); + ret = DeleteFileA(dest); + ok(ret, "DeleteFileA: error %ld\n", GetLastError()); +} + +void test_CopyFileW(void) +{ + WCHAR temp_path[MAX_PATH]; + WCHAR source[MAX_PATH], dest[MAX_PATH]; + static const WCHAR prefix[] = {'p','f','x',0}; + DWORD ret; + + ret = GetTempPathW(MAX_PATH, temp_path); + ok(ret != 0, "GetTempPathW error %ld", GetLastError()); + ok(ret < MAX_PATH, "temp path should fit into MAX_PATH"); + + ret = GetTempFileNameW(temp_path, prefix, 0, source); + ok(ret != 0, "GetTempFileNameW error %ld", GetLastError()); + + ret = GetTempFileNameW(temp_path, prefix, 0, dest); + ok(ret != 0, "GetTempFileNameW error %ld", GetLastError()); + + ret = CopyFileW(source, dest, TRUE); + ok(!ret && GetLastError() == ERROR_FILE_EXISTS, + "CopyFileW: unexpected error %ld\n", GetLastError()); + + ret = CopyFileW(source, dest, FALSE); + ok(ret, "CopyFileW: error %ld\n", GetLastError()); + + ret = DeleteFileW(source); + ok(ret, "DeleteFileW: error %ld\n", GetLastError()); + ret = DeleteFileW(dest); + ok(ret, "DeleteFileW: error %ld\n", GetLastError()); +} + +void test_CreateFileA(void) +{ + HANDLE hFile; + char temp_path[MAX_PATH]; + char filename[MAX_PATH]; + static const char prefix[] = "pfx"; + DWORD ret; + + ret = GetTempPathA(MAX_PATH, temp_path); + ok(ret != 0, "GetTempPathA error %ld", GetLastError()); + ok(ret < MAX_PATH, "temp path should fit into MAX_PATH"); + + ret = GetTempFileNameA(temp_path, prefix, 0, filename); + ok(ret != 0, "GetTempFileNameA error %ld", GetLastError()); + + hFile = CreateFileA(filename, GENERIC_READ, 0, NULL, + CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); + ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS, + "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS"); + + ret = DeleteFileA(filename); + ok(ret, "DeleteFileA: error %ld\n", GetLastError()); +} + +void test_CreateFileW(void) +{ + HANDLE hFile; + WCHAR temp_path[MAX_PATH]; + WCHAR filename[MAX_PATH]; + static const WCHAR prefix[] = {'p','f','x',0}; + DWORD ret; + + ret = GetTempPathW(MAX_PATH, temp_path); + ok(ret != 0, "GetTempPathW error %ld", GetLastError()); + ok(ret < MAX_PATH, "temp path should fit into MAX_PATH"); + + ret = GetTempFileNameW(temp_path, prefix, 0, filename); + ok(ret != 0, "GetTempFileNameW error %ld", GetLastError()); + + hFile = CreateFileW(filename, GENERIC_READ, 0, NULL, + CREATE_NEW, FILE_FLAG_RANDOM_ACCESS, 0); + ok(hFile == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_EXISTS, + "CREATE_NEW should fail if file exists and last error value should be ERROR_FILE_EXISTS"); + + ret = DeleteFileW(filename); + ok(ret, "DeleteFileW: error %ld\n", GetLastError()); +} + +#define PATTERN_OFFSET 0x10 + +void test_offset_in_overlapped_structure(void) +{ + HANDLE hFile; + OVERLAPPED ov; + DWORD done; + BYTE buf[256], pattern[] = "TeSt"; + UINT i; + char temp_path[MAX_PATH], temp_fname[MAX_PATH]; + + ok(GetTempPathA(MAX_PATH, temp_path) != 0, "GetTempPathA error %ld", GetLastError()); + ok(GetTempFileNameA(temp_path, "pfx", 0, temp_fname) != 0, "GetTempFileNameA error %ld", GetLastError()); + + /*** Write File *****************************************************/ + + hFile = CreateFileA(temp_fname, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %ld", GetLastError()); + + for(i = 0; i < sizeof(buf); i++) buf[i] = i; + ok(WriteFile(hFile, buf, sizeof(buf), &done, NULL), "WriteFile error %ld", GetLastError()); + ok(done == sizeof(buf), "expected number of bytes written %lu", done); + + memset(&ov, 0, sizeof(ov)); + ov.Offset = PATTERN_OFFSET; + ov.OffsetHigh = 0; + ok(WriteFile(hFile, pattern, sizeof(pattern), &done, &ov), "WriteFile error %ld", GetLastError()); + ok(done == sizeof(pattern), "expected number of bytes written %lu", done); + trace("Current offset = %04lx\n", SetFilePointer(hFile, 0, NULL, FILE_CURRENT)); + ok(SetFilePointer(hFile, 0, NULL, FILE_CURRENT) == (PATTERN_OFFSET + sizeof(pattern)), + "expected file offset %d", PATTERN_OFFSET + sizeof(pattern)); + + ov.Offset = sizeof(buf) * 2; + ov.OffsetHigh = 0; + ok(WriteFile(hFile, pattern, sizeof(pattern), &done, &ov), "WriteFile error %ld", GetLastError()); + ok(done == sizeof(pattern), "expected number of bytes written %lu", done); + /*trace("Current offset = %04lx\n", SetFilePointer(hFile, 0, NULL, FILE_CURRENT));*/ + ok(SetFilePointer(hFile, 0, NULL, FILE_CURRENT) == (sizeof(buf) * 2 + sizeof(pattern)), + "expected file offset %d", sizeof(buf) * 2 + sizeof(pattern)); + + CloseHandle(hFile); + + /*** Read File *****************************************************/ + + hFile = CreateFileA(temp_fname, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); + ok(hFile != INVALID_HANDLE_VALUE, "CreateFileA error %ld", GetLastError()); + + memset(buf, 0, sizeof(buf)); + memset(&ov, 0, sizeof(ov)); + ov.Offset = PATTERN_OFFSET; + ov.OffsetHigh = 0; + ok(ReadFile(hFile, buf, sizeof(pattern), &done, &ov), "ReadFile error %ld", GetLastError()); + ok(done == sizeof(pattern), "expected number of bytes read %lu", done); + trace("Current offset = %04lx\n", SetFilePointer(hFile, 0, NULL, FILE_CURRENT)); + ok(SetFilePointer(hFile, 0, NULL, FILE_CURRENT) == (PATTERN_OFFSET + sizeof(pattern)), + "expected file offset %d", PATTERN_OFFSET + sizeof(pattern)); + ok(!memcmp(buf, pattern, sizeof(pattern)), "pattern match failed"); + + CloseHandle(hFile); + + ok(DeleteFileA(temp_fname), "DeleteFileA error %ld\n", GetLastError()); +} START_TEST(file) { @@ -474,4 +644,9 @@ START_TEST(file) test__llopen( ); test__lread( ); test__lwrite( ); + test_CopyFileA(); + test_CopyFileW(); + test_CreateFileA(); + test_CreateFileW(); + test_offset_in_overlapped_structure(); } diff --git a/dlls/kernel/tests/path.c b/dlls/kernel/tests/path.c index af3248a8069..29ae72b4a13 100644 --- a/dlls/kernel/tests/path.c +++ b/dlls/kernel/tests/path.c @@ -795,6 +795,169 @@ static void test_PathNameA(CHAR *curdir, CHAR curDrive, CHAR otherDrive) test_FunnyChars(curdir,"Long File :" ,0,0,"check-7"); } +static void test_GetTempPathA(void) +{ + UINT len, len_with_null; + char buf[MAX_PATH]; + + lstrcpyA(buf, "foo"); + len = GetTempPathA(MAX_PATH, buf); + ok(len <= MAX_PATH, "should fit into MAX_PATH"); + ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer"); + ok(len == lstrlenA(buf), "returned length should be equal to the length of string"); + ok(buf[len - 1] == '\\', "should add back slash"); + + len_with_null = lstrlenA(buf) + 1; + + /* this one is different from unicode version: ANSI version doesn't + * touch the buffer, unicode version truncates the buffer to zero size + */ + lstrcpyA(buf, "foo"); + len = GetTempPathA(1, buf); + ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer"); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(len == len_with_null, "win2000 BUG: expected %u, got %u", len_with_null, len); + + /* this one is different from unicode version: ANSI version doesn't + * touch the buffer, unicode version returns path without backslash + */ + lstrcpyA(buf, "foo"); + len = GetTempPathA(len_with_null - 1, buf); + ok(lstrcmpA(buf, "foo") == 0, "should not touch the buffer"); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(len == len_with_null, "win2000 BUG: expected %u, got %u", len_with_null, len); + + lstrcpyA(buf, "foo"); + len = GetTempPathA(len_with_null, buf); + ok(lstrcmpA(buf, "foo") != 0, "should touch the buffer"); + ok(len == lstrlenA(buf), "returned length should be equal to the length of string"); + ok(buf[len - 1] == '\\', "should add back slash"); + ok(len == (len_with_null - 1), "should return length without terminating 0"); + + len = GetTempPathA(0, NULL); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(len == len_with_null, "win2000 BUG: expected %u, got %u", len_with_null, len); +} + +static void test_GetTempPathW(void) +{ + UINT len, len_with_null; + WCHAR buf[MAX_PATH]; + WCHAR sample[MAX_PATH]; + static const WCHAR fooW[] = {'f','o','o',0}; + + lstrcpyW(buf, fooW); + len = GetTempPathW(MAX_PATH, buf); + ok(len <= MAX_PATH, "should fit into MAX_PATH"); + ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer"); + ok(len == lstrlenW(buf), "returned length should be equal to the length of string"); + ok(buf[len - 1] == '\\', "should add back slash"); + + len_with_null = lstrlenW(buf) + 1; + lstrcpyW(sample, buf); + sample[len_with_null - 2] = 0; + + /* this one is different from ANSI version: ANSI version doesn't + * touch the buffer, unicode version truncates the buffer to zero size + */ + lstrcpyW(buf, fooW); + len = GetTempPathW(1, buf); + ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer"); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(len == len_with_null, "win2000 BUG: expected %u, got %u", len_with_null, len); + ok(buf[0] == 0, "unicode version should truncate the buffer to zero size"); + + /* this one is different from ANSI version: ANSI version doesn't + * touch the buffer, unicode version returns path without backslash + */ + lstrcpyW(buf, fooW); + len = GetTempPathW(len_with_null - 1, buf); + ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer"); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(len == len_with_null, "win2000 BUG: expected %u, got %u", len_with_null, len); + /* win2000 fails here when TMP variable does not specify full path, + * but buffer is large enough to hold path without backslash. + */ + if(len_with_null > 4) /* not the drive root: just do not add backslash */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(lstrcmpW(sample, buf) == 0, "win2000 BUG: should return path without terminating back slash"); + else /* drive root: truncate, to avoid returning ambiguous "X:" */ + /* FIXME: replace ok by xfail below when it's implemeted */ + ok(buf[0] == 0, "should truncate the buffer to zero size"); + + lstrcpyW(buf, fooW); + len = GetTempPathW(len_with_null, buf); + ok(lstrcmpW(buf, fooW) != 0, "should touch the buffer"); + ok(len == lstrlenW(buf), "returned length should be equal to the length of string"); + ok(buf[len - 1] == '\\', "should add back slash"); + ok(len == (len_with_null - 1), "should return length without terminating 0"); + + len = GetTempPathW(0, NULL); + /* win2000 adds excessive 0 when TMP variable does not specify full path, + * and buffer is not large enough to hold path with backslash. + * Therefore simple (len == len_with_null) fails. + */ + ok(len >= len_with_null, "should reserve space for terminating 0"); +} + +static void test_GetTempPath(void) +{ + char save_TMP[MAX_PATH]; + char windir[MAX_PATH]; + char buf[MAX_PATH]; + + GetEnvironmentVariableA("TMP", save_TMP, sizeof(save_TMP)); + + /* test default configuration */ + trace("TMP=%s\n", save_TMP); + test_GetTempPathA(); + test_GetTempPathW(); + + /* TMP=C:\WINDOWS */ + GetWindowsDirectoryA(windir, sizeof(windir)); + SetEnvironmentVariableA("TMP", windir); + GetEnvironmentVariableA("TMP", buf, sizeof(buf)); + trace("TMP=%s\n", buf); + test_GetTempPathA(); + test_GetTempPathW(); + + /* TMP=C:\ */ + GetWindowsDirectoryA(windir, sizeof(windir)); + windir[3] = 0; + SetEnvironmentVariableA("TMP", windir); + GetEnvironmentVariableA("TMP", buf, sizeof(buf)); + trace("TMP=%s\n", buf); + test_GetTempPathA(); + test_GetTempPathW(); + + /* TMP=C: i.e. use current working directory of the specified drive */ + GetWindowsDirectoryA(windir, sizeof(windir)); + SetCurrentDirectoryA(windir); + windir[2] = 0; + SetEnvironmentVariableA("TMP", windir); + GetEnvironmentVariableA("TMP", buf, sizeof(buf)); + trace("TMP=%s\n", buf); + test_GetTempPathA(); + test_GetTempPathW(); + + SetEnvironmentVariableA("TMP", save_TMP); +} + START_TEST(path) { CHAR origdir[MAX_PATH],curdir[MAX_PATH], curDrive, otherDrive; @@ -806,4 +969,5 @@ START_TEST(path) test_CurrentDirectoryA(origdir,curdir); test_PathNameA(curdir, curDrive, otherDrive); test_CleanupPathA(origdir,curdir); + test_GetTempPath(); }