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