Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenldrutils.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS NT User-Mode Library 00004 * FILE: dll/ntdll/ldr/ldrutils.c 00005 * PURPOSE: Internal Loader Utility Functions 00006 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) 00007 * Aleksey Bragin (aleksey@reactos.org) 00008 */ 00009 00010 /* INCLUDES *****************************************************************/ 00011 00012 #include <ntdll.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS *******************************************************************/ 00017 00018 PLDR_DATA_TABLE_ENTRY LdrpLoadedDllHandleCache, LdrpGetModuleHandleCache; 00019 BOOLEAN g_ShimsEnabled; 00020 00021 /* FUNCTIONS *****************************************************************/ 00022 00023 /* NOTE: Remove those two once our actctx support becomes better */ 00024 NTSTATUS create_module_activation_context( LDR_DATA_TABLE_ENTRY *module ) 00025 { 00026 NTSTATUS status; 00027 LDR_RESOURCE_INFO info; 00028 IMAGE_RESOURCE_DATA_ENTRY *entry; 00029 00030 info.Type = (ULONG)RT_MANIFEST; 00031 info.Name = (ULONG)ISOLATIONAWARE_MANIFEST_RESOURCE_ID; 00032 info.Language = 0; 00033 if (!(status = LdrFindResource_U( module->DllBase, &info, 3, &entry ))) 00034 { 00035 ACTCTXW ctx; 00036 ctx.cbSize = sizeof(ctx); 00037 ctx.lpSource = NULL; 00038 ctx.dwFlags = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID; 00039 ctx.hModule = module->DllBase; 00040 ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID; 00041 status = RtlCreateActivationContext( &module->EntryPointActivationContext, &ctx ); 00042 } 00043 return status; 00044 } 00045 00046 NTSTATUS find_actctx_dll( LPCWSTR libname, WCHAR *fullname ) 00047 { 00048 static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'}; 00049 static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0}; 00050 00051 ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info; 00052 ACTCTX_SECTION_KEYED_DATA data; 00053 UNICODE_STRING nameW; 00054 NTSTATUS status; 00055 SIZE_T needed, size = 1024; 00056 WCHAR *p; 00057 00058 RtlInitUnicodeString( &nameW, libname ); 00059 data.cbSize = sizeof(data); 00060 status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL, 00061 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, 00062 &nameW, &data ); 00063 if (status != STATUS_SUCCESS) return status; 00064 00065 for (;;) 00066 { 00067 if (!(info = RtlAllocateHeap( RtlGetProcessHeap(), 0, size ))) 00068 { 00069 status = STATUS_NO_MEMORY; 00070 goto done; 00071 } 00072 status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex, 00073 AssemblyDetailedInformationInActivationContext, 00074 info, size, &needed ); 00075 if (status == STATUS_SUCCESS) break; 00076 if (status != STATUS_BUFFER_TOO_SMALL) goto done; 00077 RtlFreeHeap( RtlGetProcessHeap(), 0, info ); 00078 size = needed; 00079 } 00080 00081 DPRINT("manifestpath === %S\n", info->lpAssemblyManifestPath); 00082 DPRINT("DirectoryName === %S\n", info->lpAssemblyDirectoryName); 00083 if (!info->lpAssemblyManifestPath || !info->lpAssemblyDirectoryName) 00084 { 00085 status = STATUS_SXS_KEY_NOT_FOUND; 00086 goto done; 00087 } 00088 00089 if ((p = wcsrchr( info->lpAssemblyManifestPath, '\\' ))) 00090 { 00091 DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); 00092 00093 p++; 00094 if (_wcsnicmp( p, info->lpAssemblyDirectoryName, dirlen ) || wcsicmp( p + dirlen, dotManifestW )) 00095 { 00096 /* manifest name does not match directory name, so it's not a global 00097 * windows/winsxs manifest; use the manifest directory name instead */ 00098 dirlen = p - info->lpAssemblyManifestPath; 00099 needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length; 00100 00101 p = fullname; 00102 /*if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) 00103 { 00104 status = STATUS_NO_MEMORY; 00105 goto done; 00106 }*/ 00107 memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) ); 00108 p += dirlen; 00109 wcscpy( p, libname ); 00110 goto done; 00111 } 00112 } 00113 00114 needed = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR) + 00115 sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength + nameW.Length + 2*sizeof(WCHAR)); 00116 00117 p = fullname; 00118 //if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) 00119 //{ 00120 //status = STATUS_NO_MEMORY; 00121 //goto done; 00122 //} 00123 wcscpy( p, SharedUserData->NtSystemRoot ); 00124 p += wcslen(p); 00125 memcpy( p, winsxsW, sizeof(winsxsW) ); 00126 p += sizeof(winsxsW) / sizeof(WCHAR); 00127 memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength ); 00128 p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR); 00129 *p++ = '\\'; 00130 wcscpy( p, libname ); 00131 00132 done: 00133 RtlFreeHeap( RtlGetProcessHeap(), 0, info ); 00134 RtlReleaseActivationContext( data.hActCtx ); 00135 DPRINT("%S\n", fullname); 00136 return status; 00137 } 00138 00139 00140 NTSTATUS 00141 NTAPI 00142 LdrpAllocateUnicodeString(IN OUT PUNICODE_STRING StringOut, 00143 IN ULONG Length) 00144 { 00145 /* Sanity checks */ 00146 ASSERT(StringOut); 00147 ASSERT(Length <= UNICODE_STRING_MAX_BYTES); 00148 00149 /* Assume failure */ 00150 StringOut->Length = 0; 00151 00152 /* Make sure it's not mis-aligned */ 00153 if (Length & 1) 00154 { 00155 /* Fail */ 00156 StringOut->Buffer = NULL; 00157 StringOut->MaximumLength = 0; 00158 return STATUS_INVALID_PARAMETER; 00159 } 00160 00161 /* Allocate the string*/ 00162 StringOut->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00163 0, 00164 StringOut->Length + sizeof(WCHAR)); 00165 if (!StringOut->Buffer) 00166 { 00167 /* Fail */ 00168 StringOut->MaximumLength = 0; 00169 return STATUS_NO_MEMORY; 00170 } 00171 00172 /* Null-terminate it */ 00173 StringOut->Buffer[StringOut->Length / sizeof(WCHAR)] = UNICODE_NULL; 00174 00175 /* Check if this is a maximum-sized string */ 00176 if (StringOut->Length != UNICODE_STRING_MAX_BYTES) 00177 { 00178 /* It's not, so set the maximum length to be one char more */ 00179 StringOut->MaximumLength = StringOut->Length + sizeof(UNICODE_NULL); 00180 } 00181 else 00182 { 00183 /* The length is already the maximum possible */ 00184 StringOut->MaximumLength = UNICODE_STRING_MAX_BYTES; 00185 } 00186 00187 /* Return success */ 00188 return STATUS_SUCCESS; 00189 } 00190 00191 VOID 00192 NTAPI 00193 LdrpFreeUnicodeString(IN PUNICODE_STRING StringIn) 00194 { 00195 ASSERT(StringIn != NULL); 00196 00197 /* If Buffer is not NULL - free it */ 00198 if (StringIn->Buffer) 00199 { 00200 RtlFreeHeap(RtlGetProcessHeap(), 0, StringIn->Buffer); 00201 } 00202 00203 /* Zero it out */ 00204 RtlInitEmptyUnicodeString(StringIn, NULL, 0); 00205 } 00206 BOOLEAN 00207 NTAPI 00208 LdrpCallInitRoutine(IN PDLL_INIT_ROUTINE EntryPoint, 00209 IN PVOID BaseAddress, 00210 IN ULONG Reason, 00211 IN PVOID Context) 00212 { 00213 /* Call the entry */ 00214 return EntryPoint(BaseAddress, Reason, Context); 00215 } 00216 00217 /* NOTE: This function is broken */ 00218 VOID 00219 NTAPI 00220 LdrpUpdateLoadCount3(IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00221 IN ULONG Flags, 00222 OUT PUNICODE_STRING UpdateString) 00223 { 00224 PIMAGE_BOUND_FORWARDER_REF NewImportForwarder; 00225 PIMAGE_BOUND_IMPORT_DESCRIPTOR BoundEntry; 00226 PIMAGE_IMPORT_DESCRIPTOR ImportEntry; 00227 PIMAGE_THUNK_DATA FirstThunk; 00228 PLDR_DATA_TABLE_ENTRY Entry; 00229 PUNICODE_STRING ImportNameUnic; 00230 ANSI_STRING ImportNameAnsi; 00231 LPSTR ImportName; 00232 ULONG ImportSize; 00233 NTSTATUS Status; 00234 ULONG i; 00235 00236 /* Check the action we need to perform */ 00237 if (Flags == LDRP_UPDATE_REFCOUNT) 00238 { 00239 /* Make sure entry is not being loaded already */ 00240 if (LdrEntry->Flags & LDRP_LOAD_IN_PROGRESS) 00241 return; 00242 00243 LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS; 00244 } 00245 else if (Flags == LDRP_UPDATE_DEREFCOUNT) 00246 { 00247 /* Make sure the entry is not being unloaded already */ 00248 if (LdrEntry->Flags & LDRP_UNLOAD_IN_PROGRESS) 00249 return; 00250 00251 LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS; 00252 } 00253 00254 /* Go through all bound DLLs and dereference them */ 00255 ImportNameUnic = &NtCurrentTeb()->StaticUnicodeString; 00256 00257 /* Try to get the new import entry */ 00258 BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase, 00259 TRUE, 00260 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT, 00261 &ImportSize); 00262 00263 if (BoundEntry) 00264 { 00265 /* Set entry flags if refing/derefing */ 00266 if (Flags == LDRP_UPDATE_REFCOUNT) 00267 LdrEntry->Flags |= LDRP_LOAD_IN_PROGRESS; 00268 else if (Flags == LDRP_UPDATE_DEREFCOUNT) 00269 LdrEntry->Flags |= LDRP_UNLOAD_IN_PROGRESS; 00270 00271 while (BoundEntry->OffsetModuleName) 00272 { 00273 /* Get pointer to the current import name */ 00274 ImportName = (PCHAR)BoundEntry + BoundEntry->OffsetModuleName; 00275 00276 RtlInitAnsiString(&ImportNameAnsi, ImportName); 00277 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); 00278 00279 if (NT_SUCCESS(Status)) 00280 { 00281 if (LdrpCheckForLoadedDll(NULL, 00282 ImportNameUnic, 00283 TRUE, 00284 FALSE, 00285 &Entry)) 00286 { 00287 if (Entry->LoadCount != 0xFFFF) 00288 { 00289 /* Perform the required action */ 00290 switch (Flags) 00291 { 00292 case LDRP_UPDATE_REFCOUNT: 00293 Entry->LoadCount++; 00294 break; 00295 case LDRP_UPDATE_DEREFCOUNT: 00296 Entry->LoadCount--; 00297 break; 00298 case LDRP_UPDATE_PIN: 00299 Entry->LoadCount = 0xFFFF; 00300 break; 00301 } 00302 00303 /* Show snaps */ 00304 if (ShowSnaps) 00305 { 00306 DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); 00307 } 00308 } 00309 00310 /* Recurse into this entry */ 00311 LdrpUpdateLoadCount3(Entry, Flags, UpdateString); 00312 } 00313 } 00314 00315 /* Go through forwarders */ 00316 NewImportForwarder = (PIMAGE_BOUND_FORWARDER_REF)(BoundEntry + 1); 00317 for (i=0; i<BoundEntry->NumberOfModuleForwarderRefs; i++) 00318 { 00319 ImportName = (PCHAR)BoundEntry + NewImportForwarder->OffsetModuleName; 00320 00321 RtlInitAnsiString(&ImportNameAnsi, ImportName); 00322 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); 00323 if (NT_SUCCESS(Status)) 00324 { 00325 if (LdrpCheckForLoadedDll(NULL, 00326 ImportNameUnic, 00327 TRUE, 00328 FALSE, 00329 &Entry)) 00330 { 00331 if (Entry->LoadCount != 0xFFFF) 00332 { 00333 /* Perform the required action */ 00334 switch (Flags) 00335 { 00336 case LDRP_UPDATE_REFCOUNT: 00337 Entry->LoadCount++; 00338 break; 00339 case LDRP_UPDATE_DEREFCOUNT: 00340 Entry->LoadCount--; 00341 break; 00342 case LDRP_UPDATE_PIN: 00343 Entry->LoadCount = 0xFFFF; 00344 break; 00345 } 00346 00347 /* Show snaps */ 00348 if (ShowSnaps) 00349 { 00350 DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); 00351 } 00352 } 00353 00354 /* Recurse into this entry */ 00355 LdrpUpdateLoadCount3(Entry, Flags, UpdateString); 00356 } 00357 } 00358 00359 NewImportForwarder++; 00360 } 00361 00362 BoundEntry = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)NewImportForwarder; 00363 } 00364 00365 /* We're done */ 00366 return; 00367 } 00368 00369 /* Check oldstyle import descriptor */ 00370 ImportEntry = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(LdrEntry->DllBase, 00371 TRUE, 00372 IMAGE_DIRECTORY_ENTRY_IMPORT, 00373 &ImportSize); 00374 if (ImportEntry) 00375 { 00376 /* There is old one, so go through its entries */ 00377 while (ImportEntry->Name && ImportEntry->FirstThunk) 00378 { 00379 FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->FirstThunk); 00380 00381 /* Skip this entry if needed */ 00382 if (!FirstThunk->u1.Function) 00383 { 00384 ImportEntry++; 00385 continue; 00386 } 00387 00388 ImportName = (PSZ)((ULONG_PTR)LdrEntry->DllBase + ImportEntry->Name); 00389 00390 RtlInitAnsiString(&ImportNameAnsi, ImportName); 00391 Status = RtlAnsiStringToUnicodeString(ImportNameUnic, &ImportNameAnsi, FALSE); 00392 if (NT_SUCCESS(Status)) 00393 { 00394 if (LdrpCheckForLoadedDll(NULL, 00395 ImportNameUnic, 00396 TRUE, 00397 FALSE, 00398 &Entry)) 00399 { 00400 if (Entry->LoadCount != 0xFFFF) 00401 { 00402 /* Perform the required action */ 00403 switch (Flags) 00404 { 00405 case LDRP_UPDATE_REFCOUNT: 00406 Entry->LoadCount++; 00407 break; 00408 case LDRP_UPDATE_DEREFCOUNT: 00409 Entry->LoadCount--; 00410 break; 00411 case LDRP_UPDATE_PIN: 00412 Entry->LoadCount = 0xFFFF; 00413 break; 00414 } 00415 00416 /* Show snaps */ 00417 if (ShowSnaps) 00418 { 00419 DPRINT1("LDR: Flags %d %wZ (%lx)\n", Flags, ImportNameUnic, Entry->LoadCount); 00420 } 00421 } 00422 00423 /* Recurse */ 00424 LdrpUpdateLoadCount3(Entry, Flags, UpdateString); 00425 } 00426 } 00427 00428 /* Go to the next entry */ 00429 ImportEntry++; 00430 } 00431 } 00432 } 00433 00434 VOID 00435 NTAPI 00436 LdrpUpdateLoadCount2(IN PLDR_DATA_TABLE_ENTRY LdrEntry, 00437 IN ULONG Flags) 00438 { 00439 WCHAR Buffer[MAX_PATH]; 00440 UNICODE_STRING UpdateString; 00441 00442 /* Setup the string and call the extended API */ 00443 RtlInitEmptyUnicodeString(&UpdateString, Buffer, sizeof(Buffer)); 00444 LdrpUpdateLoadCount3(LdrEntry, Flags, &UpdateString); 00445 } 00446 00447 VOID 00448 NTAPI 00449 LdrpCallTlsInitializers(IN PVOID BaseAddress, 00450 IN ULONG Reason) 00451 { 00452 PIMAGE_TLS_DIRECTORY TlsDirectory; 00453 PIMAGE_TLS_CALLBACK *Array, Callback; 00454 ULONG Size; 00455 00456 /* Get the TLS Directory */ 00457 TlsDirectory = RtlImageDirectoryEntryToData(BaseAddress, 00458 TRUE, 00459 IMAGE_DIRECTORY_ENTRY_TLS, 00460 &Size); 00461 00462 /* Protect against invalid pointers */ 00463 _SEH2_TRY 00464 { 00465 /* Make sure it's valid */ 00466 if (TlsDirectory) 00467 { 00468 /* Get the array */ 00469 Array = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks; 00470 if (Array) 00471 { 00472 /* Display debug */ 00473 if (ShowSnaps) 00474 { 00475 DPRINT1("LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p\n", 00476 BaseAddress, TlsDirectory, Array); 00477 } 00478 00479 /* Loop the array */ 00480 while (*Array) 00481 { 00482 /* Get the TLS Entrypoint */ 00483 Callback = *Array++; 00484 00485 /* Display debug */ 00486 if (ShowSnaps) 00487 { 00488 DPRINT1("LDR: Calling Tls Callback Imagebase %p Function %p\n", 00489 BaseAddress, Callback); 00490 } 00491 00492 /* Call it */ 00493 LdrpCallInitRoutine((PDLL_INIT_ROUTINE)Callback, 00494 BaseAddress, 00495 Reason, 00496 NULL); 00497 } 00498 } 00499 } 00500 } 00501 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 00502 { 00503 /* Do nothing */ 00504 } 00505 _SEH2_END; 00506 } 00507 00508 NTSTATUS 00509 NTAPI 00510 LdrpCodeAuthzCheckDllAllowed(IN PUNICODE_STRING FullName, 00511 IN HANDLE DllHandle) 00512 { 00513 /* Not implemented */ 00514 return STATUS_SUCCESS; 00515 } 00516 00517 NTSTATUS 00518 NTAPI 00519 LdrpCreateDllSection(IN PUNICODE_STRING FullName, 00520 IN HANDLE DllHandle, 00521 IN PULONG DllCharacteristics OPTIONAL, 00522 OUT PHANDLE SectionHandle) 00523 { 00524 HANDLE FileHandle; 00525 NTSTATUS Status; 00526 OBJECT_ATTRIBUTES ObjectAttributes; 00527 IO_STATUS_BLOCK IoStatusBlock; 00528 ULONG_PTR HardErrorParameters[1]; 00529 ULONG Response; 00530 SECTION_IMAGE_INFORMATION SectionImageInfo; 00531 00532 /* Check if we don't already have a handle */ 00533 if (!DllHandle) 00534 { 00535 /* Create the object attributes */ 00536 InitializeObjectAttributes(&ObjectAttributes, 00537 FullName, 00538 OBJ_CASE_INSENSITIVE, 00539 NULL, 00540 NULL); 00541 00542 /* Open the DLL */ 00543 Status = NtOpenFile(&FileHandle, 00544 SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA, 00545 &ObjectAttributes, 00546 &IoStatusBlock, 00547 FILE_SHARE_READ | FILE_SHARE_DELETE, 00548 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 00549 00550 /* Check if we failed */ 00551 if (!NT_SUCCESS(Status)) 00552 { 00553 /* Attempt to open for execute only */ 00554 Status = NtOpenFile(&FileHandle, 00555 SYNCHRONIZE | FILE_EXECUTE, 00556 &ObjectAttributes, 00557 &IoStatusBlock, 00558 FILE_SHARE_READ | FILE_SHARE_DELETE, 00559 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 00560 00561 /* Check if this failed too */ 00562 if (!NT_SUCCESS(Status)) 00563 { 00564 /* Show debug message */ 00565 if (ShowSnaps) 00566 { 00567 DPRINT1("LDR: LdrpCreateDllSection - NtOpenFile failed; status = %x\n", 00568 Status); 00569 } 00570 00571 /* Make sure to return an expected status code */ 00572 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) 00573 { 00574 /* Callers expect this instead */ 00575 Status = STATUS_DLL_NOT_FOUND; 00576 } 00577 00578 /* Return an empty section handle */ 00579 *SectionHandle = NULL; 00580 return Status; 00581 } 00582 } 00583 } 00584 else 00585 { 00586 /* Use the handle we already have */ 00587 FileHandle = DllHandle; 00588 } 00589 00590 /* Create a section for the DLL */ 00591 Status = NtCreateSection(SectionHandle, 00592 SECTION_MAP_READ | SECTION_MAP_EXECUTE | 00593 SECTION_MAP_WRITE | SECTION_QUERY, 00594 NULL, 00595 NULL, 00596 PAGE_EXECUTE, 00597 SEC_IMAGE, 00598 FileHandle); 00599 00600 /* If mapping failed, raise a hard error */ 00601 if (!NT_SUCCESS(Status)) 00602 { 00603 /* Forget the handle */ 00604 *SectionHandle = NULL; 00605 00606 /* Give the DLL name */ 00607 HardErrorParameters[0] = (ULONG_PTR)FullName; 00608 00609 /* Raise the error */ 00610 ZwRaiseHardError(STATUS_INVALID_IMAGE_FORMAT, 00611 1, 00612 1, 00613 HardErrorParameters, 00614 OptionOk, 00615 &Response); 00616 00617 /* Increment the error count */ 00618 if (LdrpInLdrInit) LdrpFatalHardErrorCount++; 00619 } 00620 00621 /* Check for Safer restrictions */ 00622 if (DllCharacteristics && 00623 !(*DllCharacteristics & IMAGE_FILE_SYSTEM)) 00624 { 00625 /* Make sure it's executable */ 00626 Status = ZwQuerySection(*SectionHandle, 00627 SectionImageInformation, 00628 &SectionImageInfo, 00629 sizeof(SECTION_IMAGE_INFORMATION), 00630 NULL); 00631 if (NT_SUCCESS(Status)) 00632 { 00633 /* Bypass the check for .NET images */ 00634 if (!(SectionImageInfo.LoaderFlags & IMAGE_LOADER_FLAGS_COMPLUS)) 00635 { 00636 /* Check with Safer */ 00637 Status = LdrpCodeAuthzCheckDllAllowed(FullName, DllHandle); 00638 if (!NT_SUCCESS(Status) && (Status != STATUS_NOT_FOUND)) 00639 { 00640 /* Show debug message */ 00641 if (ShowSnaps) 00642 { 00643 DPRINT1("LDR: Loading of (%wZ) blocked by Winsafer\n", 00644 &FullName); 00645 } 00646 00647 /* Failure case, close section handle */ 00648 NtClose(*SectionHandle); 00649 *SectionHandle = NULL; 00650 } 00651 } 00652 } 00653 else 00654 { 00655 /* Failure case, close section handle */ 00656 NtClose(*SectionHandle); 00657 *SectionHandle = NULL; 00658 } 00659 } 00660 00661 /* Close the file handle, we don't need it */ 00662 NtClose(FileHandle); 00663 00664 /* Return status */ 00665 return Status; 00666 } 00667 00668 /* NOTE: This function is totally b0rked and doesn't handle the parameters/functionality it should */ 00669 BOOLEAN 00670 NTAPI 00671 LdrpResolveDllName(PWSTR DllPath, 00672 PWSTR DllName, 00673 PUNICODE_STRING FullDllName, 00674 PUNICODE_STRING BaseDllName) 00675 { 00676 PWCHAR NameBuffer, p1, p2 = 0; 00677 ULONG Length; 00678 ULONG BufSize = 500; 00679 NTSTATUS Status; 00680 00681 /* Allocate space for full DLL name */ 00682 FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufSize + sizeof(UNICODE_NULL)); 00683 if (!FullDllName->Buffer) return FALSE; 00684 00685 Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, 00686 DllName, 00687 NULL, 00688 BufSize, 00689 FullDllName->Buffer, 00690 &BaseDllName->Buffer); 00691 00692 if (!Length || Length > BufSize) 00693 { 00694 /* HACK: Try to find active context dll */ 00695 Status = find_actctx_dll(DllName, FullDllName->Buffer); 00696 if(Status == STATUS_SUCCESS) 00697 { 00698 Length = wcslen(FullDllName->Buffer) * sizeof(WCHAR); 00699 DPRINT1("found %S for %S\n", FullDllName->Buffer, DllName); 00700 } 00701 else 00702 { 00703 /* NOTE: This code should remain after removing the hack */ 00704 if (ShowSnaps) 00705 { 00706 DPRINT1("LDR: LdrResolveDllName - Unable to find "); 00707 DPRINT1("%ws from %ws\n", DllName, DllPath ? DllPath : LdrpDefaultPath.Buffer); 00708 } 00709 00710 RtlFreeUnicodeString(FullDllName); 00711 return FALSE; 00712 } 00713 } 00714 00715 /* Construct full DLL name */ 00716 FullDllName->Length = Length; 00717 FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL); 00718 00719 /* Allocate a new buffer */ 00720 NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength); 00721 if (!NameBuffer) 00722 { 00723 RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); 00724 return FALSE; 00725 } 00726 00727 /* Copy over the contents from the previous one and free it */ 00728 RtlCopyMemory(NameBuffer, FullDllName->Buffer, FullDllName->MaximumLength); 00729 RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); 00730 FullDllName->Buffer = NameBuffer; 00731 00732 /* Find last backslash */ 00733 p1 = FullDllName->Buffer; 00734 while (*p1) 00735 { 00736 if (*p1++ == L'\\') 00737 { 00738 p2 = p1; 00739 } 00740 } 00741 00742 /* If found, set p1 to it, otherwise p1 points to the beginning of DllName */ 00743 if (p2) 00744 p1 = p2; 00745 else 00746 p1 = DllName; 00747 00748 p2 = p1; 00749 00750 /* Calculate remaining length */ 00751 while (*p1) ++p1; 00752 00753 /* Construct base DLL name */ 00754 BaseDllName->Length = (ULONG_PTR)p1 - (ULONG_PTR)p2; 00755 BaseDllName->MaximumLength = BaseDllName->Length + sizeof(UNICODE_NULL); 00756 BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, BaseDllName->MaximumLength); 00757 00758 if (!BaseDllName->Buffer) 00759 { 00760 RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); 00761 return FALSE; 00762 } 00763 00764 /* Copy base dll name to the new buffer */ 00765 RtlMoveMemory(BaseDllName->Buffer, 00766 p2, 00767 BaseDllName->Length); 00768 00769 /* Null-terminate the string */ 00770 BaseDllName->Buffer[BaseDllName->Length / sizeof(WCHAR)] = 0; 00771 00772 return TRUE; 00773 } 00774 00775 PVOID 00776 NTAPI 00777 LdrpFetchAddressOfEntryPoint(IN PVOID ImageBase) 00778 { 00779 PIMAGE_NT_HEADERS NtHeaders; 00780 ULONG_PTR EntryPoint = 0; 00781 00782 /* Get entry point offset from NT headers */ 00783 NtHeaders = RtlImageNtHeader(ImageBase); 00784 if (NtHeaders) 00785 { 00786 /* Add image base */ 00787 EntryPoint = NtHeaders->OptionalHeader.AddressOfEntryPoint; 00788 if (EntryPoint) EntryPoint += (ULONG_PTR)ImageBase; 00789 } 00790 00791 /* Return calculated pointer (or zero in case of failure) */ 00792 return (PVOID)EntryPoint; 00793 } 00794 00795 /* NOTE: This function is partially missing SxS */ 00796 NTSTATUS 00797 NTAPI 00798 LdrpCheckForKnownDll(PWSTR DllName, 00799 PUNICODE_STRING FullDllName, 00800 PUNICODE_STRING BaseDllName, 00801 HANDLE *SectionHandle) 00802 { 00803 OBJECT_ATTRIBUTES ObjectAttributes; 00804 HANDLE Section = NULL; 00805 UNICODE_STRING DllNameUnic; 00806 NTSTATUS Status; 00807 PCHAR p1; 00808 PWCHAR p2; 00809 00810 /* Zero initialize provided parameters */ 00811 if (SectionHandle) *SectionHandle = 0; 00812 00813 if (FullDllName) 00814 { 00815 FullDllName->Length = 0; 00816 FullDllName->MaximumLength = 0; 00817 FullDllName->Buffer = NULL; 00818 } 00819 00820 if (BaseDllName) 00821 { 00822 BaseDllName->Length = 0; 00823 BaseDllName->MaximumLength = 0; 00824 BaseDllName->Buffer = NULL; 00825 } 00826 00827 /* If any of these three params are missing then fail */ 00828 if (!SectionHandle || !FullDllName || !BaseDllName) 00829 return STATUS_INVALID_PARAMETER; 00830 00831 /* Check the Loader Lock */ 00832 LdrpEnsureLoaderLockIsHeld(); 00833 00834 /* Upgrade DllName to a unicode string */ 00835 RtlInitUnicodeString(&DllNameUnic, DllName); 00836 00837 /* FIXME: Missing RtlComputePrivatizedDllName_U related functionality */ 00838 00839 /* Get the activation context */ 00840 Status = RtlFindActivationContextSectionString(0, 00841 NULL, 00842 ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION, 00843 &DllNameUnic, 00844 NULL); 00845 00846 /* Check if it's a SxS or not */ 00847 if (Status == STATUS_SXS_SECTION_NOT_FOUND || 00848 Status == STATUS_SXS_KEY_NOT_FOUND) 00849 { 00850 /* NOTE: Here it's beneficial to allocate one big unicode string 00851 using LdrpAllocateUnicodeString instead of fragmenting the heap 00852 with two allocations as it's done now. */ 00853 00854 /* Set up BaseDllName */ 00855 BaseDllName->Length = DllNameUnic.Length; 00856 BaseDllName->MaximumLength = DllNameUnic.MaximumLength; 00857 BaseDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 00858 0, 00859 DllNameUnic.MaximumLength); 00860 if (!BaseDllName->Buffer) 00861 { 00862 Status = STATUS_NO_MEMORY; 00863 goto Failure; 00864 } 00865 00866 /* Copy the contents there */ 00867 RtlMoveMemory(BaseDllName->Buffer, DllNameUnic.Buffer, DllNameUnic.MaximumLength); 00868 00869 /* Set up FullDllName */ 00870 FullDllName->Length = LdrpKnownDllPath.Length + BaseDllName->Length + sizeof(WCHAR); 00871 FullDllName->MaximumLength = FullDllName->Length + sizeof(UNICODE_NULL); 00872 FullDllName->Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, FullDllName->MaximumLength); 00873 if (!FullDllName->Buffer) 00874 { 00875 Status = STATUS_NO_MEMORY; 00876 goto Failure; 00877 } 00878 00879 RtlMoveMemory(FullDllName->Buffer, LdrpKnownDllPath.Buffer, LdrpKnownDllPath.Length); 00880 00881 /* Put a slash there */ 00882 p1 = (PCHAR)FullDllName->Buffer + LdrpKnownDllPath.Length; 00883 p2 = (PWCHAR)p1; 00884 *p2++ = (WCHAR)'\\'; 00885 p1 = (PCHAR)p2; 00886 00887 /* Set up DllNameUnic for a relative path */ 00888 DllNameUnic.Buffer = (PWSTR)p1; 00889 DllNameUnic.Length = BaseDllName->Length; 00890 DllNameUnic.MaximumLength = DllNameUnic.Length + sizeof(UNICODE_NULL); 00891 00892 /* Copy the contents */ 00893 RtlMoveMemory(p1, BaseDllName->Buffer, BaseDllName->MaximumLength); 00894 00895 /* There are all names, init attributes and open the section */ 00896 InitializeObjectAttributes(&ObjectAttributes, 00897 &DllNameUnic, 00898 OBJ_CASE_INSENSITIVE, 00899 LdrpKnownDllObjectDirectory, 00900 NULL); 00901 00902 Status = NtOpenSection(&Section, 00903 SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_MAP_WRITE, 00904 &ObjectAttributes); 00905 if (!NT_SUCCESS(Status)) 00906 { 00907 /* Clear status in case it was just not found */ 00908 if (Status == STATUS_OBJECT_NAME_NOT_FOUND) Status = STATUS_SUCCESS; 00909 goto Failure; 00910 } 00911 00912 /* Pass section handle to the caller and return success */ 00913 *SectionHandle = Section; 00914 return STATUS_SUCCESS; 00915 } 00916 00917 Failure: 00918 /* Close section object if it was opened */ 00919 if (Section) NtClose(Section); 00920 00921 /* Free string resources */ 00922 if (BaseDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, BaseDllName->Buffer); 00923 if (FullDllName->Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FullDllName->Buffer); 00924 00925 /* Return status */ 00926 return Status; 00927 } 00928 00929 NTSTATUS 00930 NTAPI 00931 LdrpSetProtection(PVOID ViewBase, 00932 BOOLEAN Restore) 00933 { 00934 PIMAGE_NT_HEADERS NtHeaders; 00935 PIMAGE_SECTION_HEADER Section; 00936 NTSTATUS Status; 00937 PVOID SectionBase; 00938 SIZE_T SectionSize; 00939 ULONG NewProtection, OldProtection, i; 00940 00941 /* Get the NT headers */ 00942 NtHeaders = RtlImageNtHeader(ViewBase); 00943 if (!NtHeaders) return STATUS_INVALID_IMAGE_FORMAT; 00944 00945 /* Compute address of the first section header */ 00946 Section = IMAGE_FIRST_SECTION(NtHeaders); 00947 00948 /* Go through all sections */ 00949 for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++) 00950 { 00951 /* Check for read-only non-zero section */ 00952 if ((Section->SizeOfRawData) && 00953 !(Section->Characteristics & IMAGE_SCN_MEM_WRITE)) 00954 { 00955 /* Check if we are setting or restoring protection */ 00956 if (Restore) 00957 { 00958 /* Set it to either EXECUTE or READONLY */ 00959 if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE) 00960 { 00961 NewProtection = PAGE_EXECUTE; 00962 } 00963 else 00964 { 00965 NewProtection = PAGE_READONLY; 00966 } 00967 00968 /* Add PAGE_NOCACHE if needed */ 00969 if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED) 00970 { 00971 NewProtection |= PAGE_NOCACHE; 00972 } 00973 } 00974 else 00975 { 00976 /* Enable write access */ 00977 NewProtection = PAGE_READWRITE; 00978 } 00979 00980 /* Get the section VA */ 00981 SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress); 00982 SectionSize = Section->SizeOfRawData; 00983 if (SectionSize) 00984 { 00985 /* Set protection */ 00986 Status = ZwProtectVirtualMemory(NtCurrentProcess(), 00987 &SectionBase, 00988 &SectionSize, 00989 NewProtection, 00990 &OldProtection); 00991 if (!NT_SUCCESS(Status)) return Status; 00992 } 00993 } 00994 00995 /* Move to the next section */ 00996 Section++; 00997 } 00998 00999 /* Flush instruction cache if necessary */ 01000 if (Restore) ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0); 01001 return STATUS_SUCCESS; 01002 } 01003 01004 /* NOTE: Not yet reviewed */ 01005 NTSTATUS 01006 NTAPI 01007 LdrpMapDll(IN PWSTR SearchPath OPTIONAL, 01008 IN PWSTR DllPath2, 01009 IN PWSTR DllName OPTIONAL, 01010 IN PULONG DllCharacteristics, 01011 IN BOOLEAN Static, 01012 IN BOOLEAN Redirect, 01013 OUT PLDR_DATA_TABLE_ENTRY *DataTableEntry) 01014 { 01015 PTEB Teb = NtCurrentTeb(); 01016 PPEB Peb = NtCurrentPeb(); 01017 PWCHAR p1 = DllName; 01018 WCHAR TempChar; 01019 BOOLEAN KnownDll = FALSE; 01020 UNICODE_STRING FullDllName, BaseDllName; 01021 HANDLE SectionHandle = NULL, DllHandle = 0; 01022 UNICODE_STRING NtPathDllName; 01023 ULONG_PTR HardErrorParameters[2]; 01024 UNICODE_STRING HardErrorDllName, HardErrorDllPath; 01025 ULONG Response; 01026 SIZE_T ViewSize = 0; 01027 PVOID ViewBase = NULL; 01028 PVOID ArbitraryUserPointer; 01029 PIMAGE_NT_HEADERS NtHeaders; 01030 NTSTATUS HardErrorStatus, Status; 01031 BOOLEAN OverlapDllFound = FALSE; 01032 ULONG_PTR ImageBase, ImageEnd; 01033 PLIST_ENTRY ListHead, NextEntry; 01034 PLDR_DATA_TABLE_ENTRY CandidateEntry, LdrEntry; 01035 ULONG_PTR CandidateBase, CandidateEnd; 01036 UNICODE_STRING OverlapDll; 01037 BOOLEAN RelocatableDll = TRUE; 01038 UNICODE_STRING IllegalDll; 01039 PVOID RelocData; 01040 ULONG RelocDataSize = 0; 01041 01042 // FIXME: AppCompat stuff is missing 01043 01044 if (ShowSnaps) 01045 { 01046 DPRINT1("LDR: LdrpMapDll: Image Name %ws, Search Path %ws\n", 01047 DllName, 01048 SearchPath ? SearchPath : L""); 01049 } 01050 01051 /* Check if we have a known dll directory */ 01052 if (LdrpKnownDllObjectDirectory) 01053 { 01054 /* Check if the path is full */ 01055 while (*p1) 01056 { 01057 TempChar = *p1++; 01058 if (TempChar == '\\' || TempChar == '/' ) 01059 { 01060 /* Complete path, don't do Known Dll lookup */ 01061 goto SkipCheck; 01062 } 01063 } 01064 01065 /* Try to find a Known DLL */ 01066 Status = LdrpCheckForKnownDll(DllName, 01067 &FullDllName, 01068 &BaseDllName, 01069 &SectionHandle); 01070 01071 if (!NT_SUCCESS(Status) && (Status != STATUS_DLL_NOT_FOUND)) 01072 { 01073 /* Failure */ 01074 DbgPrintEx(81, //DPFLTR_LDR_ID, 01075 0, 01076 "LDR: %s - call to LdrpCheckForKnownDll(\"%ws\", ...) failed with status %x\n", 01077 __FUNCTION__, 01078 DllName, 01079 Status); 01080 01081 return Status; 01082 } 01083 } 01084 01085 SkipCheck: 01086 01087 /* Check if the Known DLL Check returned something */ 01088 if (!SectionHandle) 01089 { 01090 /* It didn't, so try to resolve the name now */ 01091 if (LdrpResolveDllName(SearchPath, 01092 DllName, 01093 &FullDllName, 01094 &BaseDllName)) 01095 { 01096 /* Got a name, display a message */ 01097 if (ShowSnaps) 01098 { 01099 DPRINT1("LDR: Loading (%s) %wZ\n", 01100 Static ? "STATIC" : "DYNAMIC", 01101 &FullDllName); 01102 } 01103 01104 /* Convert to NT Name */ 01105 if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer, 01106 &NtPathDllName, 01107 NULL, 01108 NULL)) 01109 { 01110 /* Path was invalid */ 01111 return STATUS_OBJECT_PATH_SYNTAX_BAD; 01112 } 01113 01114 /* Create a section for this dLL */ 01115 Status = LdrpCreateDllSection(&NtPathDllName, 01116 DllHandle, 01117 DllCharacteristics, 01118 &SectionHandle); 01119 01120 /* Free the NT Name */ 01121 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer); 01122 01123 /* If we failed */ 01124 if (!NT_SUCCESS(Status)) 01125 { 01126 /* Free the name strings and return */ 01127 RtlFreeUnicodeString(&FullDllName); 01128 RtlFreeUnicodeString(&BaseDllName); 01129 return Status; 01130 } 01131 } 01132 else 01133 { 01134 /* We couldn't resolve the name, is this a static load? */ 01135 if (Static) 01136 { 01137 /* 01138 * This is BAD! Static loads are CRITICAL. Bugcheck! 01139 * Initialize the strings for the error 01140 */ 01141 RtlInitUnicodeString(&HardErrorDllName, DllName); 01142 RtlInitUnicodeString(&HardErrorDllPath, 01143 DllPath2 ? DllPath2 : LdrpDefaultPath.Buffer); 01144 01145 /* Set them as error parameters */ 01146 HardErrorParameters[0] = (ULONG_PTR)&HardErrorDllName; 01147 HardErrorParameters[1] = (ULONG_PTR)&HardErrorDllPath; 01148 01149 /* Raise the hard error */ 01150 NtRaiseHardError(STATUS_DLL_NOT_FOUND, 01151 2, 01152 0x00000003, 01153 HardErrorParameters, 01154 OptionOk, 01155 &Response); 01156 01157 /* We're back, where we initializing? */ 01158 if (LdrpInLdrInit) LdrpFatalHardErrorCount++; 01159 } 01160 01161 /* Return failure */ 01162 return STATUS_DLL_NOT_FOUND; 01163 } 01164 } 01165 else 01166 { 01167 /* We have a section handle, so this is a known dll */ 01168 KnownDll = TRUE; 01169 } 01170 01171 /* Stuff the image name in the TIB, for the debugger */ 01172 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer; 01173 Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer; 01174 01175 /* Map the DLL */ 01176 ViewBase = NULL; 01177 ViewSize = 0; 01178 Status = NtMapViewOfSection(SectionHandle, 01179 NtCurrentProcess(), 01180 &ViewBase, 01181 0, 01182 0, 01183 NULL, 01184 &ViewSize, 01185 ViewShare, 01186 0, 01187 PAGE_READWRITE); 01188 01189 /* Restore */ 01190 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer; 01191 01192 /* Fail if we couldn't map it */ 01193 if (!NT_SUCCESS(Status)) 01194 { 01195 /* Close and return */ 01196 NtClose(SectionHandle); 01197 return Status; 01198 } 01199 01200 /* Get the NT Header */ 01201 if (!(NtHeaders = RtlImageNtHeader(ViewBase))) 01202 { 01203 /* Invalid image, unmap, close handle and fail */ 01204 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 01205 NtClose(SectionHandle); 01206 return STATUS_INVALID_IMAGE_FORMAT; 01207 } 01208 01209 // FIXME: .NET support is missing 01210 01211 /* Allocate an entry */ 01212 if (!(LdrEntry = LdrpAllocateDataTableEntry(ViewBase))) 01213 { 01214 /* Invalid image, unmap, close handle and fail */ 01215 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 01216 NtClose(SectionHandle); 01217 return STATUS_NO_MEMORY; 01218 } 01219 01220 /* Setup the entry */ 01221 LdrEntry->Flags = Static ? LDRP_STATIC_LINK : 0; 01222 if (Redirect) LdrEntry->Flags |= LDRP_REDIRECTED; 01223 LdrEntry->LoadCount = 0; 01224 LdrEntry->FullDllName = FullDllName; 01225 LdrEntry->BaseDllName = BaseDllName; 01226 LdrEntry->EntryPoint = LdrpFetchAddressOfEntryPoint(LdrEntry->DllBase); 01227 01228 /* Show debug message */ 01229 if (ShowSnaps) 01230 { 01231 DPRINT1("LDR: LdrpMapDll: Full Name %wZ, Base Name %wZ\n", 01232 &FullDllName, 01233 &BaseDllName); 01234 } 01235 01236 /* Insert this entry */ 01237 LdrpInsertMemoryTableEntry(LdrEntry); 01238 01239 // LdrpSendDllNotifications(LdrEntry, TRUE, Status == STATUS_IMAGE_NOT_AT_BASE) 01240 01241 /* Check for invalid CPU Image */ 01242 if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) 01243 { 01244 /* Load our header */ 01245 PIMAGE_NT_HEADERS ImageNtHeader = RtlImageNtHeader(Peb->ImageBaseAddress); 01246 01247 /* Assume defaults if we don't have to run the Hard Error path */ 01248 HardErrorStatus = STATUS_SUCCESS; 01249 Response = ResponseCancel; 01250 01251 /* Are we an NT 3.0 image? [Do these still exist? LOL -- IAI] */ 01252 if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3) 01253 { 01254 /* Reset the entrypoint, save our Dll Name */ 01255 LdrEntry->EntryPoint = 0; 01256 HardErrorParameters[0] = (ULONG_PTR)&FullDllName; 01257 01258 /* Raise the error */ 01259 HardErrorStatus = ZwRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH, 01260 1, 01261 1, 01262 HardErrorParameters, 01263 OptionOkCancel, 01264 &Response); 01265 } 01266 01267 /* Check if the user pressed cancel */ 01268 if (NT_SUCCESS(HardErrorStatus) && Response == ResponseCancel) 01269 { 01270 /* Remove the DLL from the lists */ 01271 RemoveEntryList(&LdrEntry->InLoadOrderLinks); 01272 RemoveEntryList(&LdrEntry->InMemoryOrderModuleList); 01273 RemoveEntryList(&LdrEntry->HashLinks); 01274 01275 /* Remove the LDR Entry */ 01276 RtlFreeHeap(RtlGetProcessHeap(), 0, LdrEntry ); 01277 01278 /* Unmap and close section */ 01279 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 01280 NtClose(SectionHandle); 01281 01282 /* Did we do a hard error? */ 01283 if (ImageNtHeader->OptionalHeader.MajorSubsystemVersion <= 3) 01284 { 01285 /* Yup, so increase fatal error count if we are initializing */ 01286 if (LdrpInLdrInit) LdrpFatalHardErrorCount++; 01287 } 01288 01289 /* Return failure */ 01290 return STATUS_INVALID_IMAGE_FORMAT; 01291 } 01292 } 01293 else 01294 { 01295 /* The image was valid. Is it a DLL? */ 01296 if (NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) 01297 { 01298 /* Set the DLL Flag */ 01299 LdrEntry->Flags |= LDRP_IMAGE_DLL; 01300 } 01301 01302 /* If we're not a DLL, clear the entrypoint */ 01303 if (!(LdrEntry->Flags & LDRP_IMAGE_DLL)) 01304 { 01305 LdrEntry->EntryPoint = 0; 01306 } 01307 } 01308 01309 /* Return it for the caller */ 01310 *DataTableEntry = LdrEntry; 01311 01312 /* Check if we loaded somewhere else */ 01313 if (Status == STATUS_IMAGE_NOT_AT_BASE) 01314 { 01315 /* Write the flag */ 01316 LdrEntry->Flags |= LDRP_IMAGE_NOT_AT_BASE; 01317 01318 /* Find our region */ 01319 ImageBase = (ULONG_PTR)NtHeaders->OptionalHeader.ImageBase; 01320 ImageEnd = ImageBase + ViewSize; 01321 01322 DPRINT1("LDR: LdrpMapDll Relocating Image Name %ws (%p -> %p)\n", DllName, ImageBase, ViewBase); 01323 01324 /* Scan all the modules */ 01325 ListHead = &Peb->Ldr->InLoadOrderModuleList; 01326 NextEntry = ListHead->Flink; 01327 while (NextEntry != ListHead) 01328 { 01329 /* Get the entry */ 01330 CandidateEntry = CONTAINING_RECORD(NextEntry, 01331 LDR_DATA_TABLE_ENTRY, 01332 InLoadOrderLinks); 01333 NextEntry = NextEntry->Flink; 01334 01335 /* Get the entry's bounds */ 01336 CandidateBase = (ULONG_PTR)CandidateEntry->DllBase; 01337 CandidateEnd = CandidateBase + CandidateEntry->SizeOfImage; 01338 01339 /* Make sure this entry isn't unloading */ 01340 if (!CandidateEntry->InMemoryOrderModuleList.Flink) continue; 01341 01342 /* Check if our regions are colliding */ 01343 if ((ImageBase >= CandidateBase && ImageBase <= CandidateEnd) || 01344 (ImageEnd >= CandidateBase && ImageEnd <= CandidateEnd) || 01345 (CandidateBase >= ImageBase && CandidateBase <= ImageEnd)) 01346 { 01347 /* Found who is overlapping */ 01348 OverlapDllFound = TRUE; 01349 OverlapDll = CandidateEntry->FullDllName; 01350 break; 01351 } 01352 } 01353 01354 /* Check if we found the DLL overlapping with us */ 01355 if (!OverlapDllFound) 01356 { 01357 /* It's not another DLL, it's memory already here */ 01358 RtlInitUnicodeString(&OverlapDll, L"Dynamically Allocated Memory"); 01359 } 01360 01361 DPRINT1("Overlapping DLL: %wZ\n", &OverlapDll); 01362 01363 /* Are we dealing with a DLL? */ 01364 if (LdrEntry->Flags & LDRP_IMAGE_DLL) 01365 { 01366 /* Check if relocs were stripped */ 01367 if (!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED)) 01368 { 01369 /* Get the relocation data */ 01370 RelocData = RtlImageDirectoryEntryToData(ViewBase, 01371 TRUE, 01372 IMAGE_DIRECTORY_ENTRY_BASERELOC, 01373 &RelocDataSize); 01374 01375 /* Does the DLL not have any? */ 01376 if (!RelocData && !RelocDataSize) 01377 { 01378 /* We'll allow this and simply continue */ 01379 goto NoRelocNeeded; 01380 } 01381 } 01382 01383 /* See if this is an Illegal DLL - IE: user32 and kernel32 */ 01384 RtlInitUnicodeString(&IllegalDll,L"user32.dll"); 01385 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE)) 01386 { 01387 /* Can't relocate user32 */ 01388 RelocatableDll = FALSE; 01389 } 01390 else 01391 { 01392 RtlInitUnicodeString(&IllegalDll, L"kernel32.dll"); 01393 if (RtlEqualUnicodeString(&BaseDllName, &IllegalDll, TRUE)) 01394 { 01395 /* Can't relocate kernel32 */ 01396 RelocatableDll = FALSE; 01397 } 01398 } 01399 01400 /* Known DLLs are not allowed to be relocated */ 01401 if (KnownDll && !RelocatableDll) 01402 { 01403 /* Setup for hard error */ 01404 HardErrorParameters[0] = (ULONG_PTR)&IllegalDll; 01405 HardErrorParameters[1] = (ULONG_PTR)&OverlapDll; 01406 01407 /* Raise the error */ 01408 ZwRaiseHardError(STATUS_ILLEGAL_DLL_RELOCATION, 01409 2, 01410 3, 01411 HardErrorParameters, 01412 OptionOk, 01413 &Response); 01414 01415 /* If initializing, increase the error count */ 01416 if (LdrpInLdrInit) LdrpFatalHardErrorCount++; 01417 01418 /* Don't do relocation */ 01419 Status = STATUS_CONFLICTING_ADDRESSES; 01420 goto NoRelocNeeded; 01421 } 01422 01423 /* Change the protection to prepare for relocation */ 01424 Status = LdrpSetProtection(ViewBase, FALSE); 01425 01426 /* Make sure we changed the protection */ 01427 if (NT_SUCCESS(Status)) 01428 { 01429 /* Do the relocation */ 01430 Status = LdrRelocateImageWithBias(ViewBase, 0LL, NULL, STATUS_SUCCESS, 01431 STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT); 01432 01433 if (NT_SUCCESS(Status)) 01434 { 01435 /* Stuff the image name in the TIB, for the debugger */ 01436 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer; 01437 Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer; 01438 #if 0 01439 /* Map the DLL */ 01440 Status = NtMapViewOfSection(SectionHandle, 01441 NtCurrentProcess(), 01442 &ViewBase, 01443 0, 01444 0, 01445 NULL, 01446 &ViewSize, 01447 ViewShare, 01448 0, 01449 PAGE_READWRITE); 01450 #endif 01451 /* Restore */ 01452 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer; 01453 01454 /* Return the protection */ 01455 Status = LdrpSetProtection(ViewBase, TRUE); 01456 } 01457 } 01458 //FailRelocate: 01459 /* Handle any kind of failure */ 01460 if (!NT_SUCCESS(Status)) 01461 { 01462 /* Remove it from the lists */ 01463 RemoveEntryList(&LdrEntry->InLoadOrderLinks); 01464 RemoveEntryList(&LdrEntry->InMemoryOrderModuleList); 01465 RemoveEntryList(&LdrEntry->HashLinks); 01466 01467 /* Unmap it, clear the entry */ 01468 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 01469 LdrEntry = NULL; 01470 } 01471 01472 /* Show debug message */ 01473 if (ShowSnaps) 01474 { 01475 DPRINT1("LDR: Fixups %successfully re-applied @ %p\n", 01476 NT_SUCCESS(Status) ? "s" : "uns", ViewBase); 01477 } 01478 } 01479 else 01480 { 01481 NoRelocNeeded: 01482 /* Not a DLL, or no relocation needed */ 01483 Status = STATUS_SUCCESS; 01484 01485 /* Stuff the image name in the TIB, for the debugger */ 01486 ArbitraryUserPointer = Teb->NtTib.ArbitraryUserPointer; 01487 Teb->NtTib.ArbitraryUserPointer = FullDllName.Buffer; 01488 #if 0 01489 /* Map the DLL */ 01490 Status = NtMapViewOfSection(SectionHandle, 01491 NtCurrentProcess(), 01492 &ViewBase, 01493 0, 01494 0, 01495 NULL, 01496 &ViewSize, 01497 ViewShare, 01498 0, 01499 PAGE_READWRITE); 01500 #endif 01501 /* Restore */ 01502 Teb->NtTib.ArbitraryUserPointer = ArbitraryUserPointer; 01503 01504 /* Show debug message */ 01505 if (ShowSnaps) 01506 { 01507 DPRINT1("LDR: Fixups won't be re-applied to non-Dll @ %p\n", ViewBase); 01508 } 01509 } 01510 } 01511 01512 // FIXME: LdrpCheckCorImage() is missing 01513 01514 /* Check if this is an SMP Machine and a DLL */ 01515 if ((LdrpNumberOfProcessors > 1) && 01516 (LdrEntry && (LdrEntry->Flags & LDRP_IMAGE_DLL))) 01517 { 01518 /* Validate the image for MP */ 01519 LdrpValidateImageForMp(LdrEntry); 01520 } 01521 01522 // FIXME: LdrpCorUnloadImage() is missing 01523 01524 /* Close section and return status */ 01525 NtClose(SectionHandle); 01526 return Status; 01527 } 01528 01529 PLDR_DATA_TABLE_ENTRY 01530 NTAPI 01531 LdrpAllocateDataTableEntry(IN PVOID BaseAddress) 01532 { 01533 PLDR_DATA_TABLE_ENTRY LdrEntry = NULL; 01534 PIMAGE_NT_HEADERS NtHeader; 01535 01536 /* Make sure the header is valid */ 01537 NtHeader = RtlImageNtHeader(BaseAddress); 01538 DPRINT("LdrpAllocateDataTableEntry(%p), NtHeader %p\n", BaseAddress, NtHeader); 01539 01540 if (NtHeader) 01541 { 01542 /* Allocate an entry */ 01543 LdrEntry = RtlAllocateHeap(RtlGetProcessHeap(), 01544 HEAP_ZERO_MEMORY, 01545 sizeof(LDR_DATA_TABLE_ENTRY)); 01546 01547 /* Make sure we got one */ 01548 if (LdrEntry) 01549 { 01550 /* Set it up */ 01551 LdrEntry->DllBase = BaseAddress; 01552 LdrEntry->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage; 01553 LdrEntry->TimeDateStamp = NtHeader->FileHeader.TimeDateStamp; 01554 LdrEntry->PatchInformation = NULL; 01555 } 01556 } 01557 01558 /* Return the entry */ 01559 return LdrEntry; 01560 } 01561 01562 VOID 01563 NTAPI 01564 LdrpInsertMemoryTableEntry(IN PLDR_DATA_TABLE_ENTRY LdrEntry) 01565 { 01566 PPEB_LDR_DATA PebData = NtCurrentPeb()->Ldr; 01567 ULONG i; 01568 01569 /* Insert into hash table */ 01570 i = LDR_GET_HASH_ENTRY(LdrEntry->BaseDllName.Buffer[0]); 01571 InsertTailList(&LdrpHashTable[i], &LdrEntry->HashLinks); 01572 01573 /* Insert into other lists */ 01574 InsertTailList(&PebData->InLoadOrderModuleList, &LdrEntry->InLoadOrderLinks); 01575 InsertTailList(&PebData->InMemoryOrderModuleList, &LdrEntry->InMemoryOrderModuleList); 01576 } 01577 01578 VOID 01579 NTAPI 01580 LdrpFinalizeAndDeallocateDataTableEntry(IN PLDR_DATA_TABLE_ENTRY Entry) 01581 { 01582 /* Sanity check */ 01583 ASSERT(Entry != NULL); 01584 01585 /* Release the activation context if it exists and wasn't already released */ 01586 if ((Entry->EntryPointActivationContext) && 01587 (Entry->EntryPointActivationContext != INVALID_HANDLE_VALUE)) 01588 { 01589 /* Mark it as invalid */ 01590 RtlReleaseActivationContext(Entry->EntryPointActivationContext); 01591 Entry->EntryPointActivationContext = INVALID_HANDLE_VALUE; 01592 } 01593 01594 /* Release the full dll name string */ 01595 if (Entry->FullDllName.Buffer) LdrpFreeUnicodeString(&Entry->FullDllName); 01596 01597 /* Finally free the entry's memory */ 01598 RtlFreeHeap(RtlGetProcessHeap(), 0, Entry); 01599 } 01600 01601 BOOLEAN 01602 NTAPI 01603 LdrpCheckForLoadedDllHandle(IN PVOID Base, 01604 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry) 01605 { 01606 PLDR_DATA_TABLE_ENTRY Current; 01607 PLIST_ENTRY ListHead, Next; 01608 01609 /* Check the cache first */ 01610 if ((LdrpLoadedDllHandleCache) && 01611 (LdrpLoadedDllHandleCache->DllBase == Base)) 01612 { 01613 /* We got lucky, return the cached entry */ 01614 *LdrEntry = LdrpLoadedDllHandleCache; 01615 return TRUE; 01616 } 01617 01618 /* Time for a lookup */ 01619 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 01620 Next = ListHead->Flink; 01621 while (Next != ListHead) 01622 { 01623 /* Get the current entry */ 01624 Current = CONTAINING_RECORD(Next, 01625 LDR_DATA_TABLE_ENTRY, 01626 InLoadOrderLinks); 01627 01628 /* Make sure it's not unloading and check for a match */ 01629 if ((Current->InMemoryOrderModuleList.Flink) && (Base == Current->DllBase)) 01630 { 01631 /* Save in cache */ 01632 LdrpLoadedDllHandleCache = Current; 01633 01634 /* Return it */ 01635 *LdrEntry = Current; 01636 return TRUE; 01637 } 01638 01639 /* Move to the next one */ 01640 Next = Next->Flink; 01641 } 01642 01643 /* Nothing found */ 01644 return FALSE; 01645 } 01646 01647 NTSTATUS 01648 NTAPI 01649 LdrpResolveFullName(IN PUNICODE_STRING OriginalName, 01650 IN PUNICODE_STRING PathName, 01651 IN PUNICODE_STRING FullPathName, 01652 IN PUNICODE_STRING *ExpandedName) 01653 { 01654 NTSTATUS Status = STATUS_SUCCESS; 01655 // RTL_PATH_TYPE PathType; 01656 // BOOLEAN InvalidName; 01657 ULONG Length; 01658 01659 /* Display debug output if snaps are on */ 01660 if (ShowSnaps) 01661 { 01662 DbgPrintEx(81, //DPFLTR_LDR_ID, 01663 0, 01664 "LDR: %s - Expanding full name of %wZ\n", 01665 __FUNCTION__, 01666 OriginalName); 01667 } 01668 01669 /* FIXME: Lock the PEB */ 01670 //RtlEnterCriticalSection(&FastPebLock); 01671 #if 0 01672 /* Get the path name */ 01673 Length = RtlGetFullPathName_Ustr(OriginalName, 01674 PathName->Length, 01675 PathName->Buffer, 01676 NULL, 01677 &InvalidName, 01678 &PathType); 01679 #else 01680 Length = 0; 01681 #endif 01682 if (!(Length) || (Length > UNICODE_STRING_MAX_BYTES)) 01683 { 01684 /* Fail */ 01685 Status = STATUS_NAME_TOO_LONG; 01686 goto Quickie; 01687 } 01688 01689 /* Check if the length hasn't changed */ 01690 if (Length <= PathName->Length) 01691 { 01692 /* Return the same thing */ 01693 *ExpandedName = PathName; 01694 PathName->Length = (USHORT)Length; 01695 goto Quickie; 01696 } 01697 01698 /* Sanity check */ 01699 ASSERT(Length >= sizeof(WCHAR)); 01700 01701 /* Allocate a string */ 01702 Status = LdrpAllocateUnicodeString(FullPathName, Length - sizeof(WCHAR)); 01703 if (!NT_SUCCESS(Status)) goto Quickie; 01704 01705 /* Now get the full path again */ 01706 #if 0 01707 Length = RtlGetFullPathName_Ustr(OriginalName, 01708 FullPathName->Length, 01709 FullPathName->Buffer, 01710 NULL, 01711 &InvalidName, 01712 &PathType); 01713 #else 01714 Length = 0; 01715 #endif 01716 if (!(Length) || (Length > FullPathName->Length)) 01717 { 01718 /* Fail */ 01719 LdrpFreeUnicodeString(FullPathName); 01720 Status = STATUS_NAME_TOO_LONG; 01721 } 01722 else 01723 { 01724 /* Return the expanded name */ 01725 *ExpandedName = FullPathName; 01726 FullPathName->Length = (USHORT)Length; 01727 } 01728 01729 Quickie: 01730 /* FIXME: Unlock the PEB */ 01731 //RtlLeaveCriticalSection(&FastPebLock); 01732 01733 /* Display debug output if snaps are on */ 01734 if (ShowSnaps) 01735 { 01736 /* Check which output to use -- failure or success */ 01737 if (NT_SUCCESS(Status)) 01738 { 01739 DbgPrintEx(81, //DPFLTR_LDR_ID, 01740 0, 01741 "LDR: %s - Expanded to %wZ\n", 01742 __FUNCTION__, 01743 *ExpandedName); 01744 } 01745 else 01746 { 01747 DbgPrintEx(81, //DPFLTR_LDR_ID, 01748 0, 01749 "LDR: %s - Failed to expand %wZ; 0x%08x\n", 01750 __FUNCTION__, 01751 OriginalName, 01752 Status); 01753 } 01754 } 01755 01756 /* If we failed, return NULL */ 01757 if (!NT_SUCCESS(Status)) *ExpandedName = NULL; 01758 01759 /* Return status */ 01760 return Status; 01761 } 01762 01763 NTSTATUS 01764 NTAPI 01765 LdrpSearchPath(IN PWCHAR *SearchPath, 01766 IN PWCHAR DllName, 01767 IN PUNICODE_STRING PathName, 01768 IN PUNICODE_STRING FullPathName, 01769 IN PUNICODE_STRING *ExpandedName) 01770 { 01771 BOOLEAN TryAgain = FALSE; 01772 PWCHAR ActualSearchPath = *SearchPath; 01773 UNICODE_STRING TestName; 01774 NTSTATUS Status; 01775 PWCHAR Buffer, BufEnd = NULL; 01776 ULONG Length = 0; 01777 WCHAR p; 01778 //PWCHAR pp; 01779 01780 /* Check if we don't have a search path */ 01781 if (!ActualSearchPath) *SearchPath = LdrpDefaultPath.Buffer; 01782 01783 /* Display debug output if snaps are on */ 01784 if (ShowSnaps) 01785 { 01786 DbgPrintEx(81, //DPFLTR_LDR_ID, 01787 0, 01788 "LDR: %s - Looking for %ws in %ws\n", 01789 __FUNCTION__, 01790 DllName, 01791 *SearchPath); 01792 } 01793 01794 /* Check if we're dealing with a relative path */ 01795 if (RtlDetermineDosPathNameType_U(DllName) != RtlPathTypeRelative) 01796 { 01797 /* Good, we're not. Create the name string */ 01798 Status = RtlInitUnicodeStringEx(&TestName, DllName); 01799 if (!NT_SUCCESS(Status)) goto Quickie; 01800 01801 /* Make sure it exists */ 01802 #if 0 01803 if (!RtlDoesFileExists_UstrEx(&TestName, TRUE)) 01804 { 01805 /* It doesn't, fail */ 01806 Status = STATUS_DLL_NOT_FOUND; 01807 goto Quickie; 01808 } 01809 #endif 01810 01811 /* Resolve the full name */ 01812 Status = LdrpResolveFullName(&TestName, 01813 PathName, 01814 FullPathName, 01815 ExpandedName); 01816 goto Quickie; 01817 } 01818 01819 /* FIXME: Handle relative case semicolon-lookup here */ 01820 01821 /* Calculate length */ 01822 Length += (ULONG)wcslen(DllName) + sizeof(UNICODE_NULL); 01823 if (Length > UNICODE_STRING_MAX_CHARS) 01824 { 01825 /* Too long, fail */ 01826 Status = STATUS_NAME_TOO_LONG; 01827 goto Quickie; 01828 } 01829 01830 /* Allocate buffer */ 01831 Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length * sizeof(WCHAR)); 01832 if (!Buffer) 01833 { 01834 /* Fail */ 01835 Status = STATUS_NO_MEMORY; 01836 goto Quickie; 01837 } 01838 01839 /* FIXME: Setup TestName here */ 01840 Status = STATUS_NOT_FOUND; 01841 01842 /* Start loop */ 01843 do 01844 { 01845 /* Get character */ 01846 p = *ActualSearchPath; 01847 if (!(p) || (p == ';')) 01848 { 01849 /* FIXME: We don't have a character, or is a semicolon.*/ 01850 01851 /* Display debug output if snaps are on */ 01852 if (ShowSnaps) 01853 { 01854 DbgPrintEx(81, //DPFLTR_LDR_ID, 01855 0, 01856 "LDR: %s - Looking for %ws\n", 01857 __FUNCTION__, 01858 Buffer); 01859 } 01860 01861 /* Sanity check */ 01862 TestName.Length = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR); 01863 #if 0 01864 ASSERT(TestName.Length < TestName.MaximumLength); 01865 #endif 01866 01867 /* Check if the file exists */ 01868 #if 0 01869 if (RtlDoesFileExists_UstrEx(&TestName, FALSE)) 01870 #endif 01871 { 01872 /* It does. Reallocate the buffer */ 01873 TestName.MaximumLength = (USHORT)ALIGN_DOWN((BufEnd - Buffer), WCHAR) + sizeof(WCHAR); 01874 TestName.Buffer = RtlReAllocateHeap(RtlGetProcessHeap(), 01875 0, 01876 Buffer, 01877 TestName.MaximumLength); 01878 if (!TestName.Buffer) 01879 { 01880 /* Keep the old one */ 01881 TestName.Buffer = Buffer; 01882 } 01883 else 01884 { 01885 /* Update buffer */ 01886 Buffer = TestName.Buffer; 01887 } 01888 01889 /* Make sure we have a buffer at least */ 01890 ASSERT(TestName.Buffer); 01891 01892 /* Resolve the name */ 01893 *SearchPath = ActualSearchPath++; 01894 Status = LdrpResolveFullName(&TestName, 01895 PathName, 01896 FullPathName, 01897 ExpandedName); 01898 break; 01899 } 01900 01901 /* Update buffer end */ 01902 BufEnd = Buffer; 01903 01904 /* Update string position */ 01905 //pp = ActualSearchPath++; 01906 } 01907 else 01908 { 01909 /* Otherwise, write the character */ 01910 *BufEnd = p; 01911 BufEnd++; 01912 } 01913 01914 /* Check if the string is empty, meaning we're done */ 01915 if (!(*ActualSearchPath)) TryAgain = TRUE; 01916 01917 /* Advance in the string */ 01918 ActualSearchPath++; 01919 } while (!TryAgain); 01920 01921 /* Check if we had a buffer and free it */ 01922 if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer); 01923 01924 Quickie: 01925 /* Check if we got here through failure */ 01926 if (!NT_SUCCESS(Status)) *ExpandedName = NULL; 01927 01928 /* Display debug output if snaps are on */ 01929 if (ShowSnaps) 01930 { 01931 /* Check which output to use -- failure or success */ 01932 if (NT_SUCCESS(Status)) 01933 { 01934 DbgPrintEx(81, //DPFLTR_LDR_ID, 01935 0, 01936 "LDR: %s - Returning %wZ\n", 01937 __FUNCTION__, 01938 *ExpandedName); 01939 } 01940 else 01941 { 01942 DbgPrintEx(81, //DPFLTR_LDR_ID, 01943 0, 01944 "LDR: %s - Unable to locate %ws in %ws: 0x%08x\n", 01945 __FUNCTION__, 01946 DllName, 01947 ActualSearchPath, 01948 Status); 01949 } 01950 } 01951 01952 /* Return status */ 01953 return Status; 01954 } 01955 01956 01957 /* NOTE: This function is b0rked and in the process of being slowly unf*cked */ 01958 BOOLEAN 01959 NTAPI 01960 LdrpCheckForLoadedDll(IN PWSTR DllPath, 01961 IN PUNICODE_STRING DllName, 01962 IN BOOLEAN Flag, 01963 IN BOOLEAN RedirectedDll, 01964 OUT PLDR_DATA_TABLE_ENTRY *LdrEntry) 01965 { 01966 ULONG HashIndex; 01967 PLIST_ENTRY ListHead, ListEntry; 01968 PLDR_DATA_TABLE_ENTRY CurEntry; 01969 BOOLEAN FullPath = FALSE; 01970 PWCHAR wc; 01971 WCHAR NameBuf[266]; 01972 UNICODE_STRING FullDllName, NtPathName; 01973 ULONG Length; 01974 OBJECT_ATTRIBUTES ObjectAttributes; 01975 NTSTATUS Status; 01976 HANDLE FileHandle, SectionHandle; 01977 IO_STATUS_BLOCK Iosb; 01978 PVOID ViewBase = NULL; 01979 SIZE_T ViewSize = 0; 01980 PIMAGE_NT_HEADERS NtHeader, NtHeader2; 01981 DPRINT("LdrpCheckForLoadedDll('%S' '%wZ' %d %d %p)\n", DllPath ? ((ULONG_PTR)DllPath == 1 ? L"" : DllPath) : L"", DllName, Flag, RedirectedDll, LdrEntry); 01982 01983 /* Check if a dll name was provided */ 01984 if (!(DllName->Buffer) || !(DllName->Buffer[0])) return FALSE; 01985 01986 /* FIXME: Warning, "Flag" is used as magic instead of "Static" */ 01987 /* FIXME: Warning, code does not support redirection at all */ 01988 01989 /* Look in the hash table if flag was set */ 01990 lookinhash: 01991 if (Flag) 01992 { 01993 /* Get hash index */ 01994 HashIndex = LDR_GET_HASH_ENTRY(DllName->Buffer[0]); 01995 01996 /* Traverse that list */ 01997 ListHead = &LdrpHashTable[HashIndex]; 01998 ListEntry = ListHead->Flink; 01999 while (ListEntry != ListHead) 02000 { 02001 /* Get the current entry */ 02002 CurEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, HashLinks); 02003 02004 /* Check base name of that module */ 02005 if (RtlEqualUnicodeString(DllName, &CurEntry->BaseDllName, TRUE)) 02006 { 02007 /* It matches, return it */ 02008 *LdrEntry = CurEntry; 02009 return TRUE; 02010 } 02011 02012 /* Advance to the next entry */ 02013 ListEntry = ListEntry->Flink; 02014 } 02015 02016 /* Module was not found, return failure */ 02017 return FALSE; 02018 } 02019 02020 /* Check if there is a full path in this DLL */ 02021 wc = DllName->Buffer; 02022 while (*wc) 02023 { 02024 /* Check for a slash in the current position*/ 02025 if ((*wc == L'\\') || (*wc == L'/')) 02026 { 02027 /* Found the slash, so dll name contains path */ 02028 FullPath = TRUE; 02029 02030 /* Setup full dll name string */ 02031 FullDllName.Buffer = NameBuf; 02032 02033 /* FIXME: This is from the Windows 2000 loader, not XP/2003, we should call LdrpSearchPath */ 02034 Length = RtlDosSearchPath_U(DllPath ? DllPath : LdrpDefaultPath.Buffer, 02035 DllName->Buffer, 02036 NULL, 02037 sizeof(NameBuf) - sizeof(UNICODE_NULL), 02038 FullDllName.Buffer, 02039 NULL); 02040 02041 /* Check if that was successful */ 02042 if (!(Length) || (Length > (sizeof(NameBuf) - sizeof(UNICODE_NULL)))) 02043 { 02044 /* HACK: Try to find active context dll */ 02045 Status = find_actctx_dll(DllName->Buffer, FullDllName.Buffer); 02046 if(Status == STATUS_SUCCESS) 02047 { 02048 Length = wcslen(FullDllName.Buffer) * sizeof(WCHAR); 02049 DPRINT1("found %S for %S\n", FullDllName.Buffer, DllName->Buffer); 02050 } 02051 else 02052 { 02053 02054 if (ShowSnaps) 02055 { 02056 DPRINT1("LDR: LdrpCheckForLoadedDll - Unable To Locate %ws: 0x%08x\n", 02057 DllName->Buffer, Length); 02058 } 02059 02060 /* Return failure */ 02061 return FALSE; 02062 } 02063 } 02064 02065 /* Full dll name is found */ 02066 FullDllName.Length = Length; 02067 FullDllName.MaximumLength = FullDllName.Length + sizeof(UNICODE_NULL); 02068 break; 02069 } 02070 02071 wc++; 02072 } 02073 02074 /* Go check the hash table */ 02075 if (!FullPath) 02076 { 02077 Flag = TRUE; 02078 goto lookinhash; 02079 } 02080 02081 /* FIXME: Warning, activation context missing */ 02082 /* NOTE: From here on down, everything looks good */ 02083 02084 /* Loop the module list */ 02085 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 02086 ListEntry = ListHead->Flink; 02087 while (ListEntry != ListHead) 02088 { 02089 /* Get the current entry and advance to the next one */ 02090 CurEntry = CONTAINING_RECORD(ListEntry, 02091 LDR_DATA_TABLE_ENTRY, 02092 InLoadOrderLinks); 02093 ListEntry = ListEntry->Flink; 02094 02095 /* Check if it's being unloaded */ 02096 if (!CurEntry->InMemoryOrderModuleList.Flink) continue; 02097 02098 /* Check if name matches */ 02099 if (RtlEqualUnicodeString(&FullDllName, 02100 &CurEntry->FullDllName, 02101 TRUE)) 02102 { 02103 /* Found it */ 02104 *LdrEntry = CurEntry; 02105 return TRUE; 02106 } 02107 } 02108 02109 /* Convert given path to NT path */ 02110 if (!RtlDosPathNameToNtPathName_U(FullDllName.Buffer, 02111 &NtPathName, 02112 NULL, 02113 NULL)) 02114 { 02115 /* Fail if conversion failed */ 02116 return FALSE; 02117 } 02118 02119 /* Initialize object attributes and open it */ 02120 InitializeObjectAttributes(&ObjectAttributes, 02121 &NtPathName, 02122 OBJ_CASE_INSENSITIVE, 02123 NULL, 02124 NULL); 02125 Status = NtOpenFile(&FileHandle, 02126 SYNCHRONIZE | FILE_EXECUTE, 02127 &ObjectAttributes, 02128 &Iosb, 02129 FILE_SHARE_READ | FILE_SHARE_DELETE, 02130 FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT); 02131 02132 /* Free NT path name */ 02133 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathName.Buffer); 02134 02135 /* If opening the file failed - return failure */ 02136 if (!NT_SUCCESS(Status)) return FALSE; 02137 02138 /* Create a section for this file */ 02139 Status = NtCreateSection(&SectionHandle, 02140 SECTION_MAP_READ | 02141 SECTION_MAP_EXECUTE | 02142 SECTION_MAP_WRITE, 02143 NULL, 02144 NULL, 02145 PAGE_EXECUTE, 02146 SEC_COMMIT, 02147 FileHandle); 02148 02149 /* Close file handle */ 02150 NtClose(FileHandle); 02151 02152 /* If creating section failed - return failure */ 02153 if (!NT_SUCCESS(Status)) return FALSE; 02154 02155 /* Map view of this section */ 02156 Status = ZwMapViewOfSection(SectionHandle, 02157 NtCurrentProcess(), 02158 &ViewBase, 02159 0, 02160 0, 02161 NULL, 02162 &ViewSize, 02163 ViewShare, 02164 0, 02165 PAGE_EXECUTE); 02166 02167 /* Close section handle */ 02168 NtClose(SectionHandle); 02169 02170 /* If section mapping failed - return failure */ 02171 if (!NT_SUCCESS(Status)) return FALSE; 02172 02173 /* Get pointer to the NT header of this section */ 02174 Status = RtlImageNtHeaderEx(0, ViewBase, ViewSize, &NtHeader); 02175 if (!(NT_SUCCESS(Status)) || !(NtHeader)) 02176 { 02177 /* Unmap the section and fail */ 02178 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 02179 return FALSE; 02180 } 02181 02182 /* Go through the list of modules again */ 02183 ListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList; 02184 ListEntry = ListHead->Flink; 02185 while (ListEntry != ListHead) 02186 { 02187 /* Get the current entry and advance to the next one */ 02188 CurEntry = CONTAINING_RECORD(ListEntry, 02189 LDR_DATA_TABLE_ENTRY, 02190 InLoadOrderLinks); 02191 ListEntry = ListEntry->Flink; 02192 02193 /* Check if it's in the process of being unloaded */ 02194 if (!CurEntry->InMemoryOrderModuleList.Flink) continue; 02195 02196 /* The header is untrusted, use SEH */ 02197 _SEH2_TRY 02198 { 02199 /* Check if timedate stamp and sizes match */ 02200 if ((CurEntry->TimeDateStamp == NtHeader->FileHeader.TimeDateStamp) && 02201 (CurEntry->SizeOfImage == NtHeader->OptionalHeader.SizeOfImage)) 02202 { 02203 /* Time, date and size match. Let's compare their headers */ 02204 NtHeader2 = RtlImageNtHeader(CurEntry->DllBase); 02205 if (RtlCompareMemory(NtHeader2, NtHeader, sizeof(IMAGE_NT_HEADERS))) 02206 { 02207 /* Headers match too! Finally ask the kernel to compare mapped files */ 02208 Status = ZwAreMappedFilesTheSame(CurEntry->DllBase, ViewBase); 02209 if (NT_SUCCESS(Status)) 02210 { 02211 /* This is our entry!, unmap and return success */ 02212 *LdrEntry = CurEntry; 02213 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 02214 _SEH2_YIELD(return TRUE;) 02215 } 02216 } 02217 } 02218 } 02219 _SEH2_EXCEPT (EXCEPTION_EXECUTE_HANDLER) 02220 { 02221 _SEH2_YIELD(break;) 02222 } 02223 _SEH2_END; 02224 } 02225 02226 /* Unmap the section and fail */ 02227 NtUnmapViewOfSection(NtCurrentProcess(), ViewBase); 02228 return FALSE; 02229 } 02230 02231 NTSTATUS 02232 NTAPI 02233 LdrpGetProcedureAddress(IN PVOID BaseAddress, 02234 IN PANSI_STRING Name, 02235 IN ULONG Ordinal, 02236 OUT PVOID *ProcedureAddress, 02237 IN BOOLEAN ExecuteInit) 02238 { 02239 NTSTATUS Status = STATUS_SUCCESS; 02240 UCHAR ImportBuffer[64]; 02241 PLDR_DATA_TABLE_ENTRY LdrEntry; 02242 IMAGE_THUNK_DATA Thunk; 02243 PVOID ImageBase; 02244 PIMAGE_IMPORT_BY_NAME ImportName = NULL; 02245 PIMAGE_EXPORT_DIRECTORY ExportDir; 02246 ULONG ExportDirSize, Length; 02247 PLIST_ENTRY Entry; 02248 02249 /* Show debug message */ 02250 if (ShowSnaps) DPRINT1("LDR: LdrGetProcedureAddress by "); 02251 02252 /* Check if we got a name */ 02253 if (Name) 02254 { 02255 /* Show debug message */ 02256 if (ShowSnaps) DbgPrint("NAME - %s\n", Name->Buffer); 02257 02258 /* Make sure it's not too long */ 02259 Length = Name->Length + 02260 sizeof(CHAR) + 02261 FIELD_OFFSET(IMAGE_IMPORT_BY_NAME, Name); 02262 if (Length > UNICODE_STRING_MAX_BYTES) 02263 { 02264 /* Won't have enough space to add the hint */ 02265 return STATUS_NAME_TOO_LONG; 02266 } 02267 02268 /* Check if our buffer is large enough */ 02269 if (Name->Length > sizeof(ImportBuffer)) 02270 { 02271 /* Allocate from heap, plus 2 bytes for the Hint */ 02272 ImportName = RtlAllocateHeap(RtlGetProcessHeap(), 02273 0, 02274 Length); 02275 } 02276 else 02277 { 02278 /* Use our internal buffer */ 02279 ImportName = (PIMAGE_IMPORT_BY_NAME)ImportBuffer; 02280 } 02281 02282 /* Clear the hint */ 02283 ImportName->Hint = 0; 02284 02285 /* Copy the name and null-terminate it */ 02286 RtlCopyMemory(ImportName->Name, Name->Buffer, Name->Length); 02287 ImportName->Name[Name->Length] = ANSI_NULL; 02288 02289 /* Clear the high bit */ 02290 ImageBase = ImportName; 02291 Thunk.u1.AddressOfData = 0; 02292 } 02293 else 02294 { 02295 /* Do it by ordinal */ 02296 ImageBase = NULL; 02297 02298 /* Show debug message */ 02299 if (ShowSnaps) DbgPrint("ORDINAL - %lx\n", Ordinal); 02300 02301 /* Make sure an ordinal was given */ 02302 if (!Ordinal) 02303 { 02304 /* No ordinal */ 02305 DPRINT1("No ordinal and no name\n"); 02306 return STATUS_INVALID_PARAMETER; 02307 } 02308 02309 /* Set the orginal flag in the thunk */ 02310 Thunk.u1.Ordinal = Ordinal | IMAGE_ORDINAL_FLAG; 02311 } 02312 02313 /* Acquire lock unless we are initting */ 02314 if (!LdrpInLdrInit) RtlEnterCriticalSection(&LdrpLoaderLock); 02315 02316 _SEH2_TRY 02317 { 02318 /* Try to find the loaded DLL */ 02319 if (!LdrpCheckForLoadedDllHandle(BaseAddress, &LdrEntry)) 02320 { 02321 /* Invalid base */ 02322 DPRINT1("Invalid base address %p\n", BaseAddress); 02323 Status = STATUS_DLL_NOT_FOUND; 02324 _SEH2_YIELD(goto Quickie;) 02325 } 02326 02327 /* Get the pointer to the export directory */ 02328 ExportDir = RtlImageDirectoryEntryToData(LdrEntry->DllBase, 02329 TRUE, 02330 IMAGE_DIRECTORY_ENTRY_EXPORT, 02331 &ExportDirSize); 02332 02333 if (!ExportDir) 02334 { 02335 DPRINT1("Image %wZ has no exports, but were trying to get procedure %s. BaseAddress asked %p, got entry BA %p\n", &LdrEntry->BaseDllName, Name ? Name->Buffer : NULL, BaseAddress, LdrEntry->DllBase); 02336 Status = STATUS_PROCEDURE_NOT_FOUND; 02337 _SEH2_YIELD(goto Quickie;) 02338 } 02339 02340 /* Now get the thunk */ 02341 Status = LdrpSnapThunk(LdrEntry->DllBase, 02342 ImageBase, 02343 &Thunk, 02344 &Thunk, 02345 ExportDir, 02346 ExportDirSize, 02347 FALSE, 02348 NULL); 02349 02350 /* Finally, see if we're supposed to run the init routines */ 02351 if ((NT_SUCCESS(Status)) && (ExecuteInit)) 02352 { 02353 /* 02354 * It's possible a forwarded entry had us load the DLL. In that case, 02355 * then we will call its DllMain. Use the last loaded DLL for this. 02356 */ 02357 Entry = NtCurrentPeb()->Ldr->InInitializationOrderModuleList.Blink; 02358 LdrEntry = CONTAINING_RECORD(Entry, 02359 LDR_DATA_TABLE_ENTRY, 02360 InInitializationOrderModuleList); 02361 02362 /* Make sure we didn't process it yet*/ 02363 if (!(LdrEntry->Flags & LDRP_ENTRY_PROCESSED)) 02364 { 02365 /* Call the init routine */ 02366 _SEH2_TRY 02367 { 02368 Status = LdrpRunInitializeRoutines(NULL); 02369 } 02370 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02371 { 02372 /* Get the exception code */ 02373 Status = _SEH2_GetExceptionCode(); 02374 } 02375 _SEH2_END; 02376 } 02377 } 02378 02379 /* Make sure we're OK till here */ 02380 if (NT_SUCCESS(Status)) 02381 { 02382 /* Return the address */ 02383 *ProcedureAddress = (PVOID)Thunk.u1.Function; 02384 } 02385 } 02386 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 02387 { 02388 /* Just ignore exceptions */ 02389 } 02390 _SEH2_END; 02391 02392 Quickie: 02393 /* Cleanup */ 02394 if (ImportName && (ImportName != (PIMAGE_IMPORT_BY_NAME)ImportBuffer)) 02395 { 02396 /* We allocated from heap, free it */ 02397 RtlFreeHeap(RtlGetProcessHeap(), 0, ImportName); 02398 } 02399 02400 /* Release the CS if we entered it */ 02401 if (!LdrpInLdrInit) RtlLeaveCriticalSection(&LdrpLoaderLock); 02402 02403 /* We're done */ 02404 return Status; 02405 } 02406 02407 NTSTATUS 02408 NTAPI 02409 LdrpLoadDll(IN BOOLEAN Redirected, 02410 IN PWSTR DllPath OPTIONAL, 02411 IN PULONG DllCharacteristics OPTIONAL, 02412 IN PUNICODE_STRING DllName, 02413 OUT PVOID *BaseAddress, 02414 IN BOOLEAN CallInit) 02415 { 02416 PPEB Peb = NtCurrentPeb(); 02417 NTSTATUS Status = STATUS_SUCCESS; 02418 PWCHAR p1, p2; 02419 WCHAR c; 02420 WCHAR NameBuffer[266]; 02421 LPWSTR RawDllName; 02422 UNICODE_STRING RawDllNameString; 02423 PLDR_DATA_TABLE_ENTRY LdrEntry; 02424 BOOLEAN InInit = LdrpInLdrInit; 02425 02426 /* Find the name without the extension */ 02427 p1 = DllName->Buffer; 02428 p2 = NULL; 02429 while (*p1) 02430 { 02431 c = *p1++; 02432 if (c == L'.') 02433 { 02434 p2 = p1; 02435 } 02436 else if (c == L'\\') 02437 { 02438 p2 = NULL; 02439 } 02440 } 02441 02442 /* Save the Raw DLL Name */ 02443 RawDllName = NameBuffer; 02444 if (DllName->Length >= sizeof(NameBuffer)) return STATUS_NAME_TOO_LONG; 02445 RtlMoveMemory(RawDllName, DllName->Buffer, DllName->Length); 02446 02447 /* Check if no extension was found or if we got a slash */ 02448 if (!(p2) || (*p2 == '\\')) 02449 { 02450 /* Check that we have space to add one */ 02451 if ((DllName->Length + LdrApiDefaultExtension.Length + sizeof(UNICODE_NULL)) >= 02452 sizeof(NameBuffer)) 02453 { 02454 /* No space to add the extension */ 02455 DbgPrintEx(81, //DPFLTR_LDR_ID, 02456 0, 02457 "LDR: %s - Dll name missing extension; with extension " 02458 "added the name is too long\n" 02459 " DllName: (@ %p) \"%wZ\"\n" 02460 " DllName->Length: %u\n", 02461 __FUNCTION__, 02462 DllName, 02463 DllName, 02464 DllName->Length); 02465 return STATUS_NAME_TOO_LONG; 02466 } 02467 02468 /* FIXME: CLEAN THIS UP WITH Rtl String Functions */ 02469 /* Add it */ 02470 RtlMoveMemory((PVOID)((ULONG_PTR)RawDllName + DllName->Length), 02471 LdrApiDefaultExtension.Buffer, 02472 LdrApiDefaultExtension.Length); 02473 02474 /* Save the length to a unicode string */ 02475 RawDllNameString.Length = DllName->Length + LdrApiDefaultExtension.Length; 02476 02477 /* Null terminate it */ 02478 RawDllName[RawDllNameString.Length / sizeof(WCHAR)] = 0; 02479 } 02480 else 02481 { 02482 /* Null terminate it */ 02483 RawDllName[DllName->Length / sizeof(WCHAR)] = 0; 02484 02485 /* Save the length to a unicode string */ 02486 RawDllNameString.Length = DllName->Length; 02487 } 02488 02489 /* Now create a unicode string for the DLL's name */ 02490 RawDllNameString.MaximumLength = sizeof(NameBuffer); 02491 RawDllNameString.Buffer = NameBuffer; 02492 02493 /* Check for init flag and acquire lock */ 02494 if (!InInit) RtlEnterCriticalSection(&LdrpLoaderLock); 02495 02496 /* Show debug message */ 02497 if (ShowSnaps) 02498 { 02499 DPRINT1("LDR: LdrLoadDll, loading %ws from %ws\n", 02500 RawDllName, 02501 DllPath ? DllPath : L""); 02502 } 02503 02504 /* Check if the DLL is already loaded */ 02505 if (!LdrpCheckForLoadedDll(DllPath, 02506 &RawDllNameString, 02507 FALSE, 02508 Redirected, 02509 &LdrEntry)) 02510 { 02511 /* Map it */ 02512 Status = LdrpMapDll(DllPath, 02513 DllPath, 02514 NameBuffer, 02515 DllCharacteristics, 02516 FALSE, 02517 Redirected, 02518 &LdrEntry); 02519 if (!NT_SUCCESS(Status)) goto Quickie; 02520 02521 /* FIXME: Need to mark the DLL range for the stack DB */ 02522 //RtlpStkMarkDllRange(LdrEntry); 02523 02524 /* Check if IMAGE_FILE_EXECUTABLE_IMAGE was provided */ 02525 if ((DllCharacteristics) && 02526 (*DllCharacteristics & IMAGE_FILE_EXECUTABLE_IMAGE)) 02527 { 02528 /* This is not a DLL, so remove such data */ 02529 LdrEntry->EntryPoint = NULL; 02530 LdrEntry->Flags &= ~LDRP_IMAGE_DLL; 02531 } 02532 02533 /* Make sure it's a DLL */ 02534 if (LdrEntry->Flags & LDRP_IMAGE_DLL) 02535 { 02536 /* Check if this is a .NET Image */ 02537 if (!(LdrEntry->Flags & LDRP_COR_IMAGE)) 02538 { 02539 /* Walk the Import Descriptor */ 02540 Status = LdrpWalkImportDescriptor(DllPath, LdrEntry); 02541 } 02542 02543 /* Update load count, unless it's locked */ 02544 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++; 02545 LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT); 02546 02547 /* Check if we failed */ 02548 if (!NT_SUCCESS(Status)) 02549 { 02550 /* Clear entrypoint, and insert into list */ 02551 LdrEntry->EntryPoint = NULL; 02552 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 02553 &LdrEntry->InInitializationOrderModuleList); 02554 02555 /* Cancel the load */ 02556 LdrpClearLoadInProgress(); 02557 02558 /* Unload the DLL */ 02559 if (ShowSnaps) 02560 { 02561 DbgPrint("LDR: Unloading %wZ due to error %x walking " 02562 "import descriptors", 02563 DllName, 02564 Status); 02565 } 02566 LdrUnloadDll(LdrEntry->DllBase); 02567 02568 /* Return the error */ 02569 goto Quickie; 02570 } 02571 } 02572 else if (LdrEntry->LoadCount != 0xFFFF) 02573 { 02574 /* Increase load count */ 02575 LdrEntry->LoadCount++; 02576 } 02577 02578 /* Insert it into the list */ 02579 InsertTailList(&Peb->Ldr->InInitializationOrderModuleList, 02580 &LdrEntry->InInitializationOrderModuleList); 02581 02582 /* If we have to run the entrypoint, make sure the DB is ready */ 02583 if (CallInit && LdrpLdrDatabaseIsSetup) 02584 { 02585 /* FIXME: Notify Shim Engine */ 02586 if (g_ShimsEnabled) 02587 { 02588 /* Call it */ 02589 //ShimLoadCallback = RtlDecodeSystemPointer(g_pfnSE_DllLoaded); 02590 //ShimLoadCallback(LdrEntry); 02591 } 02592 02593 /* Run the init routine */ 02594 Status = LdrpRunInitializeRoutines(NULL); 02595 if (!NT_SUCCESS(Status)) 02596 { 02597 /* Failed, unload the DLL */ 02598 if (ShowSnaps) 02599 { 02600 DbgPrint("LDR: Unloading %wZ because either its init " 02601 "routine or one of its static imports failed; " 02602 "status = 0x%08lx\n", 02603 DllName, 02604 Status); 02605 } 02606 LdrUnloadDll(LdrEntry->DllBase); 02607 } 02608 } 02609 else 02610 { 02611 /* The DB isn't ready, which means we were loaded because of a forwarder */ 02612 Status = STATUS_SUCCESS; 02613 } 02614 } 02615 else 02616 { 02617 /* We were already loaded. Are we a DLL? */ 02618 if ((LdrEntry->Flags & LDRP_IMAGE_DLL) && (LdrEntry->LoadCount != 0xFFFF)) 02619 { 02620 /* Increase load count */ 02621 LdrEntry->LoadCount++; 02622 LdrpUpdateLoadCount2(LdrEntry, LDRP_UPDATE_REFCOUNT); 02623 02624 /* Clear the load in progress */ 02625 LdrpClearLoadInProgress(); 02626 } 02627 else 02628 { 02629 /* Not a DLL, just increase the load count */ 02630 if (LdrEntry->LoadCount != 0xFFFF) LdrEntry->LoadCount++; 02631 } 02632 } 02633 02634 Quickie: 02635 /* Release the lock */ 02636 if (!InInit) RtlLeaveCriticalSection(Peb->LoaderLock); 02637 02638 /* Check for success */ 02639 if (NT_SUCCESS(Status)) 02640 { 02641 /* Return the base address */ 02642 *BaseAddress = LdrEntry->DllBase; 02643 } 02644 else 02645 { 02646 /* Nothing found */ 02647 *BaseAddress = NULL; 02648 } 02649 02650 /* Return status */ 02651 return Status; 02652 } 02653 02654 ULONG 02655 NTAPI 02656 LdrpClearLoadInProgress(VOID) 02657 { 02658 PLIST_ENTRY ListHead, Entry; 02659 PLDR_DATA_TABLE_ENTRY LdrEntry; 02660 ULONG ModulesCount = 0; 02661 02662 /* Traverse the init list */ 02663 ListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList; 02664 Entry = ListHead->Flink; 02665 while (Entry != ListHead) 02666 { 02667 /* Get the loader entry */ 02668 LdrEntry = CONTAINING_RECORD(Entry, 02669 LDR_DATA_TABLE_ENTRY, 02670 InInitializationOrderModuleList); 02671 02672 /* Clear load in progress flag */ 02673 LdrEntry->Flags &= ~LDRP_LOAD_IN_PROGRESS; 02674 02675 /* Check for modules with entry point count but not processed yet */ 02676 if ((LdrEntry->EntryPoint) && 02677 !(LdrEntry->Flags & LDRP_ENTRY_PROCESSED)) 02678 { 02679 /* Increase counter */ 02680 ModulesCount++; 02681 } 02682 02683 /* Advance to the next entry */ 02684 Entry = Entry->Flink; 02685 } 02686 02687 /* Return final count */ 02688 return ModulesCount; 02689 } 02690 02691 /* EOF */ Generated on Sun May 27 2012 04:22:35 for ReactOS by
1.7.6.1
|