Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
I tried to test what happens if the temp path is longer than MAX_PATH characters, but I could not get Windows to accept a long temp path. If %TMP% is longer than 100 characters (or somewhere in that area, I did not test the precise limit) it falls back to %TEMP%, %USERPROFILE% and finally "C:\Windows".
I assume msvcp does not clear the extra bytes like GetTempPathW either because it doesn't call GetTempPath and implements the logic itself or because it writes to a temp buffer and copies the data. I don't know how to trigger this possible case even with a manual test on Windows. --- dlls/msvcp140/msvcp140.spec | 2 +- dlls/msvcp140/tests/msvcp140.c | 27 +++++++++++++++++++++++++++ dlls/msvcp90/ios.c | 6 ++++++ 3 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcp140/msvcp140.spec b/dlls/msvcp140/msvcp140.spec index 4fc8e3c5d5..3cd1975adf 100644 --- a/dlls/msvcp140/msvcp140.spec +++ b/dlls/msvcp140/msvcp140.spec @@ -3718,7 +3718,7 @@ @ stub _Strxfrm @ cdecl _Symlink(wstr wstr) tr2_sys__Symlink_wchar @ stub _Symlink_get -@ stub _Temp_get +@ cdecl _Temp_get(ptr) @ stub _Thrd_abort @ cdecl _Thrd_create(ptr ptr ptr) _Thrd_create @ cdecl -norelay _Thrd_current() diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index 620e9317c9..01ed89aceb 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -177,6 +177,7 @@ static WCHAR* (__cdecl *p_Read_dir)(WCHAR*, void*, enum file_type*); static MSVCP_bool (__cdecl *p_Remove_dir)(WCHAR const*); static enum file_type (__cdecl *p_Stat)(WCHAR const *, int *); static int (__cdecl *p_Symlink)(WCHAR const*, WCHAR const*); +static WCHAR* (__cdecl *p_Temp_get)(WCHAR *); static int (__cdecl *p_To_byte)(const WCHAR *src, char *dst); static int (__cdecl *p_To_wide)(const char *src, WCHAR *dst); static int (__cdecl *p_Unlink)(WCHAR const*); @@ -258,6 +259,7 @@ static BOOL init(void) SET(p_Remove_dir, "_Remove_dir"); SET(p_Stat, "_Stat"); SET(p_Symlink, "_Symlink"); + SET(p_Temp_get, "_Temp_get"); SET(p_To_byte, "_To_byte"); SET(p_To_wide, "_To_wide"); SET(p_Unlink, "_Unlink"); @@ -1054,6 +1056,30 @@ static void test_Unlink(void) ok(SetCurrentDirectoryW(current_path), "SetCurrentDirectoryW failed\n"); }
+static void test_Temp_get(void) +{ + WCHAR path[MAX_PATH + 1], temp_path[MAX_PATH]; + WCHAR *retval; + DWORD len; + + GetTempPathW(sizeof(temp_path)/sizeof(*temp_path), temp_path); + + /* This crashes on Windows, the input pointer is not validated. */ + if (0) + { + retval = p_Temp_get(NULL); + ok(!retval, "_Temp_get(): Got %p\n", retval); + } + + memset(path, 0xaa, sizeof(path)); + retval = p_Temp_get(path); + ok(retval == path, "_Temp_get(): Got %p, expected %p\n", retval, path); + ok(!wcscmp(path, temp_path), "Expected path %s, got %s\n", wine_dbgstr_w(temp_path), wine_dbgstr_w(path)); + len = wcslen(path); + ok(!path[len], "Expected a 0 terminated string\n"); + todo_wine ok(path[len + 1] == 0xaaaa, "Too many bytes were zeroed - %x\n", path[len + 1]); +} + START_TEST(msvcp140) { if(!init()) return; @@ -1071,5 +1097,6 @@ START_TEST(msvcp140) test_Stat(); test_dir_operation(); test_Unlink(); + test_Temp_get(); FreeLibrary(msvcp); } diff --git a/dlls/msvcp90/ios.c b/dlls/msvcp90/ios.c index 3f859979cb..ab9d7a44a4 100644 --- a/dlls/msvcp90/ios.c +++ b/dlls/msvcp90/ios.c @@ -15745,6 +15745,12 @@ enum file_type __cdecl _Lstat(WCHAR const* path, int* permissions) return _Stat(path, permissions); }
+WCHAR * __cdecl _Temp_get(WCHAR *dst) +{ + GetTempPathW(MAX_PATH, dst); + return dst; +} + /* ??1_Winit@std@@QAE@XZ */ /* ??1_Winit@std@@QAE@XZ */ DEFINE_THISCALL_WRAPPER(_Winit_dtor, 4)
Signed-off-by: Stefan Dösinger stefan@codeweavers.com
---
WGC uses it. Just ignore it because we don't have any logic to blacklist previously crashed tests anyway. --- programs/dxdiag/main.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/programs/dxdiag/main.c b/programs/dxdiag/main.c index 3ced122d6e..d7d430b570 100644 --- a/programs/dxdiag/main.c +++ b/programs/dxdiag/main.c @@ -110,6 +110,7 @@ static BOOL process_command_line(const WCHAR *cmdline, struct command_line_info static const WCHAR whql_colonW[] = {'w','h','q','l',':',0}; static const WCHAR offW[] = {'o','f','f',0}; static const WCHAR onW[] = {'o','n',0}; + static const WCHAR dontskipW[] = {'d','o','n','t','s','k','i','p',0};
info->whql_check = FALSE; info->output_type = OUTPUT_NONE; @@ -163,6 +164,14 @@ static BOOL process_command_line(const WCHAR *cmdline, struct command_line_info return FALSE;
break; + + case 'd': + case 'D': + if (strncmpiW(cmdline, dontskipW, 8)) + return FALSE; + cmdline += 8; + break; + default: return FALSE; }
On 2017-12-08 21:15, Stefan Dösinger wrote:
- memset(path, 0xaa, sizeof(path));
- retval = p_Temp_get(path);
- ok(retval == path, "_Temp_get(): Got %p, expected %p\n", retval, path);
- ok(!wcscmp(path, temp_path), "Expected path %s, got %s\n", wine_dbgstr_w(temp_path), wine_dbgstr_w(path));
- len = wcslen(path);
- ok(!path[len], "Expected a 0 terminated string\n");
This check can never fail. Perhaps len < _countof(path) or using a wcsnlen-style function above would make sense instead?
Best, Thomas
Am 2017-12-09 um 11:10 schrieb Thomas Faber:
On 2017-12-08 21:15, Stefan Dösinger wrote:
+ memset(path, 0xaa, sizeof(path)); + retval = p_Temp_get(path); + ok(retval == path, "_Temp_get(): Got %p, expected %p\n", retval, path); + ok(!wcscmp(path, temp_path), "Expected path %s, got %s\n", wine_dbgstr_w(temp_path), wine_dbgstr_w(path)); + len = wcslen(path); + ok(!path[len], "Expected a 0 terminated string\n");
This check can never fail. Perhaps len < _countof(path) or using a wcsnlen-style function above would make sense instead?
You are right, it is pointless. The wcscmp should take care of checking the 0 byte already actually, so I think I'll just remove it, but keep the check for len + 1.