Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenloader.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT : ReactOS system libraries 00004 * MODULE : kernel32.dll 00005 * FILE : reactos/dll/win32/kernel32/misc/ldr.c 00006 * AUTHOR : Aleksey Bragin <aleksey@reactos.org> 00007 */ 00008 00009 #include <k32.h> 00010 00011 #define NDEBUG 00012 #include <debug.h> 00013 00014 /* FUNCTIONS ****************************************************************/ 00015 00016 DWORD 00017 WINAPI 00018 BasepGetModuleHandleExParameterValidation(DWORD dwFlags, 00019 LPCWSTR lpwModuleName, 00020 HMODULE *phModule) 00021 { 00022 /* Set phModule to 0 if it's not a NULL pointer */ 00023 if (phModule) *phModule = 0; 00024 00025 /* Check for invalid flags combination */ 00026 if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | 00027 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | 00028 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) || 00029 ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) && 00030 (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) || 00031 (!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) 00032 ) 00033 { 00034 BaseSetLastNTError(STATUS_INVALID_PARAMETER_1); 00035 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; 00036 } 00037 00038 /* Check 2nd parameter */ 00039 if (!phModule) 00040 { 00041 BaseSetLastNTError(STATUS_INVALID_PARAMETER_2); 00042 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR; 00043 } 00044 00045 /* Return what we have according to the module name */ 00046 if (lpwModuleName) 00047 { 00048 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE; 00049 } 00050 00051 /* No name given, so put ImageBaseAddress there */ 00052 *phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress; 00053 00054 return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS; 00055 } 00056 00057 PVOID 00058 WINAPI 00059 BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile) 00060 { 00061 /* If no handle is provided - use current image base address */ 00062 if (!hModule) return NtCurrentPeb()->ImageBaseAddress; 00063 00064 /* Check if it's a normal or a datafile one */ 00065 if (LDR_IS_DATAFILE(hModule) && !AsDataFile) 00066 return NULL; 00067 00068 /* It'a a normal DLL, just return its handle */ 00069 return hModule; 00070 } 00071 00072 /* 00073 * @implemented 00074 */ 00075 BOOL 00076 WINAPI 00077 DisableThreadLibraryCalls( 00078 IN HMODULE hLibModule) 00079 { 00080 NTSTATUS Status; 00081 00082 /* Disable thread library calls */ 00083 Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule); 00084 00085 /* If it wasn't success - set last error and return failure */ 00086 if (!NT_SUCCESS(Status)) 00087 { 00088 BaseSetLastNTError(Status); 00089 return FALSE; 00090 } 00091 00092 /* Return success */ 00093 return TRUE; 00094 } 00095 00096 00097 /* 00098 * @implemented 00099 */ 00100 HINSTANCE 00101 WINAPI 00102 LoadLibraryA(LPCSTR lpLibFileName) 00103 { 00104 LPSTR PathBuffer; 00105 UINT Len; 00106 HINSTANCE Result; 00107 00108 /* Treat twain_32.dll in a special way (what a surprise...) */ 00109 if (lpLibFileName && !_strcmpi(lpLibFileName, "twain_32.dll")) 00110 { 00111 /* Allocate space for the buffer */ 00112 PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH); 00113 if (PathBuffer) 00114 { 00115 /* Get windows dir in this buffer */ 00116 Len = GetWindowsDirectoryA(PathBuffer, MAX_PATH - 13); /* 13 is sizeof of '\\twain_32.dll' */ 00117 if (Len && Len < (MAX_PATH - 13)) 00118 { 00119 /* We successfully got windows directory. Concatenate twain_32.dll to it */ 00120 strncat(PathBuffer, "\\twain_32.dll", 13); 00121 00122 /* And recursively call ourselves with a new string */ 00123 Result = LoadLibraryA(PathBuffer); 00124 00125 /* If it was successful - free memory and return result */ 00126 if (Result) 00127 { 00128 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); 00129 return Result; 00130 } 00131 } 00132 00133 /* Free allocated buffer */ 00134 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); 00135 } 00136 } 00137 00138 /* Call the Ex version of the API */ 00139 return LoadLibraryExA(lpLibFileName, 0, 0); 00140 } 00141 00142 /* 00143 * @implemented 00144 */ 00145 HINSTANCE 00146 WINAPI 00147 LoadLibraryExA(LPCSTR lpLibFileName, 00148 HANDLE hFile, 00149 DWORD dwFlags) 00150 { 00151 PUNICODE_STRING FileNameW; 00152 00153 /* Convert file name to unicode */ 00154 if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName))) 00155 return NULL; 00156 00157 /* And call W version of the API */ 00158 return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags); 00159 } 00160 00161 /* 00162 * @implemented 00163 */ 00164 HINSTANCE 00165 WINAPI 00166 LoadLibraryW(LPCWSTR lpLibFileName) 00167 { 00168 /* Call Ex version of the API */ 00169 return LoadLibraryExW (lpLibFileName, 0, 0); 00170 } 00171 00172 00173 static 00174 NTSTATUS 00175 BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule) 00176 { 00177 WCHAR FilenameW[MAX_PATH]; 00178 HANDLE hFile = INVALID_HANDLE_VALUE; 00179 HANDLE hMapping; 00180 NTSTATUS Status; 00181 PVOID lpBaseAddress = NULL; 00182 SIZE_T ViewSize = 0; 00183 //PUNICODE_STRING OriginalName; 00184 //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL"); 00185 00186 /* Zero out handle value */ 00187 *hModule = 0; 00188 00189 DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule); 00190 00191 /*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE, 00192 Name, 00193 &dotDLL, 00194 RedirName, 00195 RedirName2, 00196 &OriginalName2, 00197 NULL, 00198 NULL, 00199 NULL);*/ 00200 00201 /* Try to search for it */ 00202 if (!SearchPathW(Path, 00203 Name, 00204 L".DLL", 00205 sizeof(FilenameW) / sizeof(FilenameW[0]), 00206 FilenameW, 00207 NULL)) 00208 { 00209 /* Return last status value directly */ 00210 return NtCurrentTeb()->LastStatusValue; 00211 } 00212 00213 /* Open this file we found */ 00214 hFile = CreateFileW(FilenameW, 00215 GENERIC_READ, 00216 FILE_SHARE_READ | FILE_SHARE_DELETE, 00217 NULL, 00218 OPEN_EXISTING, 00219 0, 00220 0); 00221 00222 /* If opening failed - return last status value */ 00223 if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue; 00224 00225 /* Create file mapping */ 00226 hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 00227 00228 /* Close the file handle */ 00229 CloseHandle(hFile); 00230 00231 /* If creating file mapping failed - return last status value */ 00232 if (!hMapping) return NtCurrentTeb()->LastStatusValue; 00233 00234 /* Map view of section */ 00235 Status = NtMapViewOfSection(hMapping, 00236 NtCurrentProcess(), 00237 &lpBaseAddress, 00238 0, 00239 0, 00240 0, 00241 &ViewSize, 00242 ViewShare, 00243 0, 00244 PAGE_READONLY); 00245 00246 /* Close handle to the section */ 00247 CloseHandle(hMapping); 00248 00249 /* If mapping view of section failed - return last status value */ 00250 if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue; 00251 00252 /* Make sure it's a valid PE file */ 00253 if (!RtlImageNtHeader(lpBaseAddress)) 00254 { 00255 /* Unmap the view and return failure status */ 00256 UnmapViewOfFile(lpBaseAddress); 00257 return STATUS_INVALID_IMAGE_FORMAT; 00258 } 00259 00260 /* Set low bit of handle to indicate datafile module */ 00261 *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1); 00262 00263 /* Load alternate resource module */ 00264 //LdrLoadAlternateResourceModule(*hModule, FilenameW); 00265 00266 return STATUS_SUCCESS; 00267 } 00268 00269 /* 00270 * @implemented 00271 */ 00272 HINSTANCE 00273 WINAPI 00274 LoadLibraryExW(LPCWSTR lpLibFileName, 00275 HANDLE hFile, 00276 DWORD dwFlags) 00277 { 00278 UNICODE_STRING DllName; 00279 HINSTANCE hInst; 00280 NTSTATUS Status; 00281 PWSTR SearchPath; 00282 ULONG DllCharacteristics = 0; 00283 BOOL FreeString = FALSE; 00284 00285 /* Check for any flags LdrLoadDll might be interested in */ 00286 if (dwFlags & DONT_RESOLVE_DLL_REFERENCES) 00287 { 00288 /* Tell LDR to treat it as an EXE */ 00289 DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE; 00290 } 00291 00292 /* Build up a unicode dll name from null-terminated string */ 00293 RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName); 00294 00295 /* Lazy-initialize BasepExeLdrEntry */ 00296 if (!BasepExeLdrEntry) 00297 LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress); 00298 00299 /* Check if that module is our exe*/ 00300 if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) && 00301 DllName.Length == BasepExeLdrEntry->FullDllName.Length) 00302 { 00303 /* Lengths match and it's not a datafile, so perform name comparison */ 00304 if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE)) 00305 { 00306 /* That's us! */ 00307 return BasepExeLdrEntry->DllBase; 00308 } 00309 } 00310 00311 /* Check for trailing spaces and remove them if necessary */ 00312 if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') 00313 { 00314 RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName); 00315 while (DllName.Length > sizeof(WCHAR) && 00316 DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ') 00317 { 00318 DllName.Length -= sizeof(WCHAR); 00319 } 00320 DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL; 00321 FreeString = TRUE; 00322 } 00323 00324 /* Compute the load path */ 00325 SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? 00326 DllName.Buffer : NULL, 00327 NULL); 00328 if (!SearchPath) 00329 { 00330 /* Getting DLL path failed, so set last error, free mem and return */ 00331 BaseSetLastNTError(STATUS_NO_MEMORY); 00332 if (FreeString) RtlFreeUnicodeString(&DllName); 00333 return NULL; 00334 } 00335 00336 _SEH2_TRY 00337 { 00338 if (dwFlags & LOAD_LIBRARY_AS_DATAFILE) 00339 { 00340 /* If the image is loaded as a datafile, try to get its handle */ 00341 Status = LdrGetDllHandleEx(0, SearchPath, NULL, &DllName, (PVOID*)&hInst); 00342 if (!NT_SUCCESS(Status)) 00343 { 00344 /* It's not loaded yet - so load it up */ 00345 Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst); 00346 } 00347 _SEH2_YIELD(goto done;) 00348 } 00349 00350 /* Call the API Properly */ 00351 Status = LdrLoadDll(SearchPath, 00352 &DllCharacteristics, 00353 &DllName, 00354 (PVOID*)&hInst); 00355 } 00356 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00357 { 00358 Status = _SEH2_GetExceptionCode(); 00359 } _SEH2_END; 00360 00361 00362 done: 00363 /* Free SearchPath buffer */ 00364 RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); 00365 00366 /* Free DllName string if it was dynamically allocated */ 00367 if (FreeString) RtlFreeUnicodeString(&DllName); 00368 00369 /* Set last error in failure case */ 00370 if (!NT_SUCCESS(Status)) 00371 { 00372 BaseSetLastNTError(Status); 00373 return NULL; 00374 } 00375 00376 /* Return loaded module handle */ 00377 return hInst; 00378 } 00379 00380 00381 /* 00382 * @implemented 00383 */ 00384 FARPROC 00385 WINAPI 00386 GetProcAddress(HMODULE hModule, LPCSTR lpProcName) 00387 { 00388 ANSI_STRING ProcedureName, *ProcNamePtr = NULL; 00389 FARPROC fnExp = NULL; 00390 NTSTATUS Status; 00391 PVOID hMapped; 00392 ULONG Ordinal = 0; 00393 00394 if (HIWORD(lpProcName) != 0) 00395 { 00396 /* Look up by name */ 00397 RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName); 00398 ProcNamePtr = &ProcedureName; 00399 } 00400 else 00401 { 00402 /* Look up by ordinal */ 00403 Ordinal = (ULONG)lpProcName; 00404 } 00405 00406 /* Map provided handle */ 00407 hMapped = BasepMapModuleHandle(hModule, FALSE); 00408 00409 /* Get the proc address */ 00410 Status = LdrGetProcedureAddress(hMapped, 00411 ProcNamePtr, 00412 Ordinal, 00413 (PVOID*)&fnExp); 00414 00415 if (!NT_SUCCESS(Status)) 00416 { 00417 BaseSetLastNTError(Status); 00418 return NULL; 00419 } 00420 00421 /* Check for a special case when returned pointer is 00422 the same as iamge's base address */ 00423 if (fnExp == hMapped) 00424 { 00425 /* Set correct error code */ 00426 if (HIWORD(lpProcName) != 0) 00427 BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND); 00428 else 00429 BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND); 00430 00431 return NULL; 00432 } 00433 00434 /* All good, return procedure pointer */ 00435 return fnExp; 00436 } 00437 00438 00439 /* 00440 * @implemented 00441 */ 00442 BOOL WINAPI FreeLibrary(HINSTANCE hLibModule) 00443 { 00444 NTSTATUS Status; 00445 PIMAGE_NT_HEADERS NtHeaders; 00446 00447 if (LDR_IS_DATAFILE(hLibModule)) 00448 { 00449 // FIXME: This SEH should go inside RtlImageNtHeader instead 00450 _SEH2_TRY 00451 { 00452 /* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */ 00453 NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)); 00454 } 00455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00456 { 00457 NtHeaders = NULL; 00458 } _SEH2_END 00459 00460 if (NtHeaders) 00461 { 00462 /* Unmap view */ 00463 Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); 00464 00465 /* Unload alternate resource module */ 00466 LdrUnloadAlternateResourceModule(hLibModule); 00467 } 00468 else 00469 Status = STATUS_INVALID_IMAGE_FORMAT; 00470 } 00471 else 00472 { 00473 /* Just unload it */ 00474 Status = LdrUnloadDll((PVOID)hLibModule); 00475 } 00476 00477 /* Check what kind of status we got */ 00478 if (!NT_SUCCESS(Status)) 00479 { 00480 /* Set last error */ 00481 BaseSetLastNTError(Status); 00482 00483 /* Return failure */ 00484 return FALSE; 00485 } 00486 00487 /* Return success */ 00488 return TRUE; 00489 } 00490 00491 00492 /* 00493 * @implemented 00494 */ 00495 VOID 00496 WINAPI 00497 FreeLibraryAndExitThread(HMODULE hLibModule, 00498 DWORD dwExitCode) 00499 { 00500 00501 if (LDR_IS_DATAFILE(hLibModule)) 00502 { 00503 /* This is a LOAD_LIBRARY_AS_DATAFILE module */ 00504 if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1))) 00505 { 00506 /* Unmap view */ 00507 NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1)); 00508 00509 /* Unload alternate resource module */ 00510 LdrUnloadAlternateResourceModule(hLibModule); 00511 } 00512 } 00513 else 00514 { 00515 /* Just unload it */ 00516 LdrUnloadDll((PVOID)hLibModule); 00517 } 00518 00519 /* Exit thread */ 00520 ExitThread(dwExitCode); 00521 } 00522 00523 00524 /* 00525 * @implemented 00526 */ 00527 DWORD 00528 WINAPI 00529 GetModuleFileNameA(HINSTANCE hModule, 00530 LPSTR lpFilename, 00531 DWORD nSize) 00532 { 00533 UNICODE_STRING FilenameW; 00534 ANSI_STRING FilenameA; 00535 NTSTATUS Status; 00536 DWORD Length = 0, LengthToCopy; 00537 00538 /* Allocate a unicode buffer */ 00539 FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR)); 00540 if (!FilenameW.Buffer) 00541 { 00542 BaseSetLastNTError(STATUS_NO_MEMORY); 00543 return 0; 00544 } 00545 00546 /* Call unicode API */ 00547 FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR); 00548 FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR); 00549 00550 if (FilenameW.Length) 00551 { 00552 /* Convert to ansi string */ 00553 Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE); 00554 if (!NT_SUCCESS(Status)) 00555 { 00556 /* Set last error, free string and retun failure */ 00557 BaseSetLastNTError(Status); 00558 RtlFreeUnicodeString(&FilenameW); 00559 return 0; 00560 } 00561 00562 /* Calculate size to copy */ 00563 Length = min(nSize, FilenameA.Length); 00564 00565 /* Include terminating zero */ 00566 if (nSize > Length) 00567 LengthToCopy = Length + 1; 00568 else 00569 LengthToCopy = nSize; 00570 00571 /* Now copy back to the caller amount he asked */ 00572 RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy); 00573 00574 /* Free ansi filename */ 00575 RtlFreeAnsiString(&FilenameA); 00576 } 00577 00578 /* Free unicode filename */ 00579 RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer); 00580 00581 /* Return length copied */ 00582 return Length; 00583 } 00584 00585 /* 00586 * @implemented 00587 */ 00588 DWORD 00589 WINAPI 00590 GetModuleFileNameW(HINSTANCE hModule, 00591 LPWSTR lpFilename, 00592 DWORD nSize) 00593 { 00594 PLIST_ENTRY ModuleListHead, Entry; 00595 PLDR_DATA_TABLE_ENTRY Module; 00596 ULONG Length = 0; 00597 ULONG Cookie; 00598 PPEB Peb; 00599 00600 hModule = BasepMapModuleHandle(hModule, FALSE); 00601 00602 /* Upscale nSize from chars to bytes */ 00603 nSize *= sizeof(WCHAR); 00604 00605 _SEH2_TRY 00606 { 00607 /* We don't use per-thread cur dir now */ 00608 //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib; 00609 00610 Peb = NtCurrentPeb (); 00611 00612 /* Acquire a loader lock */ 00613 LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie); 00614 00615 /* Traverse the module list */ 00616 ModuleListHead = &Peb->Ldr->InLoadOrderModuleList; 00617 Entry = ModuleListHead->Flink; 00618 while (Entry != ModuleListHead) 00619 { 00620 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 00621 00622 /* Check if this is the requested module */ 00623 if (Module->DllBase == (PVOID)hModule) 00624 { 00625 /* Calculate size to copy */ 00626 Length = min(nSize, Module->FullDllName.MaximumLength); 00627 00628 /* Copy contents */ 00629 RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length); 00630 00631 /* Subtract a terminating zero */ 00632 if (Length == Module->FullDllName.MaximumLength) 00633 Length -= sizeof(WCHAR); 00634 00635 /* Break out of the loop */ 00636 break; 00637 } 00638 00639 /* Advance to the next entry */ 00640 Entry = Entry->Flink; 00641 } 00642 } 00643 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00644 { 00645 BaseSetLastNTError(_SEH2_GetExceptionCode()); 00646 Length = 0; 00647 } _SEH2_END 00648 00649 /* Release the loader lock */ 00650 LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie); 00651 00652 return Length / sizeof(WCHAR); 00653 } 00654 00655 HMODULE 00656 WINAPI 00657 GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName) 00658 { 00659 NTSTATUS Status; 00660 PVOID Module; 00661 LPWSTR DllPath; 00662 00663 /* Try to get a handle with a magic value of 1 for DllPath */ 00664 Status = LdrGetDllHandle((LPWSTR)1, NULL, ModuleName, &Module); 00665 00666 /* If that succeeded - we're done */ 00667 if (NT_SUCCESS(Status)) return Module; 00668 00669 /* If not, then the path should be computed */ 00670 DllPath = BaseComputeProcessDllPath(NULL, 0); 00671 if (!DllPath) 00672 { 00673 Status = STATUS_NO_MEMORY; 00674 } 00675 else 00676 { 00677 _SEH2_TRY 00678 { 00679 Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module); 00680 } 00681 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00682 { 00683 /* Fail with the SEH error */ 00684 Status = _SEH2_GetExceptionCode(); 00685 } 00686 _SEH2_END; 00687 } 00688 00689 /* Free the DllPath */ 00690 RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath); 00691 00692 /* In case of error set last win32 error and return NULL */ 00693 if (!NT_SUCCESS(Status)) 00694 { 00695 DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName, Status); 00696 BaseSetLastNTError(Status); 00697 Module = 0; 00698 } 00699 00700 /* Return module */ 00701 return (HMODULE)Module; 00702 } 00703 00704 BOOLEAN 00705 WINAPI 00706 BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleName, HMODULE *phModule) 00707 { 00708 DWORD Cookie; 00709 NTSTATUS Status = STATUS_SUCCESS, Status2; 00710 HANDLE hModule = 0; 00711 UNICODE_STRING ModuleNameU; 00712 DWORD dwValid; 00713 BOOLEAN Redirected = FALSE; // FIXME 00714 00715 /* Validate parameters */ 00716 dwValid = BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule); 00717 ASSERT(dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE); 00718 00719 /* Acquire lock if necessary */ 00720 if (!NoLock) 00721 { 00722 Status = LdrLockLoaderLock(0, NULL, &Cookie); 00723 if (!NT_SUCCESS(Status)) 00724 { 00725 /* Fail */ 00726 BaseSetLastNTError(Status); 00727 if (phModule) *phModule = 0; 00728 return NT_SUCCESS(Status); 00729 } 00730 } 00731 00732 if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) 00733 { 00734 /* Create a unicode string out of module name */ 00735 RtlInitUnicodeString(&ModuleNameU, lpwModuleName); 00736 00737 // FIXME: Do some redirected DLL stuff? 00738 if (Redirected) 00739 { 00740 UNIMPLEMENTED; 00741 } 00742 00743 if (!hModule) 00744 { 00745 hModule = GetModuleHandleForUnicodeString(&ModuleNameU); 00746 if (!hModule) 00747 { 00748 /* Last error is already set, so just return failure by setting status */ 00749 Status = STATUS_DLL_NOT_FOUND; 00750 goto quickie; 00751 } 00752 } 00753 } 00754 else 00755 { 00756 /* Perform Pc to file header to get module instance */ 00757 hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpwModuleName, 00758 (PVOID*)&hModule); 00759 00760 /* Check if it succeeded */ 00761 if (!hModule) 00762 { 00763 /* Set "dll not found" status and quit */ 00764 Status = STATUS_DLL_NOT_FOUND; 00765 goto quickie; 00766 } 00767 } 00768 00769 /* Check if changing reference is not forbidden */ 00770 if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) 00771 { 00772 /* Add reference to this DLL */ 00773 Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0, 00774 hModule); 00775 } 00776 00777 /* Set last error in case of failure */ 00778 if (!NT_SUCCESS(Status)) 00779 BaseSetLastNTError(Status); 00780 00781 quickie: 00782 /* Unlock loader lock if it was acquired */ 00783 if (!NoLock) 00784 { 00785 Status2 = LdrUnlockLoaderLock(0, Cookie); 00786 ASSERT(NT_SUCCESS(Status2)); 00787 } 00788 00789 /* Set the module handle to the caller */ 00790 if (phModule) *phModule = hModule; 00791 00792 /* Return TRUE on success and FALSE otherwise */ 00793 return NT_SUCCESS(Status); 00794 } 00795 00796 /* 00797 * @implemented 00798 */ 00799 HMODULE 00800 WINAPI 00801 GetModuleHandleA(LPCSTR lpModuleName) 00802 { 00803 PUNICODE_STRING ModuleNameW; 00804 PTEB pTeb = NtCurrentTeb(); 00805 00806 /* Check if we have no name to convert */ 00807 if (!lpModuleName) 00808 return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress); 00809 00810 /* Convert module name to unicode */ 00811 ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); 00812 00813 /* Call W version if conversion was successful */ 00814 if (ModuleNameW) 00815 return GetModuleHandleW(ModuleNameW->Buffer); 00816 00817 /* Return failure */ 00818 return 0; 00819 } 00820 00821 00822 /* 00823 * @implemented 00824 */ 00825 HMODULE 00826 WINAPI 00827 GetModuleHandleW(LPCWSTR lpModuleName) 00828 { 00829 HMODULE hModule; 00830 NTSTATUS Status; 00831 00832 /* If current module is requested - return it right away */ 00833 if (!lpModuleName) 00834 return ((HMODULE)NtCurrentPeb()->ImageBaseAddress); 00835 00836 /* Use common helper routine */ 00837 Status = BasepGetModuleHandleExW(TRUE, 00838 GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, 00839 lpModuleName, 00840 &hModule); 00841 00842 /* If it wasn't successful - return 0 */ 00843 if (!NT_SUCCESS(Status)) hModule = 0; 00844 00845 /* Return the handle */ 00846 return hModule; 00847 } 00848 00849 00850 /* 00851 * @implemented 00852 */ 00853 BOOL 00854 WINAPI 00855 GetModuleHandleExW(IN DWORD dwFlags, 00856 IN LPCWSTR lpwModuleName OPTIONAL, 00857 OUT HMODULE* phModule) 00858 { 00859 NTSTATUS Status; 00860 DWORD dwValid; 00861 BOOL Ret = FALSE; 00862 00863 /* Validate parameters */ 00864 dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule); 00865 00866 /* If result is invalid parameter - return failure */ 00867 if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; 00868 00869 /* If result is 2, there is no need to do anything - return success. */ 00870 if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; 00871 00872 /* Use common helper routine */ 00873 Status = BasepGetModuleHandleExW(FALSE, 00874 dwFlags, 00875 lpwModuleName, 00876 phModule); 00877 00878 /* Return TRUE in case of success */ 00879 if (NT_SUCCESS(Status)) Ret = TRUE; 00880 00881 return Ret; 00882 } 00883 00884 /* 00885 * @implemented 00886 */ 00887 BOOL 00888 WINAPI 00889 GetModuleHandleExA(IN DWORD dwFlags, 00890 IN LPCSTR lpModuleName OPTIONAL, 00891 OUT HMODULE* phModule) 00892 { 00893 PUNICODE_STRING lpModuleNameW; 00894 DWORD dwValid; 00895 BOOL Ret = FALSE; 00896 NTSTATUS Status; 00897 00898 /* Validate parameters */ 00899 dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule); 00900 00901 /* If result is invalid parameter - return failure */ 00902 if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE; 00903 00904 /* If result is 2, there is no need to do anything - return success. */ 00905 if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE; 00906 00907 /* Check if we don't need to convert the name */ 00908 if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) 00909 { 00910 /* Call the extended version of the API without conversion */ 00911 Status = BasepGetModuleHandleExW(FALSE, 00912 dwFlags, 00913 (LPCWSTR)lpModuleName, 00914 phModule); 00915 } 00916 else 00917 { 00918 /* Convert module name to unicode */ 00919 lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName); 00920 00921 /* Return FALSE if conversion failed */ 00922 if (!lpModuleNameW) return FALSE; 00923 00924 /* Call the extended version of the API */ 00925 Status = BasepGetModuleHandleExW(FALSE, 00926 dwFlags, 00927 lpModuleNameW->Buffer, 00928 phModule); 00929 } 00930 00931 /* If result was successful - return true */ 00932 if (NT_SUCCESS(Status)) 00933 Ret = TRUE; 00934 00935 /* Return result */ 00936 return Ret; 00937 } 00938 00939 00940 /* 00941 * @implemented 00942 */ 00943 DWORD 00944 WINAPI 00945 LoadModule(LPCSTR lpModuleName, 00946 LPVOID lpParameterBlock) 00947 { 00948 STARTUPINFOA StartupInfo; 00949 PROCESS_INFORMATION ProcessInformation; 00950 LOADPARMS32 *LoadParams; 00951 char FileName[MAX_PATH]; 00952 LPSTR CommandLine; 00953 DWORD Length, Error; 00954 BOOL ProcessStatus; 00955 ANSI_STRING AnsiStr; 00956 UNICODE_STRING UnicStr; 00957 RTL_PATH_TYPE PathType; 00958 HANDLE Handle; 00959 00960 LoadParams = (LOADPARMS32*)lpParameterBlock; 00961 00962 /* Check load parameters */ 00963 if (LoadParams->dwReserved || LoadParams->wMagicValue != 2) 00964 { 00965 /* Fail with invalid param error */ 00966 BaseSetLastNTError(STATUS_INVALID_PARAMETER); 00967 return 0; 00968 } 00969 00970 /* Search path */ 00971 Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL); 00972 00973 /* Check if path was found */ 00974 if (Length && Length < MAX_PATH) 00975 { 00976 /* Build StartupInfo */ 00977 RtlZeroMemory(&StartupInfo, sizeof(StartupInfo)); 00978 00979 StartupInfo.cb = sizeof(STARTUPINFOA); 00980 StartupInfo.dwFlags = STARTF_USESHOWWINDOW; 00981 StartupInfo.wShowWindow = LoadParams->wCmdShow; 00982 00983 /* Allocate command line buffer */ 00984 CommandLine = RtlAllocateHeap(RtlGetProcessHeap(), 00985 HEAP_ZERO_MEMORY, 00986 (ULONG)LoadParams->lpCmdLine[0] + Length + 2); 00987 00988 /* Put module name there, then a space, and then copy provided command line, 00989 and null-terminate it */ 00990 RtlCopyMemory(CommandLine, FileName, Length); 00991 CommandLine[Length] = ' '; 00992 RtlCopyMemory(&CommandLine[Length + 1], &LoadParams->lpCmdLine[1], (ULONG)LoadParams->lpCmdLine[0]); 00993 CommandLine[Length + 1 + (ULONG)LoadParams->lpCmdLine[0]] = 0; 00994 00995 /* Create the process */ 00996 ProcessStatus = CreateProcessA(FileName, 00997 CommandLine, 00998 NULL, 00999 NULL, 01000 FALSE, 01001 0, 01002 LoadParams->lpEnvAddress, 01003 NULL, 01004 &StartupInfo, 01005 &ProcessInformation); 01006 01007 /* Free the command line buffer */ 01008 RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine); 01009 01010 if (!ProcessStatus) 01011 { 01012 /* Creating process failed, return right error code */ 01013 Error = GetLastError(); 01014 switch(Error) 01015 { 01016 case ERROR_BAD_EXE_FORMAT: 01017 return ERROR_BAD_FORMAT; 01018 01019 case ERROR_FILE_NOT_FOUND: 01020 case ERROR_PATH_NOT_FOUND: 01021 return Error; 01022 } 01023 01024 /* Return 0 otherwise */ 01025 return 0; 01026 } 01027 01028 /* Wait up to 30 seconds for the process to become idle */ 01029 if (UserWaitForInputIdleRoutine) 01030 { 01031 UserWaitForInputIdleRoutine(ProcessInformation.hProcess, 30000); 01032 } 01033 01034 /* Close handles */ 01035 NtClose(ProcessInformation.hThread); 01036 NtClose(ProcessInformation.hProcess); 01037 01038 /* Return magic success value (33) */ 01039 return 33; 01040 } 01041 01042 /* The path was not found, create an ansi string from 01043 the module name and convert it to unicode */ 01044 RtlInitAnsiString(&AnsiStr, lpModuleName); 01045 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr,&AnsiStr,TRUE))) 01046 return ERROR_FILE_NOT_FOUND; 01047 01048 /* Determine path type */ 01049 PathType = RtlDetermineDosPathNameType_U(UnicStr.Buffer); 01050 01051 /* Free the unicode module name */ 01052 RtlFreeUnicodeString(&UnicStr); 01053 01054 /* If it's a relative path, return file not found */ 01055 if (PathType == RtlPathTypeRelative) 01056 return ERROR_FILE_NOT_FOUND; 01057 01058 /* If not, try to open it */ 01059 Handle = CreateFile(lpModuleName, 01060 GENERIC_READ, 01061 FILE_SHARE_READ | FILE_SHARE_WRITE, 01062 NULL, 01063 OPEN_EXISTING, 01064 FILE_ATTRIBUTE_NORMAL, 01065 NULL); 01066 01067 if (Handle != INVALID_HANDLE_VALUE) 01068 { 01069 /* Opening file succeeded for some reason, close the handle and return file not found anyway */ 01070 CloseHandle(Handle); 01071 return ERROR_FILE_NOT_FOUND; 01072 } 01073 01074 /* Return last error which CreateFile set during an attempt to open it */ 01075 return GetLastError(); 01076 } 01077 01078 /* 01079 * @unimplemented 01080 */ 01081 FARPROC WINAPI DelayLoadFailureHook(LPCSTR pszDllName, LPCSTR pszProcName) 01082 { 01083 STUB; 01084 return NULL; 01085 } 01086 01087 /* 01088 * @unimplemented 01089 */ 01090 BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL, 01091 LPSTR lpszInitName, LPSTR lpszProcName, 01092 FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack, 01093 LPVOID lpBuff ) 01094 { 01095 STUB; 01096 return 0; 01097 } 01098 01099 /* 01100 * @unimplemented 01101 */ 01102 VOID WINAPI UTUnRegister( HMODULE hModule ) 01103 { 01104 STUB; 01105 } 01106 01107 /* 01108 * @unimplemented 01109 */ 01110 BOOL 01111 WINAPI 01112 BaseQueryModuleData(IN LPSTR ModuleName, 01113 IN LPSTR Unknown, 01114 IN PVOID Unknown2, 01115 IN PVOID Unknown3, 01116 IN PVOID Unknown4) 01117 { 01118 DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n", 01119 ModuleName, 01120 Unknown, 01121 Unknown2, 01122 Unknown3, 01123 Unknown4); 01124 return FALSE; 01125 } 01126 01127 /* 01128 * @unimplemented 01129 */ 01130 NTSTATUS 01131 WINAPI 01132 BaseProcessInitPostImport(VOID) 01133 { 01134 /* FIXME: Initialize TS pointers */ 01135 return STATUS_SUCCESS; 01136 } 01137 01138 /* EOF */ Generated on Sun May 27 2012 04:19:04 for ReactOS by
1.7.6.1
|