static void test_NtQueryDirectoryFile(void) { OBJECT_ATTRIBUTES attr; UNICODE_STRING ntdirname; char testdirA[MAX_PATH]; WCHAR testdirW[MAX_PATH]; /* Clean up from prior aborted run, if any, then set up test files */ ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n"); strcat(testdirA, "NtQueryDirectoryFile.tmp"); tear_down_attribute_test(testdirA); set_up_attribute_test(testdirA); pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1); if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL)) { ok(0, "RtlDosPathNametoNtPathName_U failed\n"); goto done; } InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL); test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, FALSE, FALSE); test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, TRUE, FALSE); done: tear_down_attribute_test(testdirA); pRtlFreeUnicodeString(&ntdirname); }
/* Create a test directory full of attribute test files, clear counts */ static void set_up_attribute_test(const char *testdirA) { int i; BOOL ret; ret = CreateDirectoryA(testdirA, NULL); ok(ret, "couldn't create dir '%s', error %d\n", testdirA, GetLastError()); for (i=0; testfiles[i].name; i++) { char buf[MAX_PATH]; pRtlMultiByteToUnicodeN(testfiles[i].nameW, sizeof(testfiles[i].nameW), NULL, testfiles[i].name, strlen(testfiles[i].name)+1); if (strcmp(testfiles[i].name, ".") == 0 || strcmp(testfiles[i].name, "..") == 0) continue; sprintf(buf, "%s\\%s", testdirA, testfiles[i].name); if (testfiles[i].attr & FILE_ATTRIBUTE_DIRECTORY) { ret = CreateDirectoryA(buf, NULL); ok(ret, "couldn't create dir '%s', error %d\n", buf, GetLastError()); } else { HANDLE h = CreateFileA(buf, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, testfiles[i].attr, 0); ok( h != INVALID_HANDLE_VALUE, "failed to create temp file '%s'\n", buf ); CloseHandle(h); } } }
static void test_RtlDetermineDosPathNameType_U(void) { struct test { const char *path; UINT ret; }; static const struct test tests[] = { { "\\\\foo", 1 }, { "//foo", 1 }, { "\\/foo", 1 }, { "/\\foo", 1 }, { "\\\\", 1 }, { "//", 1 }, { "c:\\foo", 2 }, { "c:/foo", 2 }, { "c://foo", 2 }, { "c:\\", 2 }, { "c:/", 2 }, { "c:foo", 3 }, { "c:f\\oo", 3 }, { "c:foo/bar", 3 }, { "\\foo", 4 }, { "/foo", 4 }, { "\\", 4 }, { "/", 4 }, { "foo", 5 }, { "", 5 }, { "\0:foo", 5 }, { "\\\\.\\foo", 6 }, { "//./foo", 6 }, { "/\\./foo", 6 }, { "\\\\.foo", 1 }, { "//.foo", 1 }, { "\\\\.", 7 }, { "//.", 7 }, { NULL, 0 } }; const struct test *test; WCHAR buffer[MAX_PATH]; UINT ret; if (!pRtlDetermineDosPathNameType_U) { win_skip("RtlDetermineDosPathNameType_U is not available\n"); return; } for (test = tests; test->path; test++) { pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 ); ret = pRtlDetermineDosPathNameType_U( buffer ); ok( ret == test->ret, "Wrong result %d/%d for %s\n", ret, test->ret, test->path ); } }
static void testSetHelper(LPWSTR* env, const char* var, const char* val, NTSTATUS ret, NTSTATUS alt) { WCHAR bvar[256], bval1[256], bval2[256]; UNICODE_STRING uvar; UNICODE_STRING uval; NTSTATUS nts; uvar.Length = strlen(var) * sizeof(WCHAR); uvar.MaximumLength = uvar.Length + sizeof(WCHAR); uvar.Buffer = bvar; pRtlMultiByteToUnicodeN( bvar, sizeof(bvar), NULL, var, strlen(var)+1 ); if (val) { uval.Length = strlen(val) * sizeof(WCHAR); uval.MaximumLength = uval.Length + sizeof(WCHAR); uval.Buffer = bval1; pRtlMultiByteToUnicodeN( bval1, sizeof(bval1), NULL, val, strlen(val)+1 ); } nts = pRtlSetEnvironmentVariable(env, &uvar, val ? &uval : NULL); ok(nts == ret || (alt && nts == alt), "Setting var %s=%s (%x/%x)\n", var, val, nts, ret); if (nts == STATUS_SUCCESS) { uval.Length = 0; uval.MaximumLength = sizeof(bval2); uval.Buffer = bval2; nts = pRtlQueryEnvironmentVariable_U(*env, &uvar, &uval); switch (nts) { case STATUS_SUCCESS: ok(lstrcmpW(bval1, bval2) == 0, "Cannot get value written to environment\n"); break; case STATUS_VARIABLE_NOT_FOUND: ok(val == NULL || broken(strchr(var,'=') != NULL), /* variable containing '=' may be set but not found again on NT4 */ "Couldn't find variable, but didn't delete it. val = %s\n", val); break; default: ok(0, "Wrong ret %u for %s\n", nts, var); break; } } }
static void testQuery(void) { struct test { const char *var; int len; NTSTATUS status; const char *val; NTSTATUS alt; }; static const struct test tests[] = { {"foo", 256, STATUS_SUCCESS, "toto"}, {"FoO", 256, STATUS_SUCCESS, "toto"}, {"foo=", 256, STATUS_VARIABLE_NOT_FOUND, NULL}, {"foo ", 256, STATUS_VARIABLE_NOT_FOUND, NULL}, {"foo", 1, STATUS_BUFFER_TOO_SMALL, "toto"}, {"foo", 3, STATUS_BUFFER_TOO_SMALL, "toto"}, {"foo", 4, STATUS_SUCCESS, "toto", STATUS_BUFFER_TOO_SMALL}, {"foo", 5, STATUS_SUCCESS, "toto"}, {"fooo", 256, STATUS_SUCCESS, "tutu"}, {"f", 256, STATUS_VARIABLE_NOT_FOUND, NULL}, {"g", 256, STATUS_SUCCESS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}, {"sr=an", 256, STATUS_SUCCESS, "ouo", STATUS_VARIABLE_NOT_FOUND}, {"sr", 256, STATUS_SUCCESS, "an=ouo"}, {"=oOH", 256, STATUS_SUCCESS, "III"}, {"", 256, STATUS_VARIABLE_NOT_FOUND, NULL}, {"nul", 256, STATUS_SUCCESS, ""}, {NULL, 0, 0, NULL} }; WCHAR bn[257]; WCHAR bv[257]; UNICODE_STRING name; UNICODE_STRING value; NTSTATUS nts; unsigned int i; for (i = 0; tests[i].var; i++) { const struct test *test = &tests[i]; name.Length = strlen(test->var) * 2; name.MaximumLength = name.Length + 2; name.Buffer = bn; value.Length = 0; value.MaximumLength = test->len * 2; value.Buffer = bv; bv[test->len] = '@'; pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->var, strlen(test->var)+1 ); nts = pRtlQueryEnvironmentVariable_U(small_env, &name, &value); ok( nts == test->status || (test->alt && nts == test->alt), "[%d]: Wrong status for '%s', expecting %x got %x\n", i, test->var, test->status, nts ); if (nts == test->status) switch (nts) { case STATUS_SUCCESS: pRtlMultiByteToUnicodeN( bn, sizeof(bn), NULL, test->val, strlen(test->val)+1 ); ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong length %d for %s\n", value.Length, test->var ); ok((value.Length == strlen(test->val) * sizeof(WCHAR) && memcmp(bv, bn, test->len*sizeof(WCHAR)) == 0) || lstrcmpW(bv, bn) == 0, "Wrong result for %s/%d\n", test->var, test->len); ok(bv[test->len] == '@', "Writing too far away in the buffer for %s/%d\n", test->var, test->len); break; case STATUS_BUFFER_TOO_SMALL: ok( value.Length == strlen(test->val) * sizeof(WCHAR), "Wrong returned length %d (too small buffer) for %s\n", value.Length, test->var ); break; } } }
static void testExpand(void) { static const struct test { const char *src; const char *dst; } tests[] = { {"hello%foo%world", "hellototoworld"}, {"hello%=oOH%world", "helloIIIworld"}, {"hello%foo", "hello%foo"}, {"hello%bar%world", "hello%bar%world"}, /* * {"hello%foo%world%=oOH%eeck", "hellototoworldIIIeeck"}, * Interestingly enough, with a 8 WCHAR buffers, we get on 2k: * helloIII * so it seems like strings overflowing the buffer are written * (truncated) but the write cursor is not advanced :-/ */ {NULL, NULL} }; const struct test* test; NTSTATUS nts; UNICODE_STRING us_src, us_dst; WCHAR src[256], dst[256], rst[256]; ULONG ul; for (test = tests; test->src; test++) { pRtlMultiByteToUnicodeN(src, sizeof(src), NULL, test->src, strlen(test->src)+1); pRtlMultiByteToUnicodeN(rst, sizeof(rst), NULL, test->dst, strlen(test->dst)+1); us_src.Length = strlen(test->src) * sizeof(WCHAR); us_src.MaximumLength = us_src.Length + 2; us_src.Buffer = src; us_dst.Length = 0; us_dst.MaximumLength = 0; us_dst.Buffer = NULL; nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul); ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR), "Wrong returned length for %s: %u\n", test->src, ul ); us_dst.Length = 0; us_dst.MaximumLength = sizeof(dst); us_dst.Buffer = dst; nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul); ok(nts == STATUS_SUCCESS, "Call failed (%u)\n", nts); ok(ul == us_dst.Length + sizeof(WCHAR), "Wrong returned length for %s: %u\n", test->src, ul); ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR), "Wrong returned length for %s: %u\n", test->src, ul); ok(lstrcmpW(dst, rst) == 0, "Wrong result for %s: expecting %s\n", test->src, test->dst); us_dst.Length = 0; us_dst.MaximumLength = 8 * sizeof(WCHAR); us_dst.Buffer = dst; dst[8] = '-'; nts = pRtlExpandEnvironmentStrings_U(small_env, &us_src, &us_dst, &ul); ok(nts == STATUS_BUFFER_TOO_SMALL, "Call failed (%u)\n", nts); ok(ul == strlen(test->dst) * sizeof(WCHAR) + sizeof(WCHAR), "Wrong returned length for %s (with buffer too small): %u\n", test->src, ul); ok(dst[8] == '-', "Writing too far in buffer (got %c/%d)\n", dst[8], dst[8]); } }
static void test_NtQueryDirectoryFile_case(void) { static const char testfile[] = "TesT"; static const WCHAR testfile_w[] = {'T','e','s','T'}; static int testfile_len = sizeof(testfile) - 1; static WCHAR testmask[] = {'t','e','s','t'}; OBJECT_ATTRIBUTES attr; UNICODE_STRING ntdirname; char testdir[MAX_PATH]; WCHAR testdir_w[MAX_PATH]; HANDLE dirh; UNICODE_STRING mask; IO_STATUS_BLOCK io; UINT data_size, data_len; BYTE data[8192]; FILE_BOTH_DIRECTORY_INFORMATION *dir_info = (FILE_BOTH_DIRECTORY_INFORMATION *)data; DWORD status; WCHAR *name; ULONG name_len; /* Clean up from prior aborted run, if any, then set up test files */ ok(GetTempPathA(MAX_PATH, testdir), "couldn't get temp dir\n"); strcat(testdir, "case.tmp"); tear_down_case_test(testdir); set_up_case_test(testdir); pRtlMultiByteToUnicodeN(testdir_w, sizeof(testdir_w), NULL, testdir, strlen(testdir) + 1); if (!pRtlDosPathNameToNtPathName_U(testdir_w, &ntdirname, NULL, NULL)) { ok(0, "RtlDosPathNametoNtPathName_U failed\n"); goto done; } InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL); data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]); status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); ok (status == STATUS_SUCCESS, "failed to open dir '%s', ret 0x%x, error %d\n", testdir, status, GetLastError()); if (status != STATUS_SUCCESS) { skip("can't test if we can't open the directory\n"); return; } mask.Buffer = testmask; mask.Length = mask.MaximumLength = sizeof(testmask); pNtQueryDirectoryFile(dirh, NULL, NULL, NULL, &io, data, data_size, FileBothDirectoryInformation, TRUE, &mask, FALSE); ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status); data_len = io.Information; ok(data_len >= sizeof(FILE_BOTH_DIRECTORY_INFORMATION), "not enough data in directory\n"); name = dir_info->FileName; name_len = dir_info->FileNameLength / sizeof(WCHAR); ok(name_len == testfile_len, "unexpected filename length %u\n", name_len); ok(!memcmp(name, testfile_w, testfile_len * sizeof(WCHAR)), "unexpected filename %s\n", wine_dbgstr_wn(name, name_len)); pNtClose(dirh); done: tear_down_case_test(testdir); pRtlFreeUnicodeString(&ntdirname); }
static void test_NtQueryDirectoryFile(void) { OBJECT_ATTRIBUTES attr; UNICODE_STRING ntdirname, mask; char testdirA[MAX_PATH]; WCHAR testdirW[MAX_PATH]; int i; IO_STATUS_BLOCK io; WCHAR short_name[12]; UINT data_size; BYTE data[8192]; FILE_BOTH_DIRECTORY_INFORMATION *fbdi = (FILE_BOTH_DIRECTORY_INFORMATION*)data; DWORD status; HANDLE dirh; /* Clean up from prior aborted run, if any, then set up test files */ ok(GetTempPathA(MAX_PATH, testdirA), "couldn't get temp dir\n"); strcat(testdirA, "NtQueryDirectoryFile.tmp"); tear_down_attribute_test(testdirA); set_up_attribute_test(testdirA); pRtlMultiByteToUnicodeN(testdirW, sizeof(testdirW), NULL, testdirA, strlen(testdirA)+1); if (!pRtlDosPathNameToNtPathName_U(testdirW, &ntdirname, NULL, NULL)) { ok(0, "RtlDosPathNametoNtPathName_U failed\n"); goto done; } InitializeObjectAttributes(&attr, &ntdirname, OBJ_CASE_INSENSITIVE, 0, NULL); test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, FALSE, FALSE); test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, NULL, TRUE, FALSE); for (i = 0; testfiles[i].name; i++) { if (testfiles[i].nameW[0] == '.') continue; /* . and .. as masks are broken on Windows */ mask.Buffer = testfiles[i].nameW; mask.Length = mask.MaximumLength = lstrlenW(testfiles[i].nameW) * sizeof(WCHAR); test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, FALSE, FALSE); test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, TRUE); test_flags_NtQueryDirectoryFile(&attr, testdirA, &mask, TRUE, FALSE); } /* short path passed as mask */ status = pNtOpenFile(&dirh, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); ok(status == STATUS_SUCCESS, "failed to open dir '%s'\n", testdirA); if (status != STATUS_SUCCESS) { skip("can't test if we can't open the directory\n"); return; } mask.Buffer = testfiles[0].nameW; mask.Length = mask.MaximumLength = lstrlenW(testfiles[0].nameW) * sizeof(WCHAR); data_size = offsetof(FILE_BOTH_DIRECTORY_INFORMATION, FileName[256]); pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size, FileBothDirectoryInformation, TRUE, &mask, FALSE); ok(U(io).Status == STATUS_SUCCESS, "failed to query directory; status %x\n", U(io).Status); ok(fbdi->ShortName[0], "ShortName is empty\n"); mask.Length = mask.MaximumLength = fbdi->ShortNameLength; memcpy(short_name, fbdi->ShortName, mask.Length); mask.Buffer = short_name; pNtQueryDirectoryFile(dirh, 0, NULL, NULL, &io, data, data_size, FileBothDirectoryInformation, TRUE, &mask, TRUE); ok(U(io).Status == STATUS_SUCCESS, "failed to query directory status %x\n", U(io).Status); ok(fbdi->FileNameLength == strlen(testfiles[0].name)*sizeof(WCHAR) && !memcmp(fbdi->FileName, testfiles[0].nameW, fbdi->FileNameLength), "incorrect long file name: %s\n", wine_dbgstr_wn(fbdi->FileName, fbdi->FileNameLength/sizeof(WCHAR))); pNtClose(dirh); done: tear_down_attribute_test(testdirA); pRtlFreeUnicodeString(&ntdirname); }
static void test_RtlIsDosDeviceName_U(void) { struct test { const char *path; WORD pos; WORD len; BOOL fails; }; static const struct test tests[] = { { "\\\\.\\CON", 8, 6 }, { "\\\\.\\con", 8, 6 }, { "\\\\.\\CON2", 0, 0 }, { "", 0, 0 }, { "\\\\foo\\nul", 0, 0 }, { "c:\\nul:", 6, 6 }, { "c:\\nul\\", 0, 0 }, { "c:\\nul\\foo", 0, 0 }, { "c:\\nul::", 6, 6, TRUE }, /* fails on nt4 */ { "c:\\nul::::::", 6, 6, TRUE }, /* fails on nt4 */ { "c:prn ", 4, 6 }, { "c:prn.......", 4, 6 }, { "c:prn... ...", 4, 6 }, { "c:NUL .... ", 4, 6, TRUE }, /* fails on nt4 */ { "c: . . .", 0, 0 }, { "c:", 0, 0 }, { " . . . :", 0, 0 }, { ":", 0, 0 }, { "c:nul. . . :", 4, 6 }, { "c:nul . . :", 4, 6, TRUE }, /* fails on nt4 */ { "c:nul0", 0, 0 }, { "c:prn:aaa", 4, 6, TRUE }, /* fails on win9x */ { "c:PRN:.txt", 4, 6 }, { "c:aux:.txt...", 4, 6 }, { "c:prn:.txt:", 4, 6 }, { "c:nul:aaa", 4, 6, TRUE }, /* fails on win9x */ { "con:", 0, 6 }, { "lpt1:", 0, 8 }, { "c:com5:", 4, 8 }, { "CoM4:", 0, 8 }, { "lpt9:", 0, 8 }, { "c:\\lpt0.txt", 0, 0 }, { "c:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\nul.txt", 1000, 6 }, { NULL, 0 } }; const struct test *test; WCHAR buffer[2000]; ULONG ret; if (!pRtlIsDosDeviceName_U) { win_skip("RtlIsDosDeviceName_U is not available\n"); return; } for (test = tests; test->path; test++) { pRtlMultiByteToUnicodeN( buffer, sizeof(buffer), NULL, test->path, strlen(test->path)+1 ); ret = pRtlIsDosDeviceName_U( buffer ); ok( ret == MAKELONG( test->len, test->pos ) || (test->fails && broken( ret == 0 )), "Wrong result (%d,%d)/(%d,%d) for %s\n", HIWORD(ret), LOWORD(ret), test->pos, test->len, test->path ); } }
static void test_RtlGetFullPathName_U(void) { static const WCHAR emptyW[] = {0}; static const WCHAR deadbeefW[] = {'d','e','a','d','b','e','e','f',0}; struct test { const char *path; const char *rname; const char *rfile; const char *alt_rname; const char *alt_rfile; }; static const struct test tests[] = { { "c:/test", "c:\\test", "test"}, { "c:/test ", "c:\\test", "test"}, { "c:/test.", "c:\\test", "test"}, { "c:/test .... .. ", "c:\\test", "test"}, { "c:/test/ .... .. ", "c:\\test\\", NULL}, { "c:/test/..", "c:\\", NULL}, { "c:/test/.. ", "c:\\test\\", NULL}, { "c:/TEST", "c:\\test", "test"}, { "c:/test/file", "c:\\test\\file", "file"}, { "c:/test./file", "c:\\test\\file", "file"}, { "c:/test.. /file", "c:\\test.. \\file","file"}, { "c:/test/././file", "c:\\test\\file", "file"}, { "c:/test\\.\\.\\file", "c:\\test\\file", "file"}, { "c:/test/\\.\\.\\file", "c:\\test\\file", "file"}, { "c:/test\\\\.\\.\\file", "c:\\test\\file", "file"}, { "c:/test\\test1\\..\\.\\file", "c:\\test\\file", "file"}, { "c:///test\\.\\.\\file//", "c:\\test\\file\\", NULL, "c:\\test\\file", "file"}, /* nt4 */ { "c:///test\\..\\file\\..\\//", "c:\\", NULL}, { "c:/test../file", "c:\\test.\\file", "file", "c:\\test..\\file", "file"}, /* vista */ { NULL, NULL, NULL} }; const struct test *test; WCHAR pathbufW[2*MAX_PATH], rbufferW[MAX_PATH]; CHAR rbufferA[MAX_PATH], rfileA[MAX_PATH]; ULONG ret; WCHAR *file_part; DWORD reslen; UINT len; if (!pRtlGetFullPathName_U) { win_skip("RtlGetFullPathName_U is not available\n"); return; } file_part = (WCHAR *)0xdeadbeef; lstrcpyW(rbufferW, deadbeefW); ret = pRtlGetFullPathName_U(NULL, MAX_PATH, rbufferW, &file_part); ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret); ok(!lstrcmpW(rbufferW, deadbeefW), "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW)); ok(file_part == (WCHAR *)0xdeadbeef || file_part == NULL, /* Win7 */ "Expected file part pointer to be untouched, got %p\n", file_part); file_part = (WCHAR *)0xdeadbeef; lstrcpyW(rbufferW, deadbeefW); ret = pRtlGetFullPathName_U(emptyW, MAX_PATH, rbufferW, &file_part); ok(!ret, "Expected RtlGetFullPathName_U to return 0, got %u\n", ret); ok(!lstrcmpW(rbufferW, deadbeefW), "Expected the output buffer to be untouched, got %s\n", wine_dbgstr_w(rbufferW)); ok(file_part == (WCHAR *)0xdeadbeef || file_part == NULL, /* Win7 */ "Expected file part pointer to be untouched, got %p\n", file_part); for (test = tests; test->path; test++) { len= strlen(test->rname) * sizeof(WCHAR); pRtlMultiByteToUnicodeN(pathbufW , sizeof(pathbufW), NULL, test->path, strlen(test->path)+1 ); ret = pRtlGetFullPathName_U( pathbufW,MAX_PATH, rbufferW, &file_part); ok( ret == len || (test->alt_rname && ret == strlen(test->alt_rname)*sizeof(WCHAR)), "Wrong result %d/%d for \"%s\"\n", ret, len, test->path ); ok(pRtlUnicodeToMultiByteN(rbufferA,MAX_PATH,&reslen,rbufferW,(lstrlenW(rbufferW) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS, "RtlUnicodeToMultiByteN failed\n"); ok(!lstrcmpiA(rbufferA,test->rname) || (test->alt_rname && !lstrcmpiA(rbufferA,test->alt_rname)), "Got \"%s\" expected \"%s\"\n",rbufferA,test->rname); if (file_part) { ok(pRtlUnicodeToMultiByteN(rfileA,MAX_PATH,&reslen,file_part,(lstrlenW(file_part) + 1) * sizeof(WCHAR)) == STATUS_SUCCESS, "RtlUnicodeToMultiByteN failed\n"); ok((test->rfile && !lstrcmpiA(rfileA,test->rfile)) || (test->alt_rfile && !lstrcmpiA(rfileA,test->alt_rfile)), "Got \"%s\" expected \"%s\"\n",rfileA,test->rfile); } else { ok( !test->rfile, "Got NULL expected \"%s\"\n", test->rfile ); } } }