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

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

Generated on Sun May 27 2012 04:19:04 for ReactOS by doxygen 1.7.6.1

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