Release 1.4-rc5.
[wine] / dlls / kernel32 / tests / module.c
1 /*
2  * Unit tests for module/DLL/library API
3  *
4  * Copyright (c) 2004 Eric Pouech
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
21 #include "wine/test.h"
22 #include <windows.h>
23
24 static DWORD (WINAPI *pGetDllDirectoryA)(DWORD,LPSTR);
25 static DWORD (WINAPI *pGetDllDirectoryW)(DWORD,LPWSTR);
26
27 static BOOL (WINAPI *pSetDllDirectoryA)(LPCSTR);
28
29 static BOOL is_unicode_enabled = TRUE;
30
31 static BOOL cmpStrAW(const char* a, const WCHAR* b, DWORD lenA, DWORD lenB)
32 {
33     WCHAR       aw[1024];
34
35     DWORD len = MultiByteToWideChar( AreFileApisANSI() ? CP_ACP : CP_OEMCP, 0,
36                                      a, lenA, aw, sizeof(aw) / sizeof(aw[0]) );
37     if (len != lenB) return FALSE;
38     return memcmp(aw, b, len * sizeof(WCHAR)) == 0;
39 }
40
41 static void testGetModuleFileName(const char* name)
42 {
43     HMODULE     hMod;
44     char        bufA[MAX_PATH];
45     WCHAR       bufW[MAX_PATH];
46     DWORD       len1A, len1W = 0, len2A, len2W = 0;
47
48     hMod = (name) ? GetModuleHandle(name) : NULL;
49
50     /* first test, with enough space in buffer */
51     memset(bufA, '-', sizeof(bufA));
52     SetLastError(0xdeadbeef);
53     len1A = GetModuleFileNameA(hMod, bufA, sizeof(bufA));
54     ok(GetLastError() == ERROR_SUCCESS ||
55        broken(GetLastError() == 0xdeadbeef), /* <= XP SP3 */
56        "LastError was not reset: %u\n", GetLastError());
57     ok(len1A > 0, "Getting module filename for handle %p\n", hMod);
58
59     if (is_unicode_enabled)
60     {
61         memset(bufW, '-', sizeof(bufW));
62         SetLastError(0xdeadbeef);
63         len1W = GetModuleFileNameW(hMod, bufW, sizeof(bufW) / sizeof(WCHAR));
64         ok(GetLastError() == ERROR_SUCCESS ||
65            broken(GetLastError() == 0xdeadbeef), /* <= XP SP3 */
66            "LastError was not reset: %u\n", GetLastError());
67         ok(len1W > 0, "Getting module filename for handle %p\n", hMod);
68     }
69
70     ok(len1A == strlen(bufA), "Unexpected length of GetModuleFilenameA (%d/%d)\n", len1A, lstrlenA(bufA));
71
72     if (is_unicode_enabled)
73     {
74         ok(len1W == lstrlenW(bufW), "Unexpected length of GetModuleFilenameW (%d/%d)\n", len1W, lstrlenW(bufW));
75         ok(cmpStrAW(bufA, bufW, len1A, len1W), "Comparing GetModuleFilenameAW results\n");
76     }
77
78     /* second test with a buffer too small */
79     memset(bufA, '-', sizeof(bufA));
80     len2A = GetModuleFileNameA(hMod, bufA, len1A / 2);
81     ok(len2A > 0, "Getting module filename for handle %p\n", hMod);
82
83     if (is_unicode_enabled)
84     {
85         memset(bufW, '-', sizeof(bufW));
86         len2W = GetModuleFileNameW(hMod, bufW, len1W / 2);
87         ok(len2W > 0, "Getting module filename for handle %p\n", hMod);
88         ok(cmpStrAW(bufA, bufW, len2A, len2W), "Comparing GetModuleFilenameAW results with buffer too small\n" );
89         ok(len1W / 2 == len2W, "Correct length in GetModuleFilenameW with buffer too small (%d/%d)\n", len1W / 2, len2W);
90     }
91
92     ok(len1A / 2 == len2A || 
93        len1A / 2 == len2A + 1, /* Win9x */
94        "Correct length in GetModuleFilenameA with buffer too small (%d/%d)\n", len1A / 2, len2A);
95 }
96
97 static void testGetModuleFileName_Wrong(void)
98 {
99     char        bufA[MAX_PATH];
100     WCHAR       bufW[MAX_PATH];
101
102     /* test wrong handle */
103     if (is_unicode_enabled)
104     {
105         bufW[0] = '*';
106         ok(GetModuleFileNameW((void*)0xffffffff, bufW, sizeof(bufW) / sizeof(WCHAR)) == 0, "Unexpected success in module handle\n");
107         ok(bufW[0] == '*', "When failing, buffer shouldn't be written to\n");
108     }
109
110     bufA[0] = '*';
111     ok(GetModuleFileNameA((void*)0xffffffff, bufA, sizeof(bufA)) == 0, "Unexpected success in module handle\n");
112     ok(bufA[0] == '*' ||
113        bufA[0] == 0 /* Win9x */,
114        "When failing, buffer shouldn't be written to\n");
115 }
116
117 static void testLoadLibraryA(void)
118 {
119     HMODULE hModule, hModule1;
120     FARPROC fp;
121
122     SetLastError(0xdeadbeef);
123     hModule = LoadLibraryA("kernel32.dll");
124     ok( hModule != NULL, "kernel32.dll should be loadable\n");
125     ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %d\n", GetLastError());
126
127     fp = GetProcAddress(hModule, "CreateFileA");
128     ok( fp != NULL, "CreateFileA should be there\n");
129     ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %d\n", GetLastError());
130
131     SetLastError(0xdeadbeef);
132     hModule1 = LoadLibraryA("kernel32   ");
133     /* Only winNT does this */
134     if (GetLastError() != ERROR_DLL_NOT_FOUND)
135     {
136         ok( hModule1 != NULL, "\"kernel32   \" should be loadable\n");
137         ok( GetLastError() == 0xdeadbeef, "GetLastError should be 0xdeadbeef but is %d\n", GetLastError());
138         ok( hModule == hModule1, "Loaded wrong module\n");
139         FreeLibrary(hModule1);
140     }
141     FreeLibrary(hModule);
142 }
143
144 static void testNestedLoadLibraryA(void)
145 {
146     static const char dllname[] = "shell32.dll";
147     char path1[MAX_PATH], path2[MAX_PATH];
148     HMODULE hModule1, hModule2, hModule3;
149
150     /* This is not really a Windows conformance test, but more a Wine
151      * regression test. Wine's builtin dlls can be loaded from multiple paths,
152      * and this test tries to make sure that Wine does not get confused and
153      * really unloads the Unix .so file at the right time. Failure to do so
154      * will result in the dll being unloadable.
155      * This test must be done with a dll that can be unloaded, which means:
156      * - it must not already be loaded
157      * - it must not have a 16-bit counterpart
158      */
159     GetWindowsDirectory(path1, sizeof(path1));
160     strcat(path1, "\\system\\");
161     strcat(path1, dllname);
162     hModule1 = LoadLibraryA(path1);
163     if (!hModule1)
164     {
165         /* We must be on Windows NT, so we cannot test */
166         return;
167     }
168
169     GetWindowsDirectory(path2, sizeof(path2));
170     strcat(path2, "\\system32\\");
171     strcat(path2, dllname);
172     hModule2 = LoadLibraryA(path2);
173     if (!hModule2)
174     {
175         /* We must be on Windows 9x, so we cannot test */
176         ok(FreeLibrary(hModule1), "FreeLibrary() failed\n");
177         return;
178     }
179
180     /* The first LoadLibrary() call may have registered the dll under the
181      * system32 path. So load it, again, under the '...\system\...' path so
182      * Wine does not immediately notice that it is already loaded.
183      */
184     hModule3 = LoadLibraryA(path1);
185     ok(hModule3 != NULL, "LoadLibrary(%s) failed\n", path1);
186
187     /* Now fully unload the dll */
188     ok(FreeLibrary(hModule3), "FreeLibrary() failed\n");
189     ok(FreeLibrary(hModule2), "FreeLibrary() failed\n");
190     ok(FreeLibrary(hModule1), "FreeLibrary() failed\n");
191     ok(GetModuleHandle(dllname) == NULL, "%s was not fully unloaded\n", dllname);
192
193     /* Try to load the dll again, if refcounting is ok, this should work */
194     hModule1 = LoadLibraryA(path1);
195     ok(hModule1 != NULL, "LoadLibrary(%s) failed\n", path1);
196     if (hModule1 != NULL)
197         ok(FreeLibrary(hModule1), "FreeLibrary() failed\n");
198 }
199
200 static void testLoadLibraryA_Wrong(void)
201 {
202     HMODULE hModule;
203
204     /* Try to load a nonexistent dll */
205     SetLastError(0xdeadbeef);
206     hModule = LoadLibraryA("non_ex_pv.dll");
207     ok( !hModule, "non_ex_pv.dll should be not loadable\n");
208     ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_DLL_NOT_FOUND, 
209         "Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND (win9x), got %d\n", GetLastError());
210
211     /* Just in case */
212     FreeLibrary(hModule);
213 }
214
215 static void testGetProcAddress_Wrong(void)
216 {
217     FARPROC fp;
218
219     SetLastError(0xdeadbeef);
220     fp = GetProcAddress(NULL, "non_ex_call");
221     ok( !fp, "non_ex_call should not be found\n");
222     ok( GetLastError() == ERROR_PROC_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
223         "Expected ERROR_PROC_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %d\n", GetLastError());
224
225     SetLastError(0xdeadbeef);
226     fp = GetProcAddress((HMODULE)0xdeadbeef, "non_ex_call");
227     ok( !fp, "non_ex_call should not be found\n");
228     ok( GetLastError() == ERROR_MOD_NOT_FOUND || GetLastError() == ERROR_INVALID_HANDLE,
229         "Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_HANDLE(win9x), got %d\n", GetLastError());
230 }
231
232 static void testLoadLibraryEx(void)
233 {
234     CHAR path[MAX_PATH];
235     HMODULE hmodule;
236     HANDLE hfile;
237     BOOL ret;
238
239     hfile = CreateFileA("testfile.dll", GENERIC_READ | GENERIC_WRITE,
240                         FILE_SHARE_READ | FILE_SHARE_WRITE,
241                         NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
242     ok(hfile != INVALID_HANDLE_VALUE, "Expected a valid file handle\n");
243
244     /* NULL lpFileName */
245     if (is_unicode_enabled)
246     {
247         SetLastError(0xdeadbeef);
248         hmodule = LoadLibraryExA(NULL, NULL, 0);
249         ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
250         ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
251            GetLastError() == ERROR_INVALID_PARAMETER, /* win9x */
252            "Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
253            GetLastError());
254     }
255     else
256         win_skip("NULL filename crashes on WinMe\n");
257
258     /* empty lpFileName */
259     SetLastError(0xdeadbeef);
260     hmodule = LoadLibraryExA("", NULL, 0);
261     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
262     ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
263        GetLastError() == ERROR_DLL_NOT_FOUND, /* win9x */
264        "Expected ERROR_MOD_NOT_FOUND or ERROR_DLL_NOT_FOUND, got %d\n",
265        GetLastError());
266
267     /* hFile is non-NULL */
268     SetLastError(0xdeadbeef);
269     hmodule = LoadLibraryExA("testfile.dll", hfile, 0);
270     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
271     todo_wine
272     {
273         ok(GetLastError() == ERROR_SHARING_VIOLATION ||
274            GetLastError() == ERROR_INVALID_PARAMETER || /* win2k3 */
275            GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
276            "Unexpected last error, got %d\n", GetLastError());
277     }
278
279     SetLastError(0xdeadbeef);
280     hmodule = LoadLibraryExA("testfile.dll", (HANDLE)0xdeadbeef, 0);
281     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
282     todo_wine
283     {
284         ok(GetLastError() == ERROR_SHARING_VIOLATION ||
285            GetLastError() == ERROR_INVALID_PARAMETER || /* win2k3 */
286            GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
287            "Unexpected last error, got %d\n", GetLastError());
288     }
289
290     /* try to open a file that is locked */
291     SetLastError(0xdeadbeef);
292     hmodule = LoadLibraryExA("testfile.dll", NULL, 0);
293     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
294     todo_wine
295     {
296         ok(GetLastError() == ERROR_SHARING_VIOLATION ||
297            GetLastError() == ERROR_FILE_NOT_FOUND, /* win9x */
298            "Expected ERROR_SHARING_VIOLATION or ERROR_FILE_NOT_FOUND, got %d\n",
299            GetLastError());
300     }
301
302     /* lpFileName does not matter */
303     if (is_unicode_enabled)
304     {
305         SetLastError(0xdeadbeef);
306         hmodule = LoadLibraryExA(NULL, hfile, 0);
307         ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
308         ok(GetLastError() == ERROR_MOD_NOT_FOUND ||
309            GetLastError() == ERROR_INVALID_PARAMETER, /* win2k3 */
310            "Expected ERROR_MOD_NOT_FOUND or ERROR_INVALID_PARAMETER, got %d\n",
311            GetLastError());
312     }
313
314     CloseHandle(hfile);
315
316     /* load empty file */
317     SetLastError(0xdeadbeef);
318     hmodule = LoadLibraryExA("testfile.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
319     ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
320     todo_wine
321     {
322         ok(GetLastError() == ERROR_FILE_INVALID ||
323            GetLastError() == ERROR_BAD_FORMAT, /* win9x */
324            "Expected ERROR_FILE_INVALID or ERROR_BAD_FORMAT, got %d\n",
325            GetLastError());
326     }
327
328     DeleteFileA("testfile.dll");
329
330     GetSystemDirectoryA(path, MAX_PATH);
331     if (path[lstrlenA(path) - 1] != '\\')
332         lstrcatA(path, "\\");
333     lstrcatA(path, "kernel32.dll");
334
335     /* load kernel32.dll with an absolute path */
336     SetLastError(0xdeadbeef);
337     hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
338     ok(hmodule != 0, "Expected valid module handle\n");
339     ok(GetLastError() == 0xdeadbeef ||
340        GetLastError() == ERROR_SUCCESS, /* win9x */
341        "Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
342
343     /* try invalid file handle */
344     SetLastError(0xdeadbeef);
345     hmodule = LoadLibraryExA(path, (HANDLE)0xdeadbeef, 0);
346     if (!hmodule)  /* succeeds on xp and older */
347         ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %u\n", GetLastError());
348
349     CloseHandle(hmodule);
350
351     /* load kernel32.dll with no path */
352     SetLastError(0xdeadbeef);
353     hmodule = LoadLibraryExA("kernel32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
354     ok(hmodule != 0, "Expected valid module handle\n");
355     ok(GetLastError() == 0xdeadbeef ||
356        GetLastError() == ERROR_SUCCESS, /* win9x */
357        "Expected 0xdeadbeef or ERROR_SUCCESS, got %d\n", GetLastError());
358
359     CloseHandle(hmodule);
360
361     GetCurrentDirectoryA(MAX_PATH, path);
362     if (path[lstrlenA(path) - 1] != '\\')
363         lstrcatA(path, "\\");
364     lstrcatA(path, "kernel32.dll");
365
366     /* load kernel32.dll with an absolute path that does not exist */
367     SetLastError(0xdeadbeef);
368     hmodule = LoadLibraryExA(path, NULL, LOAD_LIBRARY_AS_DATAFILE);
369     todo_wine
370     {
371         ok(hmodule == 0, "Expected 0, got %p\n", hmodule);
372     }
373     ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
374        broken(GetLastError() == ERROR_INVALID_HANDLE),  /* nt4 */
375        "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
376
377     /* Free the loaded dll when its the first time this dll is loaded
378        in process - First time should pass, second fail */
379     SetLastError(0xdeadbeef);
380     hmodule = LoadLibraryExA("comctl32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE);
381     ok(hmodule != 0, "Expected valid module handle\n");
382
383     SetLastError(0xdeadbeef);
384     ret = FreeLibrary(hmodule);
385     ok(ret, "Expected to be able to free the module, failed with %d\n", GetLastError());
386     SetLastError(0xdeadbeef);
387     ret = FreeLibrary(hmodule);
388     ok(!ret, "Unexpected ability to free the module, failed with %d\n", GetLastError());
389
390     CloseHandle(hmodule);
391
392 }
393
394 static void testGetDllDirectory(void)
395 {
396     CHAR bufferA[MAX_PATH];
397     WCHAR bufferW[MAX_PATH];
398     DWORD length, ret;
399     int i;
400     static const char *dll_directories[] =
401     {
402         "",
403         "C:\\Some\\Path",
404         "C:\\Some\\Path\\",
405         "Q:\\A\\Long\\Path with spaces that\\probably\\doesn't exist!",
406     };
407     const int test_count = sizeof(dll_directories) / sizeof(dll_directories[0]);
408
409     if (!pGetDllDirectoryA || !pGetDllDirectoryW)
410     {
411         win_skip("GetDllDirectory not available\n");
412         return;
413     }
414     if (!pSetDllDirectoryA)
415     {
416         win_skip("SetDllDirectoryA not available\n");
417         return;
418     }
419
420     for (i = 0; i < test_count; i++)
421     {
422         length = strlen(dll_directories[i]);
423         if (!pSetDllDirectoryA(dll_directories[i]))
424         {
425             skip("i=%d, SetDllDirectoryA failed\n", i);
426             continue;
427         }
428
429         /* no buffer, determine length */
430         ret = pGetDllDirectoryA(0, NULL);
431         ok(ret == length + 1, "Expected %u, got %u\n", length + 1, ret);
432
433         ret = pGetDllDirectoryW(0, NULL);
434         ok(ret == length + 1, "Expected %u, got %u\n", length + 1, ret);
435
436         /* buffer of exactly the right size */
437         bufferA[length] = 'A';
438         bufferA[length + 1] = 'A';
439         ret = pGetDllDirectoryA(length + 1, bufferA);
440         ok(ret == length, "i=%d, Expected %u, got %u\n", i, length, ret);
441         ok(bufferA[length + 1] == 'A', "i=%d, Buffer overflow\n", i);
442         ok(strcmp(bufferA, dll_directories[i]) == 0, "i=%d, Wrong path returned: '%s'\n", i, bufferA);
443
444         bufferW[length] = 'A';
445         bufferW[length + 1] = 'A';
446         ret = pGetDllDirectoryW(length + 1, bufferW);
447         ok(ret == length, "i=%d, Expected %u, got %u\n", i, length, ret);
448         ok(bufferW[length + 1] == 'A', "i=%d, Buffer overflow\n", i);
449         ok(cmpStrAW(dll_directories[i], bufferW, length, length),
450            "i=%d, Wrong path returned: %s\n", i, wine_dbgstr_w(bufferW));
451
452         /* zero size buffer
453          * the A version always null-terminates the buffer,
454          * the W version doesn't do it on some platforms */
455         bufferA[0] = 'A';
456         ret = pGetDllDirectoryA(0, bufferA);
457         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
458         ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
459
460         bufferW[0] = 'A';
461         ret = pGetDllDirectoryW(0, bufferW);
462         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
463         ok(bufferW[0] == 0 || /* XP, 2003 */
464            broken(bufferW[0] == 'A'), "i=%d, Buffer overflow\n", i);
465
466         /* buffer just one too short */
467         bufferA[0] = 'A';
468         ret = pGetDllDirectoryA(length, bufferA);
469         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
470         ok(bufferA[0] == 0, "i=%d, Buffer not null terminated\n", i);
471
472         bufferW[0] = 'A';
473         ret = pGetDllDirectoryW(length, bufferW);
474         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
475         ok(bufferW[0] == 0 || /* XP, 2003 */
476            broken(bufferW[0] == 'A'), "i=%d, Buffer overflow\n", i);
477
478         /* no buffer, but too short length */
479         ret = pGetDllDirectoryA(length, NULL);
480         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
481
482         ret = pGetDllDirectoryW(length, NULL);
483         ok(ret == length + 1, "i=%d, Expected %u, got %u\n", i, length + 1, ret);
484     }
485
486     /* unset whatever we did so following tests won't be affected */
487     pSetDllDirectoryA(NULL);
488 }
489
490 static void init_pointers(void)
491 {
492     HMODULE hKernel32 = GetModuleHandleA("kernel32.dll");
493
494 #define MAKEFUNC(f) (p##f = (void*)GetProcAddress(hKernel32, #f))
495     MAKEFUNC(GetDllDirectoryA);
496     MAKEFUNC(GetDllDirectoryW);
497     MAKEFUNC(SetDllDirectoryA);
498 #undef MAKEFUNC
499 }
500
501 START_TEST(module)
502 {
503     WCHAR filenameW[MAX_PATH];
504
505     /* Test if we can use GetModuleFileNameW */
506
507     SetLastError(0xdeadbeef);
508     GetModuleFileNameW(NULL, filenameW, MAX_PATH);
509     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
510     {
511         win_skip("GetModuleFileNameW not existing on this platform, skipping W-calls\n");
512         is_unicode_enabled = FALSE;
513     }
514
515     init_pointers();
516
517     testGetModuleFileName(NULL);
518     testGetModuleFileName("kernel32.dll");
519     testGetModuleFileName_Wrong();
520
521     testGetDllDirectory();
522
523     testLoadLibraryA();
524     testNestedLoadLibraryA();
525     testLoadLibraryA_Wrong();
526     testGetProcAddress_Wrong();
527     testLoadLibraryEx();
528 }