diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c index 84e2c1686ea..b974f8d63d9 100644 --- a/dlls/shell32/shell32_main.c +++ b/dlls/shell32/shell32_main.c @@ -1238,21 +1238,3 @@ HRESULT WINAPI DllCanUnloadNow(void) FIXME("stub\n"); return S_FALSE; } - -/*********************************************************************** - * SHPathPrepareForWriteA (SHELL32.@) - */ -HRESULT WINAPI SHPathPrepareForWriteA(HWND hwnd, IUnknown *modless, LPCSTR path, DWORD flags) -{ - FIXME("%p %p %s 0x%08x\n", hwnd, modless, debugstr_a(path), flags); - return S_OK; -} - -/*********************************************************************** - * SHPathPrepareForWriteA (SHELL32.@) - */ -HRESULT WINAPI SHPathPrepareForWriteW(HWND hwnd, IUnknown *modless, LPCWSTR path, DWORD flags) -{ - FIXME("%p %p %s 0x%08x\n", hwnd, modless, debugstr_w(path), flags); - return S_OK; -} diff --git a/dlls/shell32/shlfileop.c b/dlls/shell32/shlfileop.c index 87bf6775839..134d6c5b369 100644 --- a/dlls/shell32/shlfileop.c +++ b/dlls/shell32/shlfileop.c @@ -1694,3 +1694,77 @@ INT WINAPI RealDriveType(INT drive, BOOL bQueryNet) root[0] += (char)drive; return GetDriveTypeA(root); } + +/*********************************************************************** + * SHPathPrepareForWriteA (SHELL32.@) + */ +HRESULT WINAPI SHPathPrepareForWriteA(HWND hwnd, IUnknown *modless, LPCSTR path, DWORD flags) +{ + WCHAR wpath[MAX_PATH]; + MultiByteToWideChar( CP_ACP, 0, path, -1, wpath, MAX_PATH); + return SHPathPrepareForWriteW(hwnd, modless, wpath, flags); +} + +/*********************************************************************** + * SHPathPrepareForWriteW (SHELL32.@) + */ +HRESULT WINAPI SHPathPrepareForWriteW(HWND hwnd, IUnknown *modless, LPCWSTR path, DWORD flags) +{ + HRESULT res; + DWORD err; + LPCWSTR realpath; + int len; + WCHAR* last_slash; + WCHAR* temppath=NULL; + + TRACE("%p %p %s 0x%80x\n", hwnd, modless, debugstr_w(path), flags); + + if (flags & ~(SHPPFW_DIRCREATE|SHPPFW_ASKDIRCREATE|SHPPFW_IGNOREFILENAME)) + FIXME("unimplemented flags 0x%08x\n", flags); + + /* cut off filename if necessary */ + if (flags & SHPPFW_IGNOREFILENAME) + { + last_slash = StrRChrW(path, NULL, '\\'); + if (last_slash == NULL) + len = 1; + else + len = last_slash - path + 1; + temppath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); + if (!temppath) + return E_OUTOFMEMORY; + StrCpyNW(temppath, path, len); + realpath = temppath; + } + else + { + realpath = path; + } + + /* try to create the directory if asked to */ + if (flags & (SHPPFW_DIRCREATE|SHPPFW_ASKDIRCREATE)) + { + if (flags & SHPPFW_ASKDIRCREATE) + FIXME("treating SHPPFW_ASKDIRCREATE as SHPPFW_DIRCREATE\n"); + + SHCreateDirectoryExW(0, realpath, NULL); + } + + /* check if we can access the directory */ + res = GetFileAttributesW(realpath); + + if (temppath) + HeapFree(GetProcessHeap(), 0, temppath); + + if (res == INVALID_FILE_ATTRIBUTES) + { + err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND) + return HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND); + return HRESULT_FROM_WIN32(err); + } + else if (res & FILE_ATTRIBUTE_DIRECTORY) + return S_OK; + else + return HRESULT_FROM_WIN32(ERROR_DIRECTORY); +} diff --git a/dlls/shell32/tests/shlfileop.c b/dlls/shell32/tests/shlfileop.c index 964f6ec0b9f..c310e09e9eb 100644 --- a/dlls/shell32/tests/shlfileop.c +++ b/dlls/shell32/tests/shlfileop.c @@ -1018,22 +1018,22 @@ static void test_sh_path_prepare(void) } /* directory exists, SHPPFW_NONE */ - set_curr_dir_path(path, "\0"); + set_curr_dir_path(path, "testdir2\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); /* directory exists, SHPPFW_IGNOREFILENAME */ - set_curr_dir_path(path, "nonexistent\0"); + set_curr_dir_path(path, "testdir2\\test4.txt\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); /* directory exists, SHPPFW_DIRCREATE */ - set_curr_dir_path(path, "\0"); + set_curr_dir_path(path, "testdir2\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); /* directory exists, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE */ - set_curr_dir_path(path, "nonexistent\0"); + set_curr_dir_path(path, "testdir2\\test4.txt\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n"); @@ -1041,16 +1041,16 @@ static void test_sh_path_prepare(void) /* file exists, SHPPFW_NONE */ set_curr_dir_path(path, "test1.txt\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); /* file exists, SHPPFW_DIRCREATE */ res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); /* file exists, SHPPFW_NONE, trailing \ */ set_curr_dir_path(path, "test1.txt\\\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_DIRECTORY)\n", res); /* relative path exists, SHPPFW_DIRCREATE */ res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2", SHPPFW_DIRCREATE); @@ -1058,18 +1058,18 @@ static void test_sh_path_prepare(void) /* relative path doesn't exist, SHPPFW_DIRCREATE -- Windows does not create the directory in this case */ res = pSHPathPrepareForWriteA(0, 0, ".\\testdir2\\test4.txt", SHPPFW_DIRCREATE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); ok(!file_exists(".\\testdir2\\test4.txt\\"), ".\\testdir2\\test4.txt\\ exists but shouldn't\n"); /* directory doesn't exist, SHPPFW_NONE */ set_curr_dir_path(path, "nonexistent\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); /* directory doesn't exist, SHPPFW_IGNOREFILENAME */ set_curr_dir_path(path, "nonexistent\\notreal\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == 0x%08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); ok(!file_exists("nonexistent\\notreal"), "nonexistent\\notreal exists but shouldn't\n"); ok(!file_exists("nonexistent\\"), "nonexistent\\ exists but shouldn't\n"); @@ -1077,13 +1077,13 @@ static void test_sh_path_prepare(void) set_curr_dir_path(path, "testdir2\\test4.txt\\\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_IGNOREFILENAME|SHPPFW_DIRCREATE); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); - todo_wine ok(file_exists("testdir2\\test4.txt\\"), "testdir2\\test4.txt doesn't exist but should\n"); + ok(file_exists("testdir2\\test4.txt\\"), "testdir2\\test4.txt doesn't exist but should\n"); /* nested directory doesn't exist, SHPPFW_DIRCREATE */ set_curr_dir_path(path, "nonexistent\\notreal\0"); res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE); ok(res == S_OK, "res == 0x%08x, expected S_OK\n", res); - todo_wine ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal doesn't exist but should\n"); + ok(file_exists("nonexistent\\notreal"), "nonexistent\\notreal doesn't exist but should\n"); /* SHPPFW_ASKDIRCREATE, SHPPFW_NOWRITECHECK, and SHPPFW_MEDIACHECKONLY are untested */ @@ -1094,14 +1094,14 @@ static void test_sh_path_prepare(void) } /* unicode directory doesn't exist, SHPPFW_NONE */ res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE); - todo_wine ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); + ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res); ok(!file_existsW(UNICODE_PATH), "unicode path was created but shouldn't be\n"); RemoveDirectoryW(UNICODE_PATH); /* unicode directory doesn't exist, SHPPFW_DIRCREATE */ res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE); ok(res == S_OK, "res == %08x, expected S_OK\n", res); - todo_wine ok(file_existsW(UNICODE_PATH), "unicode path should've been created\n"); + ok(file_existsW(UNICODE_PATH), "unicode path should've been created\n"); /* unicode directory exists, SHPPFW_NONE */ res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);