1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | /*===================================================================== |
6 | ** |
7 | ** Source: test1.c (FreeLibraryAndExitThread) |
8 | ** |
9 | ** Purpose: Tests the PAL implementation of the FreeLibraryAndExitThread |
10 | ** function. FreeLibraryAndExitThread when run will exit the |
11 | ** process that it is called within, therefore we create a |
12 | ** thread to run the API. Then test for the existance of the |
13 | ** thread and access to the library. |
14 | ** |
15 | ** |
16 | **===================================================================*/ |
17 | |
18 | #include <palsuite.h> |
19 | |
20 | /*Define platform specific information*/ |
21 | |
22 | /* SHLEXT is defined only for Unix variants */ |
23 | #if defined(SHLEXT) |
24 | #define LibraryName "dlltest"SHLEXT |
25 | #else |
26 | #define LibraryName "dlltest" |
27 | #endif |
28 | |
29 | #define TIMEOUT 60000 |
30 | |
31 | BOOL PALAPI StartThreadTest(); |
32 | DWORD PALAPI CreateTestThread(LPVOID); |
33 | BOOL PALAPI TestDll(HMODULE, int); |
34 | |
35 | int __cdecl main(int argc, char* argv[]) |
36 | { |
37 | /*Initialize the PAL*/ |
38 | if ((PAL_Initialize(argc, argv)) != 0) |
39 | { |
40 | return (FAIL); |
41 | } |
42 | |
43 | if (!StartThreadTest()) |
44 | { |
45 | Fail("ERROR: FreeLibraryAndExitThread test failed.\n" ); |
46 | } |
47 | |
48 | /*Terminate the PAL*/ |
49 | PAL_Terminate(); |
50 | return PASS; |
51 | |
52 | } |
53 | |
54 | |
55 | BOOL PALAPI StartThreadTest() |
56 | { |
57 | HMODULE hLib; |
58 | HANDLE hThread; |
59 | DWORD dwThreadId; |
60 | LPTHREAD_START_ROUTINE lpStartAddress = &CreateTestThread; |
61 | LPVOID lpParameter = (LPVOID)lpStartAddress; |
62 | DWORD rc = -1; |
63 | /*Load library (DLL).*/ |
64 | hLib = LoadLibrary(LibraryName); |
65 | if(hLib == NULL) |
66 | { |
67 | Trace("ERROR: Unable to load library %s\n" , LibraryName); |
68 | |
69 | return (FALSE); |
70 | } |
71 | |
72 | /*Start the test thread*/ |
73 | hThread = CreateThread(NULL, |
74 | (DWORD)0, |
75 | lpStartAddress, |
76 | hLib, |
77 | (DWORD)NULL, |
78 | &dwThreadId); |
79 | if(hThread == NULL) |
80 | { |
81 | Trace("ERROR:%u: Unable to create thread.\n" , |
82 | GetLastError()); |
83 | |
84 | FreeLibrary(hLib); |
85 | return (FALSE); |
86 | } |
87 | |
88 | /*Wait on thread.*/ |
89 | rc = WaitForSingleObject(hThread, TIMEOUT); |
90 | if( rc != WAIT_OBJECT_0 ) |
91 | { |
92 | Trace("ERROR:%u: hThread=0x%4.4lx not exited by " |
93 | "FreeLibraryAndExitThread, RC[%d]\n" , |
94 | GetLastError(), |
95 | hThread, rc); |
96 | |
97 | // There is a possibility that the other thread might |
98 | // still be using the library VSW:337893 |
99 | // FreeLibrary(hLib); |
100 | CloseHandle(hThread); |
101 | return (FALSE); |
102 | } |
103 | |
104 | /*Test access to DLL.*/ |
105 | if(!TestDll(hLib, 0)) |
106 | { |
107 | Trace("ERROR: TestDll function returned FALSE " |
108 | "expected TRUE\n." ); |
109 | |
110 | CloseHandle(hThread); |
111 | return (FALSE); |
112 | } |
113 | |
114 | FreeLibrary(hLib); |
115 | /*Clean-up thread.*/ |
116 | CloseHandle(hThread); |
117 | |
118 | return (TRUE); |
119 | } |
120 | |
121 | BOOL PALAPI TestDll(HMODULE hLib, int testResult) |
122 | { |
123 | int RetVal; |
124 | char FunctName[] = "DllTest" ; |
125 | FARPROC DllAddr; |
126 | |
127 | /* Attempt to grab the proc address of the dll function. |
128 | * This one should succeed.*/ |
129 | if(testResult == 1) |
130 | { |
131 | DllAddr = GetProcAddress(hLib, FunctName); |
132 | if(DllAddr == NULL) |
133 | { |
134 | Trace("ERROR: Unable to load function \"%s\" library \"%s\"\n" , |
135 | FunctName, |
136 | LibraryName); |
137 | return (FALSE); |
138 | } |
139 | /* Run the function in the DLL, |
140 | * to ensure that the DLL was loaded properly.*/ |
141 | RetVal = DllAddr(); |
142 | if (RetVal != 1) |
143 | { |
144 | Trace("ERROR: Unable to receive correct information from DLL! " |
145 | ":expected \"1\", returned \"%d\"\n" , |
146 | RetVal); |
147 | return (FALSE); |
148 | } |
149 | } |
150 | |
151 | /* Attempt to grab the proc address of the dll function. |
152 | * This one should fail.*/ |
153 | if(testResult == 0) |
154 | { |
155 | DllAddr = GetProcAddress(hLib, FunctName); |
156 | if(DllAddr != NULL) |
157 | { |
158 | Trace("ERROR: Able to load function \"%s\" from free'd" |
159 | " library \"%s\"\n" , |
160 | FunctName, |
161 | LibraryName); |
162 | return (FALSE); |
163 | } |
164 | } |
165 | return (TRUE); |
166 | } |
167 | |
168 | DWORD PALAPI CreateTestThread(LPVOID lpParam) |
169 | { |
170 | /* Test access to DLL.*/ |
171 | TestDll(lpParam, 1); |
172 | |
173 | /*Free library and exit thread.*/ |
174 | FreeLibraryAndExitThread(lpParam, (DWORD)0); |
175 | |
176 | /* NOT REACHED */ |
177 | |
178 | /*Infinite loop, we should not get here.*/ |
179 | while(1); |
180 | |
181 | return (DWORD)0; |
182 | } |
183 | |
184 | |