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