ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ldrutils.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.