xref: /reactos/dll/win32/kernel32/client/loader.c (revision bd0a5498)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT: See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT  : ReactOS system libraries
4c2c66affSColin Finck  * MODULE   : kernel32.dll
5c2c66affSColin Finck  * FILE     : reactos/dll/win32/kernel32/misc/ldr.c
6c2c66affSColin Finck  * AUTHOR   : Aleksey Bragin <aleksey@reactos.org>
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include <k32.h>
10c2c66affSColin Finck 
11c2c66affSColin Finck #define NDEBUG
12c2c66affSColin Finck #include <debug.h>
13c2c66affSColin Finck 
14c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
15c2c66affSColin Finck 
16c2c66affSColin Finck NTSTATUS
17c2c66affSColin Finck WINAPI
BasepInitializeTermsrvFpns(VOID)18c2c66affSColin Finck BasepInitializeTermsrvFpns(VOID)
19c2c66affSColin Finck {
20c2c66affSColin Finck     UNIMPLEMENTED;
21c2c66affSColin Finck     return STATUS_NOT_IMPLEMENTED;
22c2c66affSColin Finck }
23c2c66affSColin Finck 
24c2c66affSColin Finck DWORD
25c2c66affSColin Finck WINAPI
BasepGetModuleHandleExParameterValidation(DWORD dwFlags,LPCWSTR lpwModuleName,HMODULE * phModule)26c2c66affSColin Finck BasepGetModuleHandleExParameterValidation(DWORD dwFlags,
27c2c66affSColin Finck                                           LPCWSTR lpwModuleName,
28c2c66affSColin Finck                                           HMODULE *phModule)
29c2c66affSColin Finck {
30c2c66affSColin Finck     /* Set phModule to 0 if it's not a NULL pointer */
31c2c66affSColin Finck     if (phModule) *phModule = 0;
32c2c66affSColin Finck 
33c2c66affSColin Finck     /* Check for invalid flags combination */
34c2c66affSColin Finck     if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN |
35c2c66affSColin Finck                     GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
36c2c66affSColin Finck                     GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) ||
37c2c66affSColin Finck         ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) &&
38c2c66affSColin Finck          (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ||
39c2c66affSColin Finck          (!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
40c2c66affSColin Finck         )
41c2c66affSColin Finck     {
42c2c66affSColin Finck         BaseSetLastNTError(STATUS_INVALID_PARAMETER_1);
43c2c66affSColin Finck         return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
44c2c66affSColin Finck     }
45c2c66affSColin Finck 
46c2c66affSColin Finck     /* Check 2nd parameter */
47c2c66affSColin Finck     if (!phModule)
48c2c66affSColin Finck     {
49c2c66affSColin Finck         BaseSetLastNTError(STATUS_INVALID_PARAMETER_2);
50c2c66affSColin Finck         return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
51c2c66affSColin Finck     }
52c2c66affSColin Finck 
53c2c66affSColin Finck     /* Return what we have according to the module name */
54c2c66affSColin Finck     if (lpwModuleName)
55c2c66affSColin Finck     {
56c2c66affSColin Finck         return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE;
57c2c66affSColin Finck     }
58c2c66affSColin Finck 
59c2c66affSColin Finck     /* No name given, so put ImageBaseAddress there */
60c2c66affSColin Finck     *phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress;
61c2c66affSColin Finck 
62c2c66affSColin Finck     return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS;
63c2c66affSColin Finck }
64c2c66affSColin Finck 
65c2c66affSColin Finck PVOID
66c2c66affSColin Finck WINAPI
BasepMapModuleHandle(HMODULE hModule,BOOLEAN AsDataFile)67c2c66affSColin Finck BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile)
68c2c66affSColin Finck {
69c2c66affSColin Finck     /* If no handle is provided - use current image base address */
70c2c66affSColin Finck     if (!hModule) return NtCurrentPeb()->ImageBaseAddress;
71c2c66affSColin Finck 
72c2c66affSColin Finck     /* Check if it's a normal or a datafile one */
73c2c66affSColin Finck     if (LDR_IS_DATAFILE(hModule) && !AsDataFile)
74c2c66affSColin Finck         return NULL;
75c2c66affSColin Finck 
76c2c66affSColin Finck     /* It's a normal DLL, just return its handle */
77c2c66affSColin Finck     return hModule;
78c2c66affSColin Finck }
79c2c66affSColin Finck 
80c2c66affSColin Finck /*
81c2c66affSColin Finck  * @implemented
82c2c66affSColin Finck  */
83c2c66affSColin Finck BOOL
84c2c66affSColin Finck WINAPI
DisableThreadLibraryCalls(IN HMODULE hLibModule)85c2c66affSColin Finck DisableThreadLibraryCalls(
86c2c66affSColin Finck     IN HMODULE hLibModule)
87c2c66affSColin Finck {
88c2c66affSColin Finck     NTSTATUS Status;
89c2c66affSColin Finck 
90c2c66affSColin Finck     /* Disable thread library calls */
91c2c66affSColin Finck     Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule);
92c2c66affSColin Finck 
93c2c66affSColin Finck     /* If it wasn't success - set last error and return failure */
94c2c66affSColin Finck     if (!NT_SUCCESS(Status))
95c2c66affSColin Finck     {
96c2c66affSColin Finck         BaseSetLastNTError(Status);
97c2c66affSColin Finck         return FALSE;
98c2c66affSColin Finck     }
99c2c66affSColin Finck 
100c2c66affSColin Finck     /* Return success */
101c2c66affSColin Finck     return TRUE;
102c2c66affSColin Finck }
103c2c66affSColin Finck 
104c2c66affSColin Finck 
105c2c66affSColin Finck /*
106c2c66affSColin Finck  * @implemented
107c2c66affSColin Finck  */
108c2c66affSColin Finck HINSTANCE
109c2c66affSColin Finck WINAPI
110c2c66affSColin Finck DECLSPEC_HOTPATCH
LoadLibraryA(LPCSTR lpLibFileName)111c2c66affSColin Finck LoadLibraryA(LPCSTR lpLibFileName)
112c2c66affSColin Finck {
1131b70ddd8STimo Kreuzer     static const CHAR TwainDllName[] = "twain_32.dll";
114c2c66affSColin Finck     LPSTR PathBuffer;
115c2c66affSColin Finck     UINT Len;
116c2c66affSColin Finck     HINSTANCE Result;
117c2c66affSColin Finck 
118c2c66affSColin Finck     /* Treat twain_32.dll in a special way (what a surprise...) */
1191b70ddd8STimo Kreuzer     if (lpLibFileName && !_strcmpi(lpLibFileName, TwainDllName))
120c2c66affSColin Finck     {
121c2c66affSColin Finck         /* Allocate space for the buffer */
1221b70ddd8STimo Kreuzer         PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH + sizeof(ANSI_NULL));
123c2c66affSColin Finck         if (PathBuffer)
124c2c66affSColin Finck         {
125c2c66affSColin Finck             /* Get windows dir in this buffer */
1261b70ddd8STimo Kreuzer             Len = GetWindowsDirectoryA(PathBuffer, MAX_PATH);
1271b70ddd8STimo Kreuzer             if ((Len != 0) && (Len < (MAX_PATH - sizeof(TwainDllName) - sizeof('\\'))))
128c2c66affSColin Finck             {
129c2c66affSColin Finck                 /* We successfully got windows directory. Concatenate twain_32.dll to it */
1301b70ddd8STimo Kreuzer                 PathBuffer[Len] = '\\';
1311b70ddd8STimo Kreuzer                 strcpy(&PathBuffer[Len + 1], TwainDllName);
132c2c66affSColin Finck 
133c2c66affSColin Finck                 /* And recursively call ourselves with a new string */
134c2c66affSColin Finck                 Result = LoadLibraryA(PathBuffer);
135c2c66affSColin Finck 
136c2c66affSColin Finck                 /* If it was successful -  free memory and return result */
137c2c66affSColin Finck                 if (Result)
138c2c66affSColin Finck                 {
139c2c66affSColin Finck                     RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
140c2c66affSColin Finck                     return Result;
141c2c66affSColin Finck                 }
142c2c66affSColin Finck             }
143c2c66affSColin Finck 
144c2c66affSColin Finck             /* Free allocated buffer */
145c2c66affSColin Finck             RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
146c2c66affSColin Finck         }
147c2c66affSColin Finck     }
148c2c66affSColin Finck 
149c2c66affSColin Finck     /* Call the Ex version of the API */
150c2c66affSColin Finck     return LoadLibraryExA(lpLibFileName, 0, 0);
151c2c66affSColin Finck }
152c2c66affSColin Finck 
153c2c66affSColin Finck /*
154c2c66affSColin Finck  * @implemented
155c2c66affSColin Finck  */
156c2c66affSColin Finck HINSTANCE
157c2c66affSColin Finck WINAPI
158c2c66affSColin Finck DECLSPEC_HOTPATCH
LoadLibraryExA(LPCSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)159c2c66affSColin Finck LoadLibraryExA(LPCSTR lpLibFileName,
160c2c66affSColin Finck                HANDLE hFile,
161c2c66affSColin Finck                DWORD dwFlags)
162c2c66affSColin Finck {
163c2c66affSColin Finck     PUNICODE_STRING FileNameW;
164c2c66affSColin Finck 
165c2c66affSColin Finck     /* Convert file name to unicode */
166c2c66affSColin Finck     if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName)))
167c2c66affSColin Finck         return NULL;
168c2c66affSColin Finck 
169c2c66affSColin Finck     /* And call W version of the API */
170c2c66affSColin Finck     return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags);
171c2c66affSColin Finck }
172c2c66affSColin Finck 
173c2c66affSColin Finck /*
174c2c66affSColin Finck  * @implemented
175c2c66affSColin Finck  */
176c2c66affSColin Finck HINSTANCE
177c2c66affSColin Finck WINAPI
178c2c66affSColin Finck DECLSPEC_HOTPATCH
LoadLibraryW(LPCWSTR lpLibFileName)179c2c66affSColin Finck LoadLibraryW(LPCWSTR lpLibFileName)
180c2c66affSColin Finck {
181c2c66affSColin Finck     /* Call Ex version of the API */
182c2c66affSColin Finck     return LoadLibraryExW(lpLibFileName, 0, 0);
183c2c66affSColin Finck }
184c2c66affSColin Finck 
185c2c66affSColin Finck 
186c2c66affSColin Finck static
187c2c66affSColin Finck NTSTATUS
BasepLoadLibraryAsDatafile(PWSTR Path,LPCWSTR Name,HMODULE * hModule)188c2c66affSColin Finck BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule)
189c2c66affSColin Finck {
190c2c66affSColin Finck     WCHAR FilenameW[MAX_PATH];
191c2c66affSColin Finck     HANDLE hFile = INVALID_HANDLE_VALUE;
192c2c66affSColin Finck     HANDLE hMapping;
193c2c66affSColin Finck     NTSTATUS Status;
194c2c66affSColin Finck     PVOID lpBaseAddress = NULL;
195c2c66affSColin Finck     SIZE_T ViewSize = 0;
196c2c66affSColin Finck     //PUNICODE_STRING OriginalName;
197c2c66affSColin Finck     //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL");
198c2c66affSColin Finck 
199c2c66affSColin Finck     /* Zero out handle value */
200c2c66affSColin Finck     *hModule = 0;
201c2c66affSColin Finck 
202c2c66affSColin Finck     DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule);
203c2c66affSColin Finck 
204c2c66affSColin Finck     /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
205c2c66affSColin Finck                                                       Name,
206c2c66affSColin Finck                                                       &dotDLL,
207c2c66affSColin Finck                                                       RedirName,
208c2c66affSColin Finck                                                       RedirName2,
209c2c66affSColin Finck                                                       &OriginalName2,
210c2c66affSColin Finck                                                       NULL,
211c2c66affSColin Finck                                                       NULL,
212c2c66affSColin Finck                                                       NULL);*/
213c2c66affSColin Finck 
214c2c66affSColin Finck     /* Try to search for it */
215c2c66affSColin Finck     if (!SearchPathW(Path,
216c2c66affSColin Finck                      Name,
217c2c66affSColin Finck                      L".DLL",
218c2c66affSColin Finck                      sizeof(FilenameW) / sizeof(FilenameW[0]),
219c2c66affSColin Finck                      FilenameW,
220c2c66affSColin Finck                      NULL))
221c2c66affSColin Finck     {
222c2c66affSColin Finck         /* Return last status value directly */
223c2c66affSColin Finck         return NtCurrentTeb()->LastStatusValue;
224c2c66affSColin Finck     }
225c2c66affSColin Finck 
226c2c66affSColin Finck     /* Open this file we found */
227c2c66affSColin Finck     hFile = CreateFileW(FilenameW,
228c2c66affSColin Finck                         GENERIC_READ,
229c2c66affSColin Finck                         FILE_SHARE_READ | FILE_SHARE_DELETE,
230c2c66affSColin Finck                         NULL,
231c2c66affSColin Finck                         OPEN_EXISTING,
232c2c66affSColin Finck                         0,
233c2c66affSColin Finck                         0);
234c2c66affSColin Finck 
235c2c66affSColin Finck     /* If opening failed - return last status value */
236c2c66affSColin Finck     if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue;
237c2c66affSColin Finck 
238c2c66affSColin Finck     /* Create file mapping */
239c2c66affSColin Finck     hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
240c2c66affSColin Finck 
241c2c66affSColin Finck     /* Close the file handle */
242c2c66affSColin Finck     CloseHandle(hFile);
243c2c66affSColin Finck 
244c2c66affSColin Finck     /* If creating file mapping failed - return last status value */
245c2c66affSColin Finck     if (!hMapping) return NtCurrentTeb()->LastStatusValue;
246c2c66affSColin Finck 
247c2c66affSColin Finck     /* Map view of section */
248c2c66affSColin Finck     Status = NtMapViewOfSection(hMapping,
249c2c66affSColin Finck                                 NtCurrentProcess(),
250c2c66affSColin Finck                                 &lpBaseAddress,
251c2c66affSColin Finck                                 0,
252c2c66affSColin Finck                                 0,
253c2c66affSColin Finck                                 0,
254c2c66affSColin Finck                                 &ViewSize,
255c2c66affSColin Finck                                 ViewShare,
256c2c66affSColin Finck                                 0,
257c2c66affSColin Finck                                 PAGE_READONLY);
258c2c66affSColin Finck 
259c2c66affSColin Finck     /* Close handle to the section */
260c2c66affSColin Finck     CloseHandle(hMapping);
261c2c66affSColin Finck 
262c2c66affSColin Finck     /* If mapping view of section failed - return last status value */
263c2c66affSColin Finck     if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue;
264c2c66affSColin Finck 
265c2c66affSColin Finck     /* Make sure it's a valid PE file */
266c2c66affSColin Finck     if (!RtlImageNtHeader(lpBaseAddress))
267c2c66affSColin Finck     {
268c2c66affSColin Finck         /* Unmap the view and return failure status */
269c2c66affSColin Finck         UnmapViewOfFile(lpBaseAddress);
270c2c66affSColin Finck         return STATUS_INVALID_IMAGE_FORMAT;
271c2c66affSColin Finck     }
272c2c66affSColin Finck 
273c2c66affSColin Finck     /* Set low bit of handle to indicate datafile module */
274c2c66affSColin Finck     *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1);
275c2c66affSColin Finck 
276c2c66affSColin Finck     /* Load alternate resource module */
277c2c66affSColin Finck     //LdrLoadAlternateResourceModule(*hModule, FilenameW);
278c2c66affSColin Finck 
279c2c66affSColin Finck     return STATUS_SUCCESS;
280c2c66affSColin Finck }
281c2c66affSColin Finck 
282c2c66affSColin Finck /*
283c2c66affSColin Finck  * @implemented
284c2c66affSColin Finck  */
285c2c66affSColin Finck HINSTANCE
286c2c66affSColin Finck WINAPI
287c2c66affSColin Finck DECLSPEC_HOTPATCH
LoadLibraryExW(LPCWSTR lpLibFileName,HANDLE hFile,DWORD dwFlags)288c2c66affSColin Finck LoadLibraryExW(LPCWSTR lpLibFileName,
289c2c66affSColin Finck                HANDLE hFile,
290c2c66affSColin Finck                DWORD dwFlags)
291c2c66affSColin Finck {
292c2c66affSColin Finck     UNICODE_STRING DllName;
293c2c66affSColin Finck     HINSTANCE hInst;
294c2c66affSColin Finck     NTSTATUS Status;
295c2c66affSColin Finck     PWSTR SearchPath;
296c2c66affSColin Finck     ULONG DllCharacteristics = 0;
297c2c66affSColin Finck     BOOL FreeString = FALSE;
298c2c66affSColin Finck 
299c2c66affSColin Finck     /* Check for any flags LdrLoadDll might be interested in */
300c2c66affSColin Finck     if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
301c2c66affSColin Finck     {
302c2c66affSColin Finck         /* Tell LDR to treat it as an EXE */
303c2c66affSColin Finck         DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
304c2c66affSColin Finck     }
305c2c66affSColin Finck 
306c2c66affSColin Finck     /* Build up a unicode dll name from null-terminated string */
307c2c66affSColin Finck     RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
308c2c66affSColin Finck 
309c2c66affSColin Finck     /* Lazy-initialize BasepExeLdrEntry */
310c2c66affSColin Finck     if (!BasepExeLdrEntry)
311c2c66affSColin Finck         LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress);
312c2c66affSColin Finck 
313c2c66affSColin Finck     /* Check if that module is our exe*/
314c2c66affSColin Finck     if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) &&
315c2c66affSColin Finck         DllName.Length == BasepExeLdrEntry->FullDllName.Length)
316c2c66affSColin Finck     {
317c2c66affSColin Finck         /* Lengths match and it's not a datafile, so perform name comparison */
318c2c66affSColin Finck         if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE))
319c2c66affSColin Finck         {
320c2c66affSColin Finck             /* That's us! */
321c2c66affSColin Finck             return BasepExeLdrEntry->DllBase;
322c2c66affSColin Finck         }
323c2c66affSColin Finck     }
324c2c66affSColin Finck 
325c2c66affSColin Finck     /* Check for trailing spaces and remove them if necessary */
326c2c66affSColin Finck     if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
327c2c66affSColin Finck     {
328c2c66affSColin Finck         RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName);
329c2c66affSColin Finck         while (DllName.Length > sizeof(WCHAR) &&
330c2c66affSColin Finck             DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
331c2c66affSColin Finck         {
332c2c66affSColin Finck             DllName.Length -= sizeof(WCHAR);
333c2c66affSColin Finck         }
334c2c66affSColin Finck         DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL;
335c2c66affSColin Finck         FreeString = TRUE;
336c2c66affSColin Finck     }
337c2c66affSColin Finck 
338c2c66affSColin Finck     /* Compute the load path */
339c2c66affSColin Finck     SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ?
340c2c66affSColin Finck                                            DllName.Buffer : NULL,
341c2c66affSColin Finck                                            NULL);
342c2c66affSColin Finck     if (!SearchPath)
343c2c66affSColin Finck     {
344c2c66affSColin Finck         /* Getting DLL path failed, so set last error, free mem and return */
345c2c66affSColin Finck         BaseSetLastNTError(STATUS_NO_MEMORY);
346c2c66affSColin Finck         if (FreeString) RtlFreeUnicodeString(&DllName);
347c2c66affSColin Finck         return NULL;
348c2c66affSColin Finck     }
349c2c66affSColin Finck 
350c2c66affSColin Finck     _SEH2_TRY
351c2c66affSColin Finck     {
352c2c66affSColin Finck         if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
353c2c66affSColin Finck         {
354c2c66affSColin Finck             /* If the image is loaded as a datafile, try to get its handle */
355c2c66affSColin Finck             Status = LdrGetDllHandleEx(0, SearchPath, NULL, &DllName, (PVOID*)&hInst);
356c2c66affSColin Finck             if (!NT_SUCCESS(Status))
357c2c66affSColin Finck             {
358c2c66affSColin Finck                 /* It's not loaded yet - so load it up */
359c2c66affSColin Finck                 Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst);
360c2c66affSColin Finck             }
361c2c66affSColin Finck             _SEH2_YIELD(goto done;)
362c2c66affSColin Finck         }
363c2c66affSColin Finck 
364c2c66affSColin Finck         /* Call the API Properly */
365c2c66affSColin Finck         Status = LdrLoadDll(SearchPath,
366c2c66affSColin Finck                             &DllCharacteristics,
367c2c66affSColin Finck                             &DllName,
368c2c66affSColin Finck                             (PVOID*)&hInst);
369c2c66affSColin Finck     }
370c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
371c2c66affSColin Finck     {
372c2c66affSColin Finck         Status = _SEH2_GetExceptionCode();
373c2c66affSColin Finck     } _SEH2_END;
374c2c66affSColin Finck 
375c2c66affSColin Finck 
376c2c66affSColin Finck done:
377c2c66affSColin Finck     /* Free SearchPath buffer */
378c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath);
379c2c66affSColin Finck 
380c2c66affSColin Finck     /* Free DllName string if it was dynamically allocated */
381c2c66affSColin Finck     if (FreeString) RtlFreeUnicodeString(&DllName);
382c2c66affSColin Finck 
383c2c66affSColin Finck     /* Set last error in failure case */
384c2c66affSColin Finck     if (!NT_SUCCESS(Status))
385c2c66affSColin Finck     {
386c2c66affSColin Finck         DPRINT1("LoadLibraryExW(%ls) failing with status %lx\n", lpLibFileName, Status);
387c2c66affSColin Finck         BaseSetLastNTError(Status);
388c2c66affSColin Finck         return NULL;
389c2c66affSColin Finck     }
390c2c66affSColin Finck 
391c2c66affSColin Finck     /* Return loaded module handle */
392c2c66affSColin Finck     return hInst;
393c2c66affSColin Finck }
394c2c66affSColin Finck 
395c2c66affSColin Finck 
396c2c66affSColin Finck /*
397c2c66affSColin Finck  * @implemented
398c2c66affSColin Finck  */
399c2c66affSColin Finck FARPROC
400c2c66affSColin Finck WINAPI
GetProcAddress(HMODULE hModule,LPCSTR lpProcName)401c2c66affSColin Finck GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
402c2c66affSColin Finck {
403c2c66affSColin Finck     ANSI_STRING ProcedureName, *ProcNamePtr = NULL;
404c2c66affSColin Finck     FARPROC fnExp = NULL;
405c2c66affSColin Finck     NTSTATUS Status;
406c2c66affSColin Finck     PVOID hMapped;
407c2c66affSColin Finck     ULONG Ordinal = 0;
408c2c66affSColin Finck 
4094f0a158aSTimo Kreuzer     if ((ULONG_PTR)lpProcName > MAXUSHORT)
410c2c66affSColin Finck     {
411c2c66affSColin Finck         /* Look up by name */
412c2c66affSColin Finck         RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName);
413c2c66affSColin Finck         ProcNamePtr = &ProcedureName;
414c2c66affSColin Finck     }
415c2c66affSColin Finck     else
416c2c66affSColin Finck     {
417c2c66affSColin Finck         /* Look up by ordinal */
4184f0a158aSTimo Kreuzer         Ordinal = PtrToUlong(lpProcName);
419c2c66affSColin Finck     }
420c2c66affSColin Finck 
421c2c66affSColin Finck     /* Map provided handle */
422c2c66affSColin Finck     hMapped = BasepMapModuleHandle(hModule, FALSE);
423c2c66affSColin Finck 
424c2c66affSColin Finck     /* Get the proc address */
425c2c66affSColin Finck     Status = LdrGetProcedureAddress(hMapped,
426c2c66affSColin Finck                                     ProcNamePtr,
427c2c66affSColin Finck                                     Ordinal,
428c2c66affSColin Finck                                     (PVOID*)&fnExp);
429c2c66affSColin Finck 
430c2c66affSColin Finck     if (!NT_SUCCESS(Status))
431c2c66affSColin Finck     {
432c2c66affSColin Finck         BaseSetLastNTError(Status);
433c2c66affSColin Finck         return NULL;
434c2c66affSColin Finck     }
435c2c66affSColin Finck 
436c2c66affSColin Finck     /* Check for a special case when returned pointer is
437c2c66affSColin Finck        the same as image's base address */
438c2c66affSColin Finck     if (fnExp == hMapped)
439c2c66affSColin Finck     {
440c2c66affSColin Finck         /* Set correct error code */
441c2c66affSColin Finck         if (HIWORD(lpProcName) != 0)
442c2c66affSColin Finck             BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND);
443c2c66affSColin Finck         else
444c2c66affSColin Finck             BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND);
445c2c66affSColin Finck 
446c2c66affSColin Finck         return NULL;
447c2c66affSColin Finck     }
448c2c66affSColin Finck 
449c2c66affSColin Finck     /* All good, return procedure pointer */
450c2c66affSColin Finck     return fnExp;
451c2c66affSColin Finck }
452c2c66affSColin Finck 
453c2c66affSColin Finck 
454c2c66affSColin Finck /*
455c2c66affSColin Finck  * @implemented
456c2c66affSColin Finck  */
457c2c66affSColin Finck BOOL
458c2c66affSColin Finck WINAPI
459c2c66affSColin Finck DECLSPEC_HOTPATCH
FreeLibrary(HINSTANCE hLibModule)460c2c66affSColin Finck FreeLibrary(HINSTANCE hLibModule)
461c2c66affSColin Finck {
462c2c66affSColin Finck     NTSTATUS Status;
463c2c66affSColin Finck     PIMAGE_NT_HEADERS NtHeaders;
464c2c66affSColin Finck 
465c2c66affSColin Finck     if (LDR_IS_DATAFILE(hLibModule))
466c2c66affSColin Finck     {
467c2c66affSColin Finck         /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */
468c2c66affSColin Finck         NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1));
469c2c66affSColin Finck 
470c2c66affSColin Finck         if (NtHeaders)
471c2c66affSColin Finck         {
472c2c66affSColin Finck             /* Unmap view */
473c2c66affSColin Finck             Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
474c2c66affSColin Finck 
475c2c66affSColin Finck             /* Unload alternate resource module */
476c2c66affSColin Finck             LdrUnloadAlternateResourceModule(hLibModule);
477c2c66affSColin Finck         }
478c2c66affSColin Finck         else
479c2c66affSColin Finck             Status = STATUS_INVALID_IMAGE_FORMAT;
480c2c66affSColin Finck     }
481c2c66affSColin Finck     else
482c2c66affSColin Finck     {
483c2c66affSColin Finck         /* Just unload it */
484c2c66affSColin Finck         Status = LdrUnloadDll((PVOID)hLibModule);
485c2c66affSColin Finck     }
486c2c66affSColin Finck 
487c2c66affSColin Finck     /* Check what kind of status we got */
488c2c66affSColin Finck     if (!NT_SUCCESS(Status))
489c2c66affSColin Finck     {
490c2c66affSColin Finck         /* Set last error */
491c2c66affSColin Finck         BaseSetLastNTError(Status);
492c2c66affSColin Finck 
493c2c66affSColin Finck         /* Return failure */
494c2c66affSColin Finck         return FALSE;
495c2c66affSColin Finck     }
496c2c66affSColin Finck 
497c2c66affSColin Finck     /* Return success */
498c2c66affSColin Finck     return TRUE;
499c2c66affSColin Finck }
500c2c66affSColin Finck 
501c2c66affSColin Finck 
502c2c66affSColin Finck /*
503c2c66affSColin Finck  * @implemented
504c2c66affSColin Finck  */
505c2c66affSColin Finck VOID
506c2c66affSColin Finck WINAPI
FreeLibraryAndExitThread(HMODULE hLibModule,DWORD dwExitCode)507c2c66affSColin Finck FreeLibraryAndExitThread(HMODULE hLibModule,
508c2c66affSColin Finck                          DWORD dwExitCode)
509c2c66affSColin Finck {
510c2c66affSColin Finck 
511c2c66affSColin Finck     if (LDR_IS_DATAFILE(hLibModule))
512c2c66affSColin Finck     {
513c2c66affSColin Finck         /* This is a LOAD_LIBRARY_AS_DATAFILE module */
514c2c66affSColin Finck         if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)))
515c2c66affSColin Finck         {
516c2c66affSColin Finck             /* Unmap view */
517c2c66affSColin Finck             NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
518c2c66affSColin Finck 
519c2c66affSColin Finck             /* Unload alternate resource module */
520c2c66affSColin Finck             LdrUnloadAlternateResourceModule(hLibModule);
521c2c66affSColin Finck         }
522c2c66affSColin Finck     }
523c2c66affSColin Finck     else
524c2c66affSColin Finck     {
525c2c66affSColin Finck         /* Just unload it */
526c2c66affSColin Finck         LdrUnloadDll((PVOID)hLibModule);
527c2c66affSColin Finck     }
528c2c66affSColin Finck 
529c2c66affSColin Finck     /* Exit thread */
530c2c66affSColin Finck     ExitThread(dwExitCode);
531c2c66affSColin Finck }
532c2c66affSColin Finck 
533c2c66affSColin Finck 
534c2c66affSColin Finck /*
535c2c66affSColin Finck  * @implemented
536c2c66affSColin Finck  */
537c2c66affSColin Finck DWORD
538c2c66affSColin Finck WINAPI
GetModuleFileNameA(HINSTANCE hModule,LPSTR lpFilename,DWORD nSize)539c2c66affSColin Finck GetModuleFileNameA(HINSTANCE hModule,
540c2c66affSColin Finck                    LPSTR lpFilename,
541c2c66affSColin Finck                    DWORD nSize)
542c2c66affSColin Finck {
543c2c66affSColin Finck     UNICODE_STRING FilenameW;
544c2c66affSColin Finck     ANSI_STRING FilenameA;
545c2c66affSColin Finck     NTSTATUS Status;
546c2c66affSColin Finck     DWORD Length = 0, LengthToCopy;
547c2c66affSColin Finck 
548c2c66affSColin Finck     /* Allocate a unicode buffer */
549c2c66affSColin Finck     FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR));
550c2c66affSColin Finck     if (!FilenameW.Buffer)
551c2c66affSColin Finck     {
552c2c66affSColin Finck         BaseSetLastNTError(STATUS_NO_MEMORY);
553c2c66affSColin Finck         return 0;
554c2c66affSColin Finck     }
555c2c66affSColin Finck 
556c2c66affSColin Finck     /* Call unicode API */
557c2c66affSColin Finck     FilenameW.Length = (USHORT)GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR);
558c2c66affSColin Finck     FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR);
559c2c66affSColin Finck 
560c2c66affSColin Finck     if (FilenameW.Length)
561c2c66affSColin Finck     {
562c2c66affSColin Finck         /* Convert to ansi string */
563c2c66affSColin Finck         Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE);
564c2c66affSColin Finck         if (!NT_SUCCESS(Status))
565c2c66affSColin Finck         {
566c2c66affSColin Finck             /* Set last error, free string and return failure */
567c2c66affSColin Finck             BaseSetLastNTError(Status);
568c2c66affSColin Finck             RtlFreeUnicodeString(&FilenameW);
569c2c66affSColin Finck             return 0;
570c2c66affSColin Finck         }
571c2c66affSColin Finck 
572c2c66affSColin Finck         /* Calculate size to copy */
573c2c66affSColin Finck         Length = min(nSize, FilenameA.Length);
574c2c66affSColin Finck 
575c2c66affSColin Finck         /* Include terminating zero */
576c2c66affSColin Finck         if (nSize > Length)
577c2c66affSColin Finck             LengthToCopy = Length + 1;
578c2c66affSColin Finck         else
579c2c66affSColin Finck             LengthToCopy = nSize;
580c2c66affSColin Finck 
581c2c66affSColin Finck         /* Now copy back to the caller amount he asked */
582c2c66affSColin Finck         RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy);
583c2c66affSColin Finck 
584c2c66affSColin Finck         /* Free ansi filename */
585c2c66affSColin Finck         RtlFreeAnsiString(&FilenameA);
586c2c66affSColin Finck     }
587c2c66affSColin Finck 
588c2c66affSColin Finck     /* Free unicode filename */
589c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer);
590c2c66affSColin Finck 
591c2c66affSColin Finck     /* Return length copied */
592c2c66affSColin Finck     return Length;
593c2c66affSColin Finck }
594c2c66affSColin Finck 
595c2c66affSColin Finck /*
596c2c66affSColin Finck  * @implemented
597c2c66affSColin Finck  */
598c2c66affSColin Finck DWORD
599c2c66affSColin Finck WINAPI
GetModuleFileNameW(HINSTANCE hModule,LPWSTR lpFilename,DWORD nSize)600c2c66affSColin Finck GetModuleFileNameW(HINSTANCE hModule,
601c2c66affSColin Finck                    LPWSTR lpFilename,
602c2c66affSColin Finck                    DWORD nSize)
603c2c66affSColin Finck {
604c2c66affSColin Finck     PLIST_ENTRY ModuleListHead, Entry;
605c2c66affSColin Finck     PLDR_DATA_TABLE_ENTRY Module;
606c2c66affSColin Finck     ULONG Length = 0;
607d6792047SIvan Labutin     ULONG_PTR Cookie;
608c2c66affSColin Finck     PPEB Peb;
609c2c66affSColin Finck 
610c2c66affSColin Finck     hModule = BasepMapModuleHandle(hModule, FALSE);
611c2c66affSColin Finck 
612c2c66affSColin Finck     /* Upscale nSize from chars to bytes */
613c2c66affSColin Finck     nSize *= sizeof(WCHAR);
614c2c66affSColin Finck 
615c2c66affSColin Finck     _SEH2_TRY
616c2c66affSColin Finck     {
617c2c66affSColin Finck         /* We don't use per-thread cur dir now */
618c2c66affSColin Finck         //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
619c2c66affSColin Finck 
620c2c66affSColin Finck         Peb = NtCurrentPeb ();
621c2c66affSColin Finck 
622c2c66affSColin Finck         /* Acquire a loader lock */
623c2c66affSColin Finck         LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);
624c2c66affSColin Finck 
625c2c66affSColin Finck         /* Traverse the module list */
626c2c66affSColin Finck         ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
627c2c66affSColin Finck         Entry = ModuleListHead->Flink;
628c2c66affSColin Finck         while (Entry != ModuleListHead)
629c2c66affSColin Finck         {
630c2c66affSColin Finck             Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
631c2c66affSColin Finck 
632c2c66affSColin Finck             /* Check if this is the requested module */
633c2c66affSColin Finck             if (Module->DllBase == (PVOID)hModule)
634c2c66affSColin Finck             {
635c2c66affSColin Finck                 /* Calculate size to copy */
636c2c66affSColin Finck                 Length = min(nSize, Module->FullDllName.MaximumLength);
637c2c66affSColin Finck 
638c2c66affSColin Finck                 /* Copy contents */
639c2c66affSColin Finck                 RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length);
640c2c66affSColin Finck 
641c2c66affSColin Finck                 /* Subtract a terminating zero */
642c2c66affSColin Finck                 if (Length == Module->FullDllName.MaximumLength)
643c2c66affSColin Finck                     Length -= sizeof(WCHAR);
644c2c66affSColin Finck 
645c2c66affSColin Finck                 /* Break out of the loop */
646c2c66affSColin Finck                 break;
647c2c66affSColin Finck             }
648c2c66affSColin Finck 
649c2c66affSColin Finck             /* Advance to the next entry */
650c2c66affSColin Finck             Entry = Entry->Flink;
651c2c66affSColin Finck         }
652c2c66affSColin Finck     }
653c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
654c2c66affSColin Finck     {
655c2c66affSColin Finck         BaseSetLastNTError(_SEH2_GetExceptionCode());
656c2c66affSColin Finck         Length = 0;
657c2c66affSColin Finck     } _SEH2_END
658c2c66affSColin Finck 
659c2c66affSColin Finck     /* Release the loader lock */
660*bd0a5498SRatin Gao     LdrUnlockLoaderLock(LDR_UNLOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
661c2c66affSColin Finck 
662c2c66affSColin Finck     return Length / sizeof(WCHAR);
663c2c66affSColin Finck }
664c2c66affSColin Finck 
665c2c66affSColin Finck HMODULE
666c2c66affSColin Finck WINAPI
GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName)667c2c66affSColin Finck GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName)
668c2c66affSColin Finck {
669c2c66affSColin Finck     NTSTATUS Status;
670c2c66affSColin Finck     PVOID Module;
671c2c66affSColin Finck     LPWSTR DllPath;
672c2c66affSColin Finck 
673c2c66affSColin Finck     /* Try to get a handle with a magic value of 1 for DllPath */
674c2c66affSColin Finck     Status = LdrGetDllHandle((LPWSTR)1, NULL, ModuleName, &Module);
675c2c66affSColin Finck 
676c2c66affSColin Finck     /* If that succeeded - we're done */
677c2c66affSColin Finck     if (NT_SUCCESS(Status)) return Module;
678c2c66affSColin Finck 
679c2c66affSColin Finck     /* If not, then the path should be computed */
680d6d30f9eSHermès Bélusca-Maïto     DllPath = BaseComputeProcessDllPath(NULL, NULL);
681c2c66affSColin Finck     if (!DllPath)
682c2c66affSColin Finck     {
683c2c66affSColin Finck         Status = STATUS_NO_MEMORY;
684c2c66affSColin Finck     }
685c2c66affSColin Finck     else
686c2c66affSColin Finck     {
687c2c66affSColin Finck         _SEH2_TRY
688c2c66affSColin Finck         {
689c2c66affSColin Finck             Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module);
690c2c66affSColin Finck         }
691c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
692c2c66affSColin Finck         {
693c2c66affSColin Finck             /* Fail with the SEH error */
694c2c66affSColin Finck             Status = _SEH2_GetExceptionCode();
695c2c66affSColin Finck         }
696c2c66affSColin Finck         _SEH2_END;
697c2c66affSColin Finck     }
698c2c66affSColin Finck 
699c2c66affSColin Finck     /* Free the DllPath */
700c2c66affSColin Finck     RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
701c2c66affSColin Finck 
702c2c66affSColin Finck     /* In case of error set last win32 error and return NULL */
703c2c66affSColin Finck     if (!NT_SUCCESS(Status))
704c2c66affSColin Finck     {
705c2c66affSColin Finck         DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName, Status);
706c2c66affSColin Finck         BaseSetLastNTError(Status);
707c2c66affSColin Finck         Module = 0;
708c2c66affSColin Finck     }
709c2c66affSColin Finck 
710c2c66affSColin Finck     /* Return module */
711c2c66affSColin Finck     return (HMODULE)Module;
712c2c66affSColin Finck }
713c2c66affSColin Finck 
714c2c66affSColin Finck BOOLEAN
715c2c66affSColin Finck WINAPI
BasepGetModuleHandleExW(BOOLEAN NoLock,DWORD dwPublicFlags,LPCWSTR lpwModuleName,HMODULE * phModule)716c2c66affSColin Finck BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleName, HMODULE *phModule)
717c2c66affSColin Finck {
718d6792047SIvan Labutin     ULONG_PTR Cookie;
719c2c66affSColin Finck     NTSTATUS Status = STATUS_SUCCESS, Status2;
720c2c66affSColin Finck     HANDLE hModule = NULL;
721c2c66affSColin Finck     UNICODE_STRING ModuleNameU;
722c2c66affSColin Finck     DWORD dwValid;
723c2c66affSColin Finck     BOOLEAN Redirected = FALSE; // FIXME
724c2c66affSColin Finck 
725c2c66affSColin Finck     /* Validate parameters */
726c2c66affSColin Finck     dwValid = BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule);
727c2c66affSColin Finck     ASSERT(dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE);
728c2c66affSColin Finck 
729c2c66affSColin Finck     /* Acquire lock if necessary */
730c2c66affSColin Finck     if (!NoLock)
731c2c66affSColin Finck     {
732c2c66affSColin Finck         Status = LdrLockLoaderLock(0, NULL, &Cookie);
733c2c66affSColin Finck         if (!NT_SUCCESS(Status))
734c2c66affSColin Finck         {
735c2c66affSColin Finck             /* Fail */
736c2c66affSColin Finck             BaseSetLastNTError(Status);
737c2c66affSColin Finck             if (phModule) *phModule = NULL;
738c2c66affSColin Finck             return NT_SUCCESS(Status);
739c2c66affSColin Finck         }
740c2c66affSColin Finck     }
741c2c66affSColin Finck 
742c2c66affSColin Finck     if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
743c2c66affSColin Finck     {
744c2c66affSColin Finck         /* Create a unicode string out of module name */
745c2c66affSColin Finck         RtlInitUnicodeString(&ModuleNameU, lpwModuleName);
746c2c66affSColin Finck 
747c2c66affSColin Finck         // FIXME: Do some redirected DLL stuff?
748c2c66affSColin Finck         if (Redirected)
749c2c66affSColin Finck         {
750c2c66affSColin Finck             UNIMPLEMENTED;
751c2c66affSColin Finck         }
752c2c66affSColin Finck 
753c2c66affSColin Finck         if (!hModule)
754c2c66affSColin Finck         {
755c2c66affSColin Finck             hModule = GetModuleHandleForUnicodeString(&ModuleNameU);
756c2c66affSColin Finck             if (!hModule)
757c2c66affSColin Finck             {
758c2c66affSColin Finck                 /* Last error is already set, so just return failure by setting status */
759c2c66affSColin Finck                 Status = STATUS_DLL_NOT_FOUND;
760c2c66affSColin Finck                 goto quickie;
761c2c66affSColin Finck             }
762c2c66affSColin Finck         }
763c2c66affSColin Finck     }
764c2c66affSColin Finck     else
765c2c66affSColin Finck     {
766c2c66affSColin Finck         /* Perform Pc to file header to get module instance */
767c2c66affSColin Finck         hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpwModuleName,
768c2c66affSColin Finck                                              (PVOID*)&hModule);
769c2c66affSColin Finck 
770c2c66affSColin Finck         /* Check if it succeeded */
771c2c66affSColin Finck         if (!hModule)
772c2c66affSColin Finck         {
773c2c66affSColin Finck             /* Set "dll not found" status and quit */
774c2c66affSColin Finck             Status = STATUS_DLL_NOT_FOUND;
775c2c66affSColin Finck             goto quickie;
776c2c66affSColin Finck         }
777c2c66affSColin Finck     }
778c2c66affSColin Finck 
779c2c66affSColin Finck     /* Check if changing reference is not forbidden */
780c2c66affSColin Finck     if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))
781c2c66affSColin Finck     {
782c2c66affSColin Finck         /* Add reference to this DLL */
783c2c66affSColin Finck         Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0,
784c2c66affSColin Finck                               hModule);
785c2c66affSColin Finck     }
786c2c66affSColin Finck 
787c2c66affSColin Finck quickie:
788c2c66affSColin Finck     /* Set last error in case of failure */
789c2c66affSColin Finck     if (!NT_SUCCESS(Status))
790c2c66affSColin Finck         BaseSetLastNTError(Status);
791c2c66affSColin Finck 
792c2c66affSColin Finck     /* Unlock loader lock if it was acquired */
793c2c66affSColin Finck     if (!NoLock)
794c2c66affSColin Finck     {
795c2c66affSColin Finck         Status2 = LdrUnlockLoaderLock(0, Cookie);
796c2c66affSColin Finck         ASSERT(NT_SUCCESS(Status2));
797c2c66affSColin Finck     }
798c2c66affSColin Finck 
799c2c66affSColin Finck     /* Set the module handle to the caller */
800c2c66affSColin Finck     if (phModule) *phModule = hModule;
801c2c66affSColin Finck 
802c2c66affSColin Finck     /* Return TRUE on success and FALSE otherwise */
803c2c66affSColin Finck     return NT_SUCCESS(Status);
804c2c66affSColin Finck }
805c2c66affSColin Finck 
806c2c66affSColin Finck /*
807c2c66affSColin Finck  * @implemented
808c2c66affSColin Finck  */
809c2c66affSColin Finck HMODULE
810c2c66affSColin Finck WINAPI
811c2c66affSColin Finck DECLSPEC_HOTPATCH
GetModuleHandleA(LPCSTR lpModuleName)812c2c66affSColin Finck GetModuleHandleA(LPCSTR lpModuleName)
813c2c66affSColin Finck {
814c2c66affSColin Finck     PUNICODE_STRING ModuleNameW;
815c2c66affSColin Finck     PTEB pTeb = NtCurrentTeb();
816c2c66affSColin Finck 
817c2c66affSColin Finck     /* Check if we have no name to convert */
818c2c66affSColin Finck     if (!lpModuleName)
819c2c66affSColin Finck         return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress);
820c2c66affSColin Finck 
821c2c66affSColin Finck     /* Convert module name to unicode */
822c2c66affSColin Finck     ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
823c2c66affSColin Finck 
824c2c66affSColin Finck     /* Call W version if conversion was successful */
825c2c66affSColin Finck     if (ModuleNameW)
826c2c66affSColin Finck         return GetModuleHandleW(ModuleNameW->Buffer);
827c2c66affSColin Finck 
828c2c66affSColin Finck     /* Return failure */
829c2c66affSColin Finck     return 0;
830c2c66affSColin Finck }
831c2c66affSColin Finck 
832c2c66affSColin Finck 
833c2c66affSColin Finck /*
834c2c66affSColin Finck  * @implemented
835c2c66affSColin Finck  */
836c2c66affSColin Finck HMODULE
837c2c66affSColin Finck WINAPI
GetModuleHandleW(LPCWSTR lpModuleName)838c2c66affSColin Finck GetModuleHandleW(LPCWSTR lpModuleName)
839c2c66affSColin Finck {
840c2c66affSColin Finck     HMODULE hModule;
841c2c66affSColin Finck     BOOLEAN Success;
842c2c66affSColin Finck 
843c2c66affSColin Finck     /* If current module is requested - return it right away */
844c2c66affSColin Finck     if (!lpModuleName)
845c2c66affSColin Finck         return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
846c2c66affSColin Finck 
847c2c66affSColin Finck     /* Use common helper routine */
848c2c66affSColin Finck     Success = BasepGetModuleHandleExW(TRUE,
849c2c66affSColin Finck                                       GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
850c2c66affSColin Finck                                       lpModuleName,
851c2c66affSColin Finck                                       &hModule);
852c2c66affSColin Finck 
853c2c66affSColin Finck     /* If it wasn't successful - return NULL */
854c2c66affSColin Finck     if (!Success) hModule = NULL;
855c2c66affSColin Finck 
856c2c66affSColin Finck     /* Return the handle */
857c2c66affSColin Finck     return hModule;
858c2c66affSColin Finck }
859c2c66affSColin Finck 
860c2c66affSColin Finck 
861c2c66affSColin Finck /*
862c2c66affSColin Finck  * @implemented
863c2c66affSColin Finck  */
864c2c66affSColin Finck BOOL
865c2c66affSColin Finck WINAPI
GetModuleHandleExW(IN DWORD dwFlags,IN LPCWSTR lpwModuleName OPTIONAL,OUT HMODULE * phModule)866c2c66affSColin Finck GetModuleHandleExW(IN DWORD dwFlags,
867c2c66affSColin Finck                    IN LPCWSTR lpwModuleName  OPTIONAL,
868c2c66affSColin Finck                    OUT HMODULE* phModule)
869c2c66affSColin Finck {
870c2c66affSColin Finck     DWORD dwValid;
871c2c66affSColin Finck     BOOL Ret;
872c2c66affSColin Finck 
873c2c66affSColin Finck     /* Validate parameters */
874c2c66affSColin Finck     dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule);
875c2c66affSColin Finck 
876c2c66affSColin Finck     /* If result is invalid parameter - return failure */
877c2c66affSColin Finck     if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
878c2c66affSColin Finck 
879c2c66affSColin Finck     /* If result is 2, there is no need to do anything - return success. */
880c2c66affSColin Finck     if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE;
881c2c66affSColin Finck 
882c2c66affSColin Finck     /* Use common helper routine */
883c2c66affSColin Finck     Ret = BasepGetModuleHandleExW(FALSE,
884c2c66affSColin Finck                                   dwFlags,
885c2c66affSColin Finck                                   lpwModuleName,
886c2c66affSColin Finck                                   phModule);
887c2c66affSColin Finck 
888c2c66affSColin Finck     return Ret;
889c2c66affSColin Finck }
890c2c66affSColin Finck 
891c2c66affSColin Finck /*
892c2c66affSColin Finck  * @implemented
893c2c66affSColin Finck  */
894c2c66affSColin Finck BOOL
895c2c66affSColin Finck WINAPI
GetModuleHandleExA(IN DWORD dwFlags,IN LPCSTR lpModuleName OPTIONAL,OUT HMODULE * phModule)896c2c66affSColin Finck GetModuleHandleExA(IN DWORD dwFlags,
897c2c66affSColin Finck                    IN LPCSTR lpModuleName OPTIONAL,
898c2c66affSColin Finck                    OUT HMODULE* phModule)
899c2c66affSColin Finck {
900c2c66affSColin Finck     PUNICODE_STRING lpModuleNameW;
901c2c66affSColin Finck     DWORD dwValid;
902c2c66affSColin Finck     BOOL Ret;
903c2c66affSColin Finck 
904c2c66affSColin Finck     /* Validate parameters */
905c2c66affSColin Finck     dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule);
906c2c66affSColin Finck 
907c2c66affSColin Finck     /* If result is invalid parameter - return failure */
908c2c66affSColin Finck     if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
909c2c66affSColin Finck 
910c2c66affSColin Finck     /* If result is 2, there is no need to do anything - return success. */
911c2c66affSColin Finck     if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE;
912c2c66affSColin Finck 
913c2c66affSColin Finck     /* Check if we don't need to convert the name */
914c2c66affSColin Finck     if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
915c2c66affSColin Finck     {
916c2c66affSColin Finck         /* Call the extended version of the API without conversion */
917c2c66affSColin Finck         Ret = BasepGetModuleHandleExW(FALSE,
918c2c66affSColin Finck                                       dwFlags,
919c2c66affSColin Finck                                       (LPCWSTR)lpModuleName,
920c2c66affSColin Finck                                       phModule);
921c2c66affSColin Finck     }
922c2c66affSColin Finck     else
923c2c66affSColin Finck     {
924c2c66affSColin Finck         /* Convert module name to unicode */
925c2c66affSColin Finck         lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
926c2c66affSColin Finck 
927c2c66affSColin Finck         /* Return FALSE if conversion failed */
928c2c66affSColin Finck         if (!lpModuleNameW) return FALSE;
929c2c66affSColin Finck 
930c2c66affSColin Finck         /* Call the extended version of the API */
931c2c66affSColin Finck         Ret = BasepGetModuleHandleExW(FALSE,
932c2c66affSColin Finck                                       dwFlags,
933c2c66affSColin Finck                                       lpModuleNameW->Buffer,
934c2c66affSColin Finck                                       phModule);
935c2c66affSColin Finck     }
936c2c66affSColin Finck 
937c2c66affSColin Finck     /* Return result */
938c2c66affSColin Finck     return Ret;
939c2c66affSColin Finck }
940c2c66affSColin Finck 
941c2c66affSColin Finck 
942c2c66affSColin Finck /*
943c2c66affSColin Finck  * @implemented
944c2c66affSColin Finck  */
945c2c66affSColin Finck DWORD
946c2c66affSColin Finck WINAPI
LoadModule(LPCSTR lpModuleName,LPVOID lpParameterBlock)947c2c66affSColin Finck LoadModule(LPCSTR lpModuleName,
948c2c66affSColin Finck            LPVOID lpParameterBlock)
949c2c66affSColin Finck {
950c2c66affSColin Finck     STARTUPINFOA StartupInfo;
951c2c66affSColin Finck     PROCESS_INFORMATION ProcessInformation;
952c2c66affSColin Finck     LOADPARMS32 *LoadParams;
953c2c66affSColin Finck     char FileName[MAX_PATH];
954c2c66affSColin Finck     LPSTR CommandLine;
955c2c66affSColin Finck     DWORD Length, Error;
956c2c66affSColin Finck     BOOL ProcessStatus;
957c2c66affSColin Finck     ANSI_STRING AnsiStr;
958c2c66affSColin Finck     UNICODE_STRING UnicStr;
959c2c66affSColin Finck     RTL_PATH_TYPE PathType;
960c2c66affSColin Finck     HANDLE Handle;
961c2c66affSColin Finck 
962c2c66affSColin Finck     LoadParams = (LOADPARMS32*)lpParameterBlock;
963c2c66affSColin Finck 
964c2c66affSColin Finck     /* Check load parameters */
965c2c66affSColin Finck     if (LoadParams->dwReserved || LoadParams->wMagicValue != 2)
966c2c66affSColin Finck     {
967c2c66affSColin Finck         /* Fail with invalid param error */
968c2c66affSColin Finck         BaseSetLastNTError(STATUS_INVALID_PARAMETER);
969c2c66affSColin Finck         return 0;
970c2c66affSColin Finck     }
971c2c66affSColin Finck 
972c2c66affSColin Finck     /* Search path */
973c2c66affSColin Finck     Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL);
974c2c66affSColin Finck 
975c2c66affSColin Finck     /* Check if path was found */
976c2c66affSColin Finck     if (Length && Length < MAX_PATH)
977c2c66affSColin Finck     {
978c2c66affSColin Finck         /* Build StartupInfo */
979c2c66affSColin Finck         RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
980c2c66affSColin Finck 
981c2c66affSColin Finck         StartupInfo.cb = sizeof(STARTUPINFOA);
982c2c66affSColin Finck         StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
983c2c66affSColin Finck         StartupInfo.wShowWindow = LoadParams->wCmdShow;
984c2c66affSColin Finck 
985c2c66affSColin Finck         /* Allocate command line buffer */
986c2c66affSColin Finck         CommandLine = RtlAllocateHeap(RtlGetProcessHeap(),
987c2c66affSColin Finck                                       HEAP_ZERO_MEMORY,
988c2c66affSColin Finck                                       (ULONG)LoadParams->lpCmdLine[0] + Length + 2);
989c2c66affSColin Finck 
990c2c66affSColin Finck         /* Put module name there, then a space, and then copy provided command line,
991c2c66affSColin Finck            and null-terminate it */
992c2c66affSColin Finck         RtlCopyMemory(CommandLine, FileName, Length);
993c2c66affSColin Finck         CommandLine[Length] = ' ';
994c2c66affSColin Finck         RtlCopyMemory(&CommandLine[Length + 1], &LoadParams->lpCmdLine[1], (ULONG)LoadParams->lpCmdLine[0]);
995c2c66affSColin Finck         CommandLine[Length + 1 + (ULONG)LoadParams->lpCmdLine[0]] = 0;
996c2c66affSColin Finck 
997c2c66affSColin Finck         /* Create the process */
998c2c66affSColin Finck         ProcessStatus = CreateProcessA(FileName,
999c2c66affSColin Finck                                        CommandLine,
1000c2c66affSColin Finck                                        NULL,
1001c2c66affSColin Finck                                        NULL,
1002c2c66affSColin Finck                                        FALSE,
1003c2c66affSColin Finck                                        0,
1004c2c66affSColin Finck                                        LoadParams->lpEnvAddress,
1005c2c66affSColin Finck                                        NULL,
1006c2c66affSColin Finck                                        &StartupInfo,
1007c2c66affSColin Finck                                        &ProcessInformation);
1008c2c66affSColin Finck 
1009c2c66affSColin Finck         /* Free the command line buffer */
1010c2c66affSColin Finck         RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine);
1011c2c66affSColin Finck 
1012c2c66affSColin Finck         if (!ProcessStatus)
1013c2c66affSColin Finck         {
1014c2c66affSColin Finck             /* Creating process failed, return right error code */
1015c2c66affSColin Finck             Error = GetLastError();
1016c2c66affSColin Finck             switch(Error)
1017c2c66affSColin Finck             {
1018c2c66affSColin Finck             case ERROR_BAD_EXE_FORMAT:
1019c2c66affSColin Finck                return ERROR_BAD_FORMAT;
1020c2c66affSColin Finck 
1021c2c66affSColin Finck             case ERROR_FILE_NOT_FOUND:
1022c2c66affSColin Finck             case ERROR_PATH_NOT_FOUND:
1023c2c66affSColin Finck                 return Error;
1024c2c66affSColin Finck             }
1025c2c66affSColin Finck 
1026c2c66affSColin Finck             /* Return 0 otherwise */
1027c2c66affSColin Finck             return 0;
1028c2c66affSColin Finck         }
1029c2c66affSColin Finck 
1030c2c66affSColin Finck         /* Wait up to 30 seconds for the process to become idle */
1031c2c66affSColin Finck         if (UserWaitForInputIdleRoutine)
1032c2c66affSColin Finck         {
1033c2c66affSColin Finck             UserWaitForInputIdleRoutine(ProcessInformation.hProcess, 30000);
1034c2c66affSColin Finck         }
1035c2c66affSColin Finck 
1036c2c66affSColin Finck         /* Close handles */
1037c2c66affSColin Finck         NtClose(ProcessInformation.hThread);
1038c2c66affSColin Finck         NtClose(ProcessInformation.hProcess);
1039c2c66affSColin Finck 
1040c2c66affSColin Finck         /* Return magic success value (33) */
1041c2c66affSColin Finck         return 33;
1042c2c66affSColin Finck     }
1043c2c66affSColin Finck 
1044c2c66affSColin Finck     /* The path was not found, create an ansi string from
1045c2c66affSColin Finck         the module name and convert it to unicode */
1046c2c66affSColin Finck     RtlInitAnsiString(&AnsiStr, lpModuleName);
1047c2c66affSColin Finck     if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr,&AnsiStr,TRUE)))
1048c2c66affSColin Finck         return ERROR_FILE_NOT_FOUND;
1049c2c66affSColin Finck 
1050c2c66affSColin Finck     /* Determine path type */
1051c2c66affSColin Finck     PathType = RtlDetermineDosPathNameType_U(UnicStr.Buffer);
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     /* Free the unicode module name */
1054c2c66affSColin Finck     RtlFreeUnicodeString(&UnicStr);
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     /* If it's a relative path, return file not found */
1057c2c66affSColin Finck     if (PathType == RtlPathTypeRelative)
1058c2c66affSColin Finck         return ERROR_FILE_NOT_FOUND;
1059c2c66affSColin Finck 
1060c2c66affSColin Finck     /* If not, try to open it */
1061c2c66affSColin Finck     Handle = CreateFile(lpModuleName,
1062c2c66affSColin Finck                         GENERIC_READ,
1063c2c66affSColin Finck                         FILE_SHARE_READ | FILE_SHARE_WRITE,
1064c2c66affSColin Finck                         NULL,
1065c2c66affSColin Finck                         OPEN_EXISTING,
1066c2c66affSColin Finck                         FILE_ATTRIBUTE_NORMAL,
1067c2c66affSColin Finck                         NULL);
1068c2c66affSColin Finck 
1069c2c66affSColin Finck     if (Handle != INVALID_HANDLE_VALUE)
1070c2c66affSColin Finck     {
1071c2c66affSColin Finck         /* Opening file succeeded for some reason, close the handle and return file not found anyway */
1072c2c66affSColin Finck         CloseHandle(Handle);
1073c2c66affSColin Finck         return ERROR_FILE_NOT_FOUND;
1074c2c66affSColin Finck     }
1075c2c66affSColin Finck 
1076c2c66affSColin Finck     /* Return last error which CreateFile set during an attempt to open it */
1077c2c66affSColin Finck     return GetLastError();
1078c2c66affSColin Finck }
1079c2c66affSColin Finck 
1080c2c66affSColin Finck /*
1081c2c66affSColin Finck  * @unimplemented
1082c2c66affSColin Finck  */
DelayLoadFailureHook(LPCSTR pszDllName,LPCSTR pszProcName)1083c2c66affSColin Finck FARPROC WINAPI DelayLoadFailureHook(LPCSTR pszDllName, LPCSTR pszProcName)
1084c2c66affSColin Finck {
1085c2c66affSColin Finck     STUB;
1086c2c66affSColin Finck     return NULL;
1087c2c66affSColin Finck }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck /*
1090c2c66affSColin Finck  * @unimplemented
1091c2c66affSColin Finck  */
UTRegister(HMODULE hModule,LPSTR lpsz16BITDLL,LPSTR lpszInitName,LPSTR lpszProcName,FARPROC * ppfn32Thunk,FARPROC pfnUT32CallBack,LPVOID lpBuff)1092c2c66affSColin Finck BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
1093c2c66affSColin Finck                         LPSTR lpszInitName, LPSTR lpszProcName,
1094c2c66affSColin Finck                         FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
1095c2c66affSColin Finck                         LPVOID lpBuff )
1096c2c66affSColin Finck {
1097c2c66affSColin Finck     STUB;
1098c2c66affSColin Finck     return 0;
1099c2c66affSColin Finck }
1100c2c66affSColin Finck 
1101c2c66affSColin Finck /*
1102c2c66affSColin Finck  * @unimplemented
1103c2c66affSColin Finck  */
UTUnRegister(HMODULE hModule)1104c2c66affSColin Finck VOID WINAPI UTUnRegister( HMODULE hModule )
1105c2c66affSColin Finck {
1106c2c66affSColin Finck     STUB;
1107c2c66affSColin Finck }
1108c2c66affSColin Finck 
1109c2c66affSColin Finck /*
1110c2c66affSColin Finck  * @unimplemented
1111c2c66affSColin Finck  */
1112c2c66affSColin Finck BOOL
1113c2c66affSColin Finck WINAPI
BaseQueryModuleData(IN LPSTR ModuleName,IN LPSTR Unknown,IN PVOID Unknown2,IN PVOID Unknown3,IN PVOID Unknown4)1114c2c66affSColin Finck BaseQueryModuleData(IN LPSTR ModuleName,
1115c2c66affSColin Finck                     IN LPSTR Unknown,
1116c2c66affSColin Finck                     IN PVOID Unknown2,
1117c2c66affSColin Finck                     IN PVOID Unknown3,
1118c2c66affSColin Finck                     IN PVOID Unknown4)
1119c2c66affSColin Finck {
1120c2c66affSColin Finck     DPRINT1("BaseQueryModuleData called: %s %s %p %p %p\n",
1121c2c66affSColin Finck             ModuleName,
1122c2c66affSColin Finck             Unknown,
1123c2c66affSColin Finck             Unknown2,
1124c2c66affSColin Finck             Unknown3,
1125c2c66affSColin Finck             Unknown4);
1126c2c66affSColin Finck     return FALSE;
1127c2c66affSColin Finck }
1128c2c66affSColin Finck 
1129c2c66affSColin Finck /*
1130c2c66affSColin Finck  * @implemented
1131c2c66affSColin Finck  */
1132c2c66affSColin Finck NTSTATUS
1133c2c66affSColin Finck WINAPI
BaseProcessInitPostImport(VOID)1134c2c66affSColin Finck BaseProcessInitPostImport(VOID)
1135c2c66affSColin Finck {
11362bd33d58SPierre Schweitzer     DPRINT("Post-init called\n");
11372bd33d58SPierre Schweitzer 
1138c2c66affSColin Finck     /* Check if this is a terminal server */
1139c2c66affSColin Finck     if (SharedUserData->SuiteMask & VER_SUITE_TERMINAL)
1140c2c66affSColin Finck     {
1141c2c66affSColin Finck         /* Initialize TS pointers */
1142c2c66affSColin Finck         return BasepInitializeTermsrvFpns();
1143c2c66affSColin Finck     }
1144c2c66affSColin Finck 
1145c2c66affSColin Finck     /* FIXME: Initialize TS pointers */
1146c2c66affSColin Finck     return STATUS_SUCCESS;
1147c2c66affSColin Finck }
1148c2c66affSColin Finck 
1149c2c66affSColin Finck /* EOF */
1150