~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/comctl32/tests/mru.c

Version: ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~ [ wine-1.0-rc5 ] ~ [ wine-1.0-rc4 ] ~ [ wine-1.0-rc3 ] ~ [ wine-1.0-rc2 ] ~ [ wine-1.0-rc1 ] ~ [ wine-0.9.61 ] ~ [ wine-0.9.60 ] ~ [ wine-0.9.59 ] ~ [ wine-0.9.58 ] ~ [ wine-0.9.57 ] ~ [ wine-0.9.56 ] ~ [ wine-0.9.55 ] ~ [ wine-0.9.54 ] ~ [ wine-0.9.53 ] ~ [ wine-0.9.52 ] ~ [ wine-0.9.51 ] ~ [ wine-0.9.50 ] ~ [ wine-0.9.49 ] ~ [ wine-0.9.48 ] ~ [ wine-0.9.47 ] ~ [ wine-0.9.46 ] ~ [ wine-0.9.45 ] ~ [ wine-0.9.44 ] ~ [ wine-0.9.43 ] ~ [ wine-0.9.42 ] ~ [ wine-0.9.41 ] ~ [ wine-0.9.40 ] ~ [ wine-0.9.39 ] ~ [ wine-0.9.38 ] ~ [ wine-0.9.37 ] ~ [ wine-0.9.36 ] ~ [ wine-0.9.35 ] ~ [ wine-0.9.34 ] ~ [ wine-0.9.33 ] ~ [ wine-0.9.32 ] ~ [ wine-0.9.31 ] ~ [ wine-0.9.30 ] ~ [ wine-0.9.29 ] ~ [ wine-0.9.28 ] ~ [ wine-0.9.27 ] ~ [ wine-0.9.26 ] ~ [ wine-0.9.25 ] ~ [ wine-0.9.24 ] ~ [ wine-0.9.23 ] ~ [ wine-0.9.22 ] ~ [ wine-0.9.21 ] ~ [ wine-0.9.20 ] ~ [ wine-0.9.19 ] ~ [ wine-0.9.18 ] ~ [ wine-0.9.17 ] ~ [ wine-0.9.16 ] ~ [ wine-0.9.15 ] ~ [ wine-0.9.14 ] ~ [ wine-0.9.13 ] ~ [ wine-0.9.12 ] ~ [ wine-0.9.11 ] ~ [ wine-0.9.10 ] ~ [ wine-0.9.9 ] ~ [ wine-0.9.8 ] ~ [ wine-0.9.7 ] ~ [ wine-0.9.6 ] ~ [ wine-0.9.5 ] ~ [ wine-0.9.4 ] ~ [ wine-0.9.3 ] ~ [ wine-0.9.2 ] ~ [ wine-0.9.1 ] ~ [ wine-0.9 ] ~ [ wine20050930 ] ~ [ wine20050830 ] ~ [ wine20050725 ] ~ [ wine20050628 ] ~ [ wine20050524 ] ~ [ wine20050419 ] ~ [ wine20050310 ] ~ [ wine20050211 ] ~ [ wine20050111 ] ~ [ wine20041201 ] ~ [ wine20041019 ] ~ [ wine20040914 ] ~ [ wine20040813 ] ~ [ wine20040716 ] ~ [ wine20040615 ] ~ [ wine20040505 ] ~ [ wine20040408 ] ~ [ wine20040309 ] ~ [ wine20040213 ] ~ [ wine20040121 ] ~ [ wine20031212 ] ~ [ wine20031118 ] ~ [ wine20031016 ] ~ [ wine20030911 ] ~ [ wine20030813 ] ~ [ wine20030709 ] ~ [ wine20030618 ] ~ [ wine20030508 ] ~ [ wine20030408 ] ~ [ wine20030318 ] ~ [ wine20030219 ] ~ [ wine20030115 ] ~ [ wine20021219 ] ~ [ wine20021125 ] ~ [ wine20021031 ] ~ [ wine20021007 ] ~ [ wine20020904 ] ~ [ wine20020804 ] ~ [ wine20020710 ] ~ [ wine20020605 ] ~ [ wine20020509 ] ~ [ wine20020411 ] ~ [ wine20020310 ] ~ [ wine20020228 ] ~ [ wine20011226 ] ~ [ wine20011108 ] ~ [ wine20011004 ] ~ [ wine20010824 ] ~ [ wine20010731 ] ~ [ wine20010629 ] ~ [ wine20010510 ] ~ [ wine20010418 ] ~ [ wine20010326 ] ~ [ wine20010305 ] ~ [ wine20010216 ] ~ [ wine20010112 ] ~ [ wine20001222 ] ~ [ wine20001202 ] ~ [ wine20001026 ] ~ [ wine20001002 ] ~ [ wine20000909 ] ~ [ wine20000821 ] ~ [ wine20000801 ] ~ [ wine20000716 ] ~ [ wine20000326 ] ~ [ wine20000227 ] ~ [ wine20000130 ] ~ [ wine20000109 ] ~

  1 /*
  2  * comctl32 MRU unit tests
  3  *
  4  * Copyright (C) 2004 Jon Griffiths <jon_p_griffiths@yahoo.com>
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 #include <stdarg.h>
 21 
 22 #include "windef.h"
 23 #include "winbase.h"
 24 #include "wingdi.h"
 25 #include "winuser.h"
 26 #include "winnls.h"
 27 #include "winreg.h"
 28 #include "commctrl.h"
 29 #include "shlwapi.h"
 30 
 31 #include "wine/test.h"
 32 
 33 /* Keys for testing MRU functions */
 34 #define REG_TEST_BASEKEYA    "Software\\Wine"
 35 #define REG_TEST_BASESUBKEYA "Test"
 36 #define REG_TEST_KEYA    REG_TEST_BASEKEYA "\\" REG_TEST_BASESUBKEYA
 37 #define REG_TEST_SUBKEYA "MRUTest"
 38 #define REG_TEST_FULLKEY REG_TEST_KEYA "\\" REG_TEST_SUBKEYA
 39 
 40 /* Undocumented MRU structures & functions */
 41 typedef struct tagCREATEMRULISTA
 42 {
 43     DWORD   cbSize;
 44     DWORD   nMaxItems;
 45     DWORD   dwFlags;
 46     HKEY    hKey;
 47     LPCSTR  lpszSubKey;
 48     PROC    lpfnCompare;
 49 } CREATEMRULISTA, *LPCREATEMRULISTA;
 50 
 51 #define MRUF_STRING_LIST  0
 52 #define MRUF_BINARY_LIST  1
 53 #define MRUF_DELAYED_SAVE 2
 54 
 55 #define LIST_SIZE 3 /* Max entries for each mru */
 56 
 57 static CREATEMRULISTA mruA =
 58 {
 59     sizeof(CREATEMRULISTA),
 60     LIST_SIZE,
 61     0,
 62     NULL,
 63     REG_TEST_SUBKEYA,
 64     NULL
 65 };
 66 
 67 static HMODULE hComctl32;
 68 static HANDLE (WINAPI *pCreateMRUListA)(LPCREATEMRULISTA);
 69 static void   (WINAPI *pFreeMRUList)(HANDLE);
 70 static INT    (WINAPI *pAddMRUStringA)(HANDLE,LPCSTR);
 71 static INT    (WINAPI *pEnumMRUList)(HANDLE,INT,LPVOID,DWORD);
 72 /*
 73 static INT    (WINAPI *pFindMRUStringA)(HANDLE,LPCSTR,LPINT);
 74 */
 75 
 76 
 77 /* Based on RegDeleteTreeW from dlls/advapi32/registry.c */
 78 static LSTATUS mru_RegDeleteTreeA(HKEY hKey, LPCSTR lpszSubKey)
 79 {
 80     LONG ret;
 81     DWORD dwMaxSubkeyLen, dwMaxValueLen;
 82     DWORD dwMaxLen, dwSize;
 83     CHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
 84     HKEY hSubKey = hKey;
 85 
 86     if(lpszSubKey)
 87     {
 88         ret = RegOpenKeyExA(hKey, lpszSubKey, 0, KEY_READ, &hSubKey);
 89         if (ret) return ret;
 90     }
 91 
 92     /* Get highest length for keys, values */
 93     ret = RegQueryInfoKeyA(hSubKey, NULL, NULL, NULL, NULL,
 94             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
 95     if (ret) goto cleanup;
 96 
 97     dwMaxSubkeyLen++;
 98     dwMaxValueLen++;
 99     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
100     if (dwMaxLen > sizeof(szNameBuf)/sizeof(CHAR))
101     {
102         /* Name too big: alloc a buffer for it */
103         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(CHAR))))
104         {
105             ret = ERROR_NOT_ENOUGH_MEMORY;
106             goto cleanup;
107         }
108     }
109 
110 
111     /* Recursively delete all the subkeys */
112     while (TRUE)
113     {
114         dwSize = dwMaxLen;
115         if (RegEnumKeyExA(hSubKey, 0, lpszName, &dwSize, NULL,
116                           NULL, NULL, NULL)) break;
117 
118         ret = mru_RegDeleteTreeA(hSubKey, lpszName);
119         if (ret) goto cleanup;
120     }
121 
122     if (lpszSubKey)
123         ret = RegDeleteKeyA(hKey, lpszSubKey);
124     else
125         while (TRUE)
126         {
127             dwSize = dwMaxLen;
128             if (RegEnumValueA(hKey, 0, lpszName, &dwSize,
129                   NULL, NULL, NULL, NULL)) break;
130 
131             ret = RegDeleteValueA(hKey, lpszName);
132             if (ret) goto cleanup;
133         }
134 
135 cleanup:
136     /* Free buffer if allocated */
137     if (lpszName != szNameBuf)
138         HeapFree( GetProcessHeap(), 0, lpszName);
139     if(lpszSubKey)
140         RegCloseKey(hSubKey);
141     return ret;
142 }
143 
144 static BOOL create_reg_entries(void)
145 {
146     HKEY hKey = NULL;
147 
148     ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
149        "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
150     if (!hKey) return FALSE;
151     RegCloseKey(hKey);
152     return TRUE;
153 }
154 
155 static void delete_reg_entries(void)
156 {
157     HKEY hKey;
158 
159     if (RegOpenKeyExA(HKEY_CURRENT_USER, REG_TEST_BASEKEYA, 0, KEY_ALL_ACCESS,
160                       &hKey))
161         return;
162     mru_RegDeleteTreeA(hKey, REG_TEST_BASESUBKEYA);
163     RegCloseKey(hKey);
164 }
165 
166 static void check_reg_entries(const char *mrulist, const char**items)
167 {
168     char buff[128];
169     HKEY hKey = NULL;
170     DWORD type, size, ret;
171     unsigned int i;
172 
173     ok(!RegOpenKeyA(HKEY_CURRENT_USER, REG_TEST_FULLKEY, &hKey),
174        "Couldn't open test key \"%s\"\n", REG_TEST_FULLKEY);
175     if (!hKey) return;
176 
177     type = REG_SZ;
178     size = sizeof(buff);
179     buff[0] = '\0';
180     ret = RegQueryValueExA(hKey, "MRUList", NULL, &type, (LPBYTE)buff, &size);
181 
182     ok(!ret && buff[0], "Checking MRU: got %d from RegQueryValueExW\n", ret);
183     if(ret || !buff[0]) return;
184 
185     ok(strcmp(buff, mrulist) == 0, "Checking MRU: Expected list %s, got %s\n",
186        mrulist, buff);
187     if(strcmp(buff, mrulist)) return;
188 
189     for (i = 0; i < strlen(mrulist); i++)
190     {
191         char name[2];
192         name[0] = mrulist[i];
193         name[1] = '\0';
194         type = REG_SZ;
195         size = sizeof(buff);
196         buff[0] = '\0';
197         ret = RegQueryValueExA(hKey, name, NULL, &type, (LPBYTE)buff, &size);
198         ok(!ret && buff[0],
199            "Checking MRU item %d ('%c'): got %d from RegQueryValueExW\n",
200            i, mrulist[i], ret);
201         if(ret || !buff[0]) return;
202         ok(!strcmp(buff, items[mrulist[i]-'a']),
203            "Checking MRU item %d ('%c'): expected \"%s\", got \"%s\"\n",
204            i, mrulist[i], buff, items[mrulist[i] - 'a']);
205     }
206 }
207 
208 static INT CALLBACK cmp_mru_strA(LPCVOID data1, LPCVOID data2)
209 {
210     return lstrcmpiA(data1, data2);
211 }
212 
213 static HANDLE create_mruA(HKEY hKey, DWORD flags, PROC cmp)
214 {
215     mruA.dwFlags = flags;
216     mruA.lpfnCompare = cmp;
217     mruA.hKey = hKey;
218 
219     SetLastError(0);
220     return pCreateMRUListA(&mruA);
221 }
222 
223 static void test_MRUListA(void)
224 {
225     const char *checks[LIST_SIZE+1];
226     HANDLE hMRU;
227     HKEY hKey;
228     INT iRet;
229 
230     pCreateMRUListA = (void*)GetProcAddress(hComctl32,(LPCSTR)151);
231     pFreeMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)152);
232     pAddMRUStringA = (void*)GetProcAddress(hComctl32,(LPCSTR)153);
233     pEnumMRUList = (void*)GetProcAddress(hComctl32,(LPCSTR)154);
234 
235     if (!pCreateMRUListA || !pFreeMRUList || !pAddMRUStringA || !pEnumMRUList)
236     {
237         skip("MRU entry points not found\n");
238         return;
239     }
240 
241     if (0)
242     {
243     /* Create (NULL) - crashes native */
244     hMRU = pCreateMRUListA(NULL);
245     }
246 
247     /* Create (size too small) */
248     mruA.cbSize = sizeof(mruA) - 2;
249     hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
250     ok (!hMRU && !GetLastError(),
251         "CreateMRUListA(too small) expected NULL,0 got %p,%d\n",
252         hMRU, GetLastError());
253     mruA.cbSize = sizeof(mruA);
254 
255     /* Create (size too big) */
256     mruA.cbSize = sizeof(mruA) + 2;
257     hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
258     ok (!hMRU && !GetLastError(),
259         "CreateMRUListA(too big) expected NULL,0 got %p,%d\n",
260         hMRU, GetLastError());
261     mruA.cbSize = sizeof(mruA);
262 
263     /* Create (NULL hKey) */
264     hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
265     ok (!hMRU && !GetLastError(),
266         "CreateMRUListA(NULL key) expected NULL,0 got %p,%d\n",
267         hMRU, GetLastError());
268 
269     /* Create (NULL name) */
270     mruA.lpszSubKey = NULL;
271     hMRU = create_mruA(NULL, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
272     ok (!hMRU && !GetLastError(),
273         "CreateMRUListA(NULL name) expected NULL,0 got %p,%d\n",
274         hMRU, GetLastError());
275     mruA.lpszSubKey = REG_TEST_SUBKEYA;
276 
277     /* Create a string MRU */
278     ok(!RegCreateKeyA(HKEY_CURRENT_USER, REG_TEST_KEYA, &hKey),
279        "Couldn't create test key \"%s\"\n", REG_TEST_KEYA);
280     if (!hKey)
281         return;
282     hMRU = create_mruA(hKey, MRUF_STRING_LIST, (PROC)cmp_mru_strA);
283     ok(hMRU && !GetLastError(),
284        "CreateMRUListA(string) expected non-NULL,0 got %p,%d\n",
285        hMRU, GetLastError());
286 
287     if (hMRU)
288     {
289         char buffer[255];
290         checks[0] = "Test 1";
291         checks[1] = "Test 2";
292         checks[2] = "Test 3";
293         checks[3] = "Test 4";
294 
295         /* Add (NULL list) */
296         SetLastError(0);
297         iRet = pAddMRUStringA(NULL, checks[0]);
298         ok(iRet == -1 && !GetLastError(),
299            "AddMRUStringA(NULL list) expected -1,0 got %d,%d\n",
300            iRet, GetLastError());
301 
302         /* Add (NULL string) */
303         if (0)
304         {
305         /* Some native versions crash when passed NULL or fail to SetLastError()  */
306         SetLastError(0);
307         iRet = pAddMRUStringA(hMRU, NULL);
308         ok(iRet == 0 && GetLastError() == ERROR_INVALID_PARAMETER,
309            "AddMRUStringA(NULL str) expected 0,ERROR_INVALID_PARAMETER got %d,%d\n",
310            iRet, GetLastError());
311         }
312 
313         /* Add 3 strings. Check the registry is correct after each add */
314         SetLastError(0);
315         iRet = pAddMRUStringA(hMRU, checks[0]);
316         ok(iRet == 0 && !GetLastError(),
317            "AddMRUStringA(1) expected 0,0 got %d,%d\n",
318            iRet, GetLastError());
319         check_reg_entries("a", checks);
320 
321         SetLastError(0);
322         iRet = pAddMRUStringA(hMRU, checks[1]);
323         ok(iRet == 1 && !GetLastError(),
324            "AddMRUStringA(2) expected 1,0 got %d,%d\n",
325            iRet, GetLastError());
326         check_reg_entries("ba", checks);
327 
328         SetLastError(0);
329         iRet = pAddMRUStringA(hMRU, checks[2]);
330         ok(iRet == 2 && !GetLastError(),
331            "AddMRUStringA(2) expected 2,0 got %d,%d\n",
332            iRet, GetLastError());
333         check_reg_entries("cba", checks);
334 
335         /* Add a duplicate of the 2nd string - it should move to the front,
336          * but keep the same index in the registry.
337          */
338         SetLastError(0);
339         iRet = pAddMRUStringA(hMRU, checks[1]);
340         ok(iRet == 1 && !GetLastError(),
341            "AddMRUStringA(re-add 1) expected 1,0 got %d,%d\n",
342            iRet, GetLastError());
343         check_reg_entries("bca", checks);
344 
345         /* Add a new string - replaces the oldest string + moves to the front */
346         SetLastError(0);
347         iRet = pAddMRUStringA(hMRU, checks[3]);
348         ok(iRet == 0 && !GetLastError(),
349            "AddMRUStringA(add new) expected 0,0 got %d,%d\n",
350            iRet, GetLastError());
351         checks[0] = checks[3];
352         check_reg_entries("abc", checks);
353 
354         /* NULL buffer = get list size */
355         iRet = pEnumMRUList(hMRU, 0, NULL, 0);
356         ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
357 
358         /* negative item pos = get list size */
359         iRet = pEnumMRUList(hMRU, -1, NULL, 0);
360         ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
361 
362         /* negative item pos = get list size */
363         iRet = pEnumMRUList(hMRU, -5, NULL, 0);
364         ok(iRet == 3 || iRet == -1 /* Vista */, "EnumMRUList expected %d or -1, got %d\n", LIST_SIZE, iRet);
365 
366         /* negative item pos = get list size */
367         iRet = pEnumMRUList(hMRU, -1, buffer, 255);
368         ok(iRet == 3, "EnumMRUList expected %d, got %d\n", LIST_SIZE, iRet);
369 
370         /* negative item pos = get list size */
371         iRet = pEnumMRUList(hMRU, -5, buffer, 255);
372         ok(iRet == 3, "EnumMRUList expected %d, got %d\n", LIST_SIZE, iRet);
373 
374         /* check entry 0 */
375         buffer[0] = 0;
376         iRet = pEnumMRUList(hMRU, 0, buffer, 255);
377         todo_wine ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
378         ok(strcmp(buffer, checks[3]) == 0, "EnumMRUList expected %s, got %s\n", checks[3], buffer);
379 
380         /* check entry 0 with a too small buffer */
381         buffer[0] = 0;   /* overwritten with 'T' */
382         buffer[1] = 'A'; /* overwritten with 0   */
383         buffer[2] = 'A'; /* unchanged */
384         buffer[3] = 0;   /* unchanged */
385         iRet = pEnumMRUList(hMRU, 0, buffer, 2);
386         todo_wine ok(iRet == lstrlen(checks[3]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[3]), iRet);
387         todo_wine ok(strcmp(buffer, "T") == 0, "EnumMRUList expected %s, got %s\n", "T", buffer);
388         /* make sure space after buffer has old values */
389         ok(buffer[2] == 'A', "EnumMRUList expected %02x, got %02x\n", 'A', buffer[2]);
390 
391         /* check entry 1 */
392         buffer[0] = 0;
393         iRet = pEnumMRUList(hMRU, 1, buffer, 255);
394         todo_wine ok(iRet == lstrlen(checks[1]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[1]), iRet);
395         ok(strcmp(buffer, checks[1]) == 0, "EnumMRUList expected %s, got %s\n", checks[1], buffer);
396 
397         /* check entry 2 */
398         buffer[0] = 0;
399         iRet = pEnumMRUList(hMRU, 2, buffer, 255);
400         todo_wine ok(iRet == lstrlen(checks[2]), "EnumMRUList expected %d, got %d\n", lstrlen(checks[2]), iRet);
401         ok(strcmp(buffer, checks[2]) == 0, "EnumMRUList expected %s, got %s\n", checks[2], buffer);
402 
403         /* check out of bounds entry 3 */
404         strcpy(buffer, "dummy");
405         iRet = pEnumMRUList(hMRU, 3, buffer, 255);
406         ok(iRet == -1, "EnumMRUList expected %d, got %d\n", -1, iRet);
407         ok(strcmp(buffer, "dummy") == 0, "EnumMRUList expected unchanged buffer %s, got %s\n", "dummy", buffer);
408 
409         /* Finished with this MRU */
410         pFreeMRUList(hMRU);
411     }
412 
413     /* Free (NULL list) - Doesn't crash */
414     pFreeMRUList(NULL);
415 }
416 
417 START_TEST(mru)
418 {
419     hComctl32 = GetModuleHandleA("comctl32.dll");
420 
421     delete_reg_entries();
422     if (!create_reg_entries())
423         return;
424 
425     test_MRUListA();
426 
427     delete_reg_entries();
428 }
429 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.