1 /*
2  * PROJECT:     ReactOS api tests
3  * LICENSE:     LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later)
4  * PURPOSE:     Test for AssocQueryStringA/W
5  * COPYRIGHT:   Copyright 2024 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
6  */
7 
8 #include <apitest.h>
9 #include <shlwapi.h>
10 #include <stdio.h>
11 #include <versionhelpers.h>
12 
13 typedef HRESULT (WINAPI *FN_AssocQueryStringA)(
14     ASSOCF cfFlags,
15     ASSOCSTR str,
16     LPCSTR pszAssoc,
17     LPCSTR pszExtra,
18     LPSTR pszOut,
19     DWORD *pcchOut);
20 typedef HRESULT (WINAPI *FN_AssocQueryStringW)(
21     ASSOCF cfFlags,
22     ASSOCSTR str,
23     LPCWSTR pszAssoc,
24     LPCWSTR pszExtra,
25     LPWSTR pszOut,
26     DWORD *pcchOut);
27 
28 static HINSTANCE s_hSHLWAPI = NULL;
29 static FN_AssocQueryStringA s_fnAssocQueryStringA = NULL;
30 static FN_AssocQueryStringW s_fnAssocQueryStringW = NULL;
31 static CHAR  s_szTextFileA[MAX_PATH] =  "";
32 static WCHAR s_szTextFileW[MAX_PATH] = L"";
33 #define NON_EXISTENT_FILENAME_A  "C:\\ThisIsNotExistentFile.txt"
34 #define NON_EXISTENT_FILENAME_W L"C:\\ThisIsNotExistentFile.txt"
35 
36 static void TEST_Start(void)
37 {
38     ExpandEnvironmentStringsA( "%APPDATA%\\This is a test.txt", s_szTextFileA, _countof(s_szTextFileA));
39     ExpandEnvironmentStringsW(L"%APPDATA%\\This is a test.txt", s_szTextFileW, _countof(s_szTextFileW));
40     fclose(_wfopen(s_szTextFileW, L"w"));
41     trace("%s\n", wine_dbgstr_a(s_szTextFileA));
42     trace("%s\n", wine_dbgstr_w(s_szTextFileW));
43 }
44 
45 static void TEST_End(void)
46 {
47     DeleteFileW(s_szTextFileW);
48 }
49 
50 /*
51  * "shlwapi_winetest assoc" already has many tests.
52  * We just do additional tests in here.
53  */
54 
55 static void TEST_AssocQueryStringA(void)
56 {
57     CHAR szPath[MAX_PATH], szAnswer[MAX_PATH];
58     CHAR szDebug1[MAX_PATH], szDebug2[MAX_PATH];
59     HRESULT hr;
60     DWORD cch;
61 
62     /* ".txt" */
63     lstrcpynA(szPath, ".txt", _countof(szPath));
64     cch = _countof(szPath);
65     hr = AssocQueryStringA(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
66     if (IsWindowsVistaOrGreater())
67     {
68         ExpandEnvironmentStringsA("%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
69         ok_long(hr, S_OK);
70         ok_int(cch, lstrlenA(szAnswer) + 1);
71     }
72     else
73     {
74         lstrcpynA(szAnswer, ".txt", _countof(szAnswer));
75         ok_long(hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
76         ok_int(cch, _countof(szPath));
77     }
78     lstrcpynA(szDebug1, wine_dbgstr_a(szPath), _countof(szDebug1));
79     lstrcpynA(szDebug2, wine_dbgstr_a(szAnswer), _countof(szDebug2));
80     ok(lstrcmpiA(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
81 
82     /* s_szTextFileA */
83     lstrcpynA(szPath, s_szTextFileA, _countof(szPath));
84     cch = _countof(szPath);
85     hr = AssocQueryStringA(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
86     if (IsWindowsVistaOrGreater())
87     {
88         ExpandEnvironmentStringsA("%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
89         ok_long(hr, S_OK);
90         ok_int(cch, lstrlenA(szAnswer) + 1);
91     }
92     else
93     {
94         lstrcpynA(szAnswer, s_szTextFileA, _countof(szAnswer));
95         ok_long(hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
96         ok_int(cch, _countof(szPath));
97     }
98     lstrcpynA(szDebug1, wine_dbgstr_a(szPath), _countof(szDebug1));
99     lstrcpynA(szDebug2, wine_dbgstr_a(szAnswer), _countof(szDebug2));
100     ok(lstrcmpiA(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
101 
102     /* NON_EXISTENT_FILENAME_A */
103     lstrcpynA(szPath, NON_EXISTENT_FILENAME_A, _countof(szPath));
104     cch = _countof(szPath);
105     hr = AssocQueryStringA(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
106     if (IsWindowsVistaOrGreater())
107     {
108         ExpandEnvironmentStringsA("%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
109         ok_long(hr, S_OK);
110         ok_int(cch, lstrlenA(szAnswer) + 1);
111     }
112     else
113     {
114         lstrcpynA(szAnswer, NON_EXISTENT_FILENAME_A, _countof(szAnswer));
115         ok_long(hr, HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
116         ok_int(cch, _countof(szPath));
117     }
118     lstrcpynA(szDebug1, wine_dbgstr_a(szPath), _countof(szDebug1));
119     lstrcpynA(szDebug2, wine_dbgstr_a(szAnswer), _countof(szDebug2));
120     ok(lstrcmpiA(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
121 }
122 
123 static void TEST_AssocQueryStringW(void)
124 {
125     WCHAR szPath[MAX_PATH], szAnswer[MAX_PATH];
126     CHAR szDebug1[MAX_PATH], szDebug2[MAX_PATH];
127     HRESULT hr;
128     DWORD cch;
129 
130     /* ".txt" */
131     lstrcpynW(szPath, L".txt", _countof(szPath));
132     cch = _countof(szPath);
133     hr = AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
134     ok_long(hr, S_OK);
135     ExpandEnvironmentStringsW(L"%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
136     lstrcpynA(szDebug1, wine_dbgstr_w(szPath), _countof(szDebug1));
137     lstrcpynA(szDebug2, wine_dbgstr_w(szAnswer), _countof(szDebug2));
138     ok(lstrcmpiW(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
139     ok_int(cch, lstrlenW(szAnswer) + 1);
140 
141     /* s_szTextFileW */
142     lstrcpynW(szPath, s_szTextFileW, _countof(szPath));
143     cch = _countof(szPath);
144     hr = AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
145     ok_long(hr, S_OK);
146     ExpandEnvironmentStringsW(L"%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
147     lstrcpynA(szDebug1, wine_dbgstr_w(szPath), _countof(szDebug1));
148     lstrcpynA(szDebug2, wine_dbgstr_w(szAnswer), _countof(szDebug2));
149     ok(lstrcmpiW(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
150     ok_int(cch, lstrlenW(szAnswer) + 1);
151 
152     /* NON_EXISTENT_FILENAME_W */
153     lstrcpynW(szPath, NON_EXISTENT_FILENAME_W, _countof(szPath));
154     cch = _countof(szPath);
155     hr = AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, szPath, NULL, szPath, &cch);
156     ok_long(hr, S_OK);
157     ExpandEnvironmentStringsW(L"%WINDIR%\\system32\\notepad.exe", szAnswer, _countof(szAnswer));
158     lstrcpynA(szDebug1, wine_dbgstr_w(szPath), _countof(szDebug1));
159     lstrcpynA(szDebug2, wine_dbgstr_w(szAnswer), _countof(szDebug2));
160     ok(lstrcmpiW(szPath, szAnswer) == 0, "%s vs %s\n", szDebug1, szDebug2);
161     ok_int(cch, lstrlenW(szAnswer) + 1);
162 }
163 
164 START_TEST(AssocQueryString)
165 {
166     HRESULT hrCoInit = CoInitialize(NULL);
167 
168     s_hSHLWAPI = LoadLibraryW(L"shlwapi.dll");
169     s_fnAssocQueryStringA = (FN_AssocQueryStringA)GetProcAddress(s_hSHLWAPI, "AssocQueryStringA");
170     s_fnAssocQueryStringW = (FN_AssocQueryStringW)GetProcAddress(s_hSHLWAPI, "AssocQueryStringW");
171     if (!s_fnAssocQueryStringA || !s_fnAssocQueryStringW)
172     {
173         skip("AssocQueryStringA or AssocQueryStringW not found: %p, %p\n",
174              s_fnAssocQueryStringA, s_fnAssocQueryStringW);
175         return;
176     }
177 
178     TEST_Start();
179     TEST_AssocQueryStringA();
180     TEST_AssocQueryStringW();
181     TEST_End();
182 
183     FreeLibrary(s_hSHLWAPI);
184 
185     if (SUCCEEDED(hrCoInit))
186         CoUninitialize();
187 }
188