2011-04-03 09:42:08 +00:00
|
|
|
/*
|
1999-10-31 22:41:15 +00:00
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
2011-04-06 21:49:04 +00:00
|
|
|
* PROJECT : ReactOS system libraries
|
1999-10-31 22:41:15 +00:00
|
|
|
* MODULE : kernel32.dll
|
2011-04-03 09:42:08 +00:00
|
|
|
* FILE : reactos/dll/win32/kernel32/misc/ldr.c
|
|
|
|
* AUTHOR : Aleksey Bragin <aleksey@reactos.org>
|
1999-10-31 22:41:15 +00:00
|
|
|
*/
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2003-01-15 21:24:36 +00:00
|
|
|
#include <k32.h>
|
2000-04-14 01:50:38 +00:00
|
|
|
|
|
|
|
#define NDEBUG
|
2007-09-02 19:42:22 +00:00
|
|
|
#include <debug.h>
|
2000-04-14 01:50:38 +00:00
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
1999-10-12 19:45:01 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
DWORD
|
|
|
|
WINAPI
|
|
|
|
BasepGetModuleHandleExParameterValidation(DWORD dwFlags,
|
|
|
|
LPCWSTR lpwModuleName,
|
|
|
|
HMODULE *phModule)
|
|
|
|
{
|
|
|
|
/* Set phModule to 0 if it's not a NULL pointer */
|
|
|
|
if (phModule) *phModule = 0;
|
|
|
|
|
|
|
|
/* Check for invalid flags combination */
|
|
|
|
if (dwFlags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN |
|
|
|
|
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
|
|
|
|
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS) ||
|
2011-04-03 21:46:42 +00:00
|
|
|
((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) &&
|
|
|
|
(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ||
|
2011-04-03 09:42:08 +00:00
|
|
|
(!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
|
|
|
|
)
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(STATUS_INVALID_PARAMETER_1);
|
2011-04-04 19:35:24 +00:00
|
|
|
return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check 2nd parameter */
|
|
|
|
if (!phModule)
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(STATUS_INVALID_PARAMETER_2);
|
2011-04-04 19:35:24 +00:00
|
|
|
return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Return what we have according to the module name */
|
|
|
|
if (lpwModuleName)
|
|
|
|
{
|
|
|
|
return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* No name given, so put ImageBaseAddress there */
|
|
|
|
*phModule = (HMODULE)NtCurrentPeb()->ImageBaseAddress;
|
|
|
|
|
|
|
|
return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
PVOID
|
|
|
|
WINAPI
|
|
|
|
BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile)
|
|
|
|
{
|
|
|
|
/* If no handle is provided - use current image base address */
|
|
|
|
if (!hModule) return NtCurrentPeb()->ImageBaseAddress;
|
|
|
|
|
|
|
|
/* Check if it's a normal or a datafile one */
|
|
|
|
if (LDR_IS_DATAFILE(hModule) && !AsDataFile)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* It'a a normal DLL, just return its handle */
|
|
|
|
return hModule;
|
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2004-01-23 17:18:16 +00:00
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-02-19 17:00:08 +00:00
|
|
|
DisableThreadLibraryCalls(
|
|
|
|
IN HMODULE hLibModule)
|
2000-09-01 17:09:50 +00:00
|
|
|
{
|
2011-02-19 17:00:08 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Disable thread library calls */
|
2011-02-19 17:00:08 +00:00
|
|
|
Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule);
|
2011-04-06 19:03:20 +00:00
|
|
|
|
|
|
|
/* If it wasn't success - set last error and return failure */
|
2011-02-19 17:00:08 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-04-06 19:03:20 +00:00
|
|
|
|
|
|
|
/* Return success */
|
2011-02-19 17:00:08 +00:00
|
|
|
return TRUE;
|
2000-09-01 17:09:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
1999-10-31 22:41:15 +00:00
|
|
|
HINSTANCE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 19:03:20 +00:00
|
|
|
LoadLibraryA(LPCSTR lpLibFileName)
|
2000-04-14 01:50:38 +00:00
|
|
|
{
|
2011-04-06 19:03:20 +00:00
|
|
|
LPSTR PathBuffer;
|
|
|
|
UINT Len;
|
|
|
|
HINSTANCE Result;
|
|
|
|
|
|
|
|
/* Treat twain_32.dll in a special way (what a surprise...) */
|
|
|
|
if (lpLibFileName && !_strcmpi(lpLibFileName, "twain_32.dll"))
|
|
|
|
{
|
|
|
|
/* Allocate space for the buffer */
|
|
|
|
PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH);
|
|
|
|
if (PathBuffer)
|
|
|
|
{
|
|
|
|
/* Get windows dir in this buffer */
|
|
|
|
Len = GetWindowsDirectoryA(PathBuffer, MAX_PATH - 13); /* 13 is sizeof of '\\twain_32.dll' */
|
|
|
|
if (Len && Len < (MAX_PATH - 13))
|
|
|
|
{
|
|
|
|
/* We successfully got windows directory. Concatenate twain_32.dll to it */
|
|
|
|
strncat(PathBuffer, "\\twain_32.dll", 13);
|
|
|
|
|
|
|
|
/* And recursively call ourselves with a new string */
|
|
|
|
Result = LoadLibraryA(PathBuffer);
|
|
|
|
|
|
|
|
/* If it was successful - free memory and return result */
|
|
|
|
if (Result)
|
|
|
|
{
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
}
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Free allocated buffer */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Call the Ex version of the API */
|
|
|
|
return LoadLibraryExA(lpLibFileName, 0, 0);
|
|
|
|
}
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-04-14 01:50:38 +00:00
|
|
|
HINSTANCE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 19:03:20 +00:00
|
|
|
LoadLibraryExA(LPCSTR lpLibFileName,
|
|
|
|
HANDLE hFile,
|
|
|
|
DWORD dwFlags)
|
2000-04-14 01:50:38 +00:00
|
|
|
{
|
2011-04-06 19:03:20 +00:00
|
|
|
PUNICODE_STRING FileNameW;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Convert file name to unicode */
|
2011-02-19 17:00:08 +00:00
|
|
|
if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName)))
|
|
|
|
return NULL;
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* And call W version of the API */
|
2011-02-19 17:00:08 +00:00
|
|
|
return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags);
|
2000-04-14 01:50:38 +00:00
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-04-14 01:50:38 +00:00
|
|
|
HINSTANCE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 19:03:20 +00:00
|
|
|
LoadLibraryW(LPCWSTR lpLibFileName)
|
2000-04-14 01:50:38 +00:00
|
|
|
{
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Call Ex version of the API */
|
|
|
|
return LoadLibraryExW (lpLibFileName, 0, 0);
|
2000-04-14 01:50:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-17 15:53:15 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
2011-04-06 21:49:04 +00:00
|
|
|
BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule)
|
2009-07-17 15:53:15 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
WCHAR FilenameW[MAX_PATH];
|
2009-07-17 15:53:15 +00:00
|
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
2011-04-06 21:49:04 +00:00
|
|
|
HANDLE hMapping;
|
|
|
|
NTSTATUS Status;
|
2011-04-08 09:21:41 +00:00
|
|
|
PVOID lpBaseAddress = NULL;
|
2011-05-01 22:00:14 +00:00
|
|
|
SIZE_T ViewSize = 0;
|
2011-04-06 21:49:04 +00:00
|
|
|
//PUNICODE_STRING OriginalName;
|
|
|
|
//UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL");
|
|
|
|
|
|
|
|
/* Zero out handle value */
|
|
|
|
*hModule = 0;
|
|
|
|
|
2011-04-08 09:21:41 +00:00
|
|
|
DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule);
|
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/*Status = RtlDosApplyFileIsolationRedirection_Ustr(TRUE,
|
|
|
|
Name,
|
|
|
|
&dotDLL,
|
|
|
|
RedirName,
|
|
|
|
RedirName2,
|
|
|
|
&OriginalName2,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
NULL);*/
|
|
|
|
|
|
|
|
/* Try to search for it */
|
|
|
|
if (!SearchPathW(Path,
|
|
|
|
Name,
|
|
|
|
L".DLL",
|
|
|
|
sizeof(FilenameW) / sizeof(FilenameW[0]),
|
|
|
|
FilenameW,
|
|
|
|
NULL))
|
2009-07-17 15:53:15 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Return last status value directly */
|
2009-07-17 15:53:15 +00:00
|
|
|
return NtCurrentTeb()->LastStatusValue;
|
|
|
|
}
|
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Open this file we found */
|
|
|
|
hFile = CreateFileW(FilenameW,
|
|
|
|
GENERIC_READ,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_DELETE,
|
|
|
|
NULL,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
0,
|
|
|
|
0);
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* If opening failed - return last status value */
|
2009-07-17 15:53:15 +00:00
|
|
|
if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue;
|
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Create file mapping */
|
|
|
|
hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
|
|
|
|
|
|
|
/* Close the file handle */
|
|
|
|
CloseHandle(hFile);
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* If creating file mapping failed - return last status value */
|
|
|
|
if (!hMapping) return NtCurrentTeb()->LastStatusValue;
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Map view of section */
|
|
|
|
Status = NtMapViewOfSection(hMapping,
|
|
|
|
NtCurrentProcess(),
|
|
|
|
&lpBaseAddress,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
&ViewSize,
|
|
|
|
ViewShare,
|
|
|
|
0,
|
|
|
|
PAGE_READONLY);
|
|
|
|
|
|
|
|
/* Close handle to the section */
|
|
|
|
CloseHandle(hMapping);
|
|
|
|
|
|
|
|
/* If mapping view of section failed - return last status value */
|
|
|
|
if (!NT_SUCCESS(Status)) return NtCurrentTeb()->LastStatusValue;
|
|
|
|
|
|
|
|
/* Make sure it's a valid PE file */
|
|
|
|
if (!RtlImageNtHeader(lpBaseAddress))
|
2009-07-17 15:53:15 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Unmap the view and return failure status */
|
|
|
|
UnmapViewOfFile(lpBaseAddress);
|
2009-07-17 15:53:15 +00:00
|
|
|
return STATUS_INVALID_IMAGE_FORMAT;
|
|
|
|
}
|
2011-04-06 21:49:04 +00:00
|
|
|
|
|
|
|
/* Set low bit of handle to indicate datafile module */
|
|
|
|
*hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1);
|
|
|
|
|
|
|
|
/* Load alternate resource module */
|
|
|
|
//LdrLoadAlternateResourceModule(*hModule, FilenameW);
|
|
|
|
|
2009-07-17 15:53:15 +00:00
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-04-14 01:50:38 +00:00
|
|
|
HINSTANCE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 21:49:04 +00:00
|
|
|
LoadLibraryExW(LPCWSTR lpLibFileName,
|
|
|
|
HANDLE hFile,
|
|
|
|
DWORD dwFlags)
|
1999-10-12 19:45:01 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
UNICODE_STRING DllName;
|
|
|
|
HINSTANCE hInst;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PWSTR SearchPath;
|
2011-04-03 09:42:08 +00:00
|
|
|
ULONG DllCharacteristics = 0;
|
2011-04-06 21:49:04 +00:00
|
|
|
BOOL FreeString = FALSE;
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2005-09-26 20:08:11 +00:00
|
|
|
/* Check for any flags LdrLoadDll might be interested in */
|
|
|
|
if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
|
|
|
|
{
|
|
|
|
/* Tell LDR to treat it as an EXE */
|
|
|
|
DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
|
|
|
|
}
|
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Build up a unicode dll name from null-terminated string */
|
|
|
|
RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
|
2005-03-27 11:00:41 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Lazy-initialize BasepExeLdrEntry */
|
|
|
|
if (!BasepExeLdrEntry)
|
|
|
|
LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress);
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Check if that module is our exe*/
|
|
|
|
if (BasepExeLdrEntry && !(dwFlags & LOAD_LIBRARY_AS_DATAFILE) &&
|
|
|
|
DllName.Length == BasepExeLdrEntry->FullDllName.Length)
|
|
|
|
{
|
|
|
|
/* Lengths match and it's not a datafile, so perform name comparison */
|
|
|
|
if (RtlEqualUnicodeString(&DllName, &BasepExeLdrEntry->FullDllName, TRUE))
|
|
|
|
{
|
|
|
|
/* That's us! */
|
|
|
|
return BasepExeLdrEntry->DllBase;
|
|
|
|
}
|
|
|
|
}
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Check for trailing spaces and remove them if necessary */
|
|
|
|
if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
|
2009-07-17 15:53:15 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName);
|
|
|
|
while (DllName.Length > sizeof(WCHAR) &&
|
|
|
|
DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
|
2009-07-17 15:53:15 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
DllName.Length -= sizeof(WCHAR);
|
2009-07-17 15:53:15 +00:00
|
|
|
}
|
2011-04-06 21:49:04 +00:00
|
|
|
DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
FreeString = TRUE;
|
2009-07-17 15:53:15 +00:00
|
|
|
}
|
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Compute the load path */
|
2011-12-04 19:30:12 +00:00
|
|
|
SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ?
|
|
|
|
DllName.Buffer : NULL,
|
|
|
|
NULL);
|
2011-04-06 21:49:04 +00:00
|
|
|
if (!SearchPath)
|
2005-09-26 20:08:11 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Getting DLL path failed, so set last error, free mem and return */
|
|
|
|
BaseSetLastNTError(STATUS_NO_MEMORY);
|
|
|
|
if (FreeString) RtlFreeUnicodeString(&DllName);
|
|
|
|
return NULL;
|
2005-09-26 20:08:11 +00:00
|
|
|
}
|
2011-04-06 21:49:04 +00:00
|
|
|
|
|
|
|
_SEH2_TRY
|
2005-09-26 20:08:11 +00:00
|
|
|
{
|
2011-04-06 21:49:04 +00:00
|
|
|
if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
|
|
|
|
{
|
|
|
|
/* If the image is loaded as a datafile, try to get its handle */
|
2011-11-02 23:37:38 +00:00
|
|
|
Status = LdrGetDllHandleEx(0, SearchPath, NULL, &DllName, (PVOID*)&hInst);
|
2011-04-06 21:49:04 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* It's not loaded yet - so load it up */
|
|
|
|
Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst);
|
|
|
|
}
|
2011-11-02 23:37:38 +00:00
|
|
|
_SEH2_YIELD(goto done;)
|
2011-04-06 21:49:04 +00:00
|
|
|
}
|
|
|
|
|
[NTDLL/LDR]
- The long awaited LDR rewrite, a commit for testing the new implementation. In case of serious problems it may be reverted (revert should be approved by me).
- Its features include:
* A proper ...everything. Process, thread initialization codes, DLL loading (including compatible path lookup, and compatible/proper loading order of the dependent DLLs, including their initialization) and mapping and section creation, reference counting, relocations, good and understandable PE code for walking import descriptor, snapping, etc etc. Hacks--; GoodCode++;
* Activation contexts operations are now being performed compatible to how Windows performs them (though the actual actctx implementation is still Wine's, it was modified to be compatible). Previously, actctx stuff was added to the ldr code like a pepper is added to the soup: in different places until it starts to work.
* Partial DLL redirection implementation.
* Possibility to support Shim engine and app compat stuff in future.
* More cool stuff, just browse the code.
- I fixed all regressions I could find but one (hang during shutdown of the 3rd stage). The purpose of this commit is to seek and destroy the regressions I couldn't find (if there are any).
- Some of the old rarely called ldr code still remains in startup.c and utils.c. They are subject to be rewritten/removed soon, and every remaining old function is marked with a respective DPRINT1 to see when it's being called.
svn path=/trunk/; revision=52446
2011-06-24 21:30:09 +00:00
|
|
|
/* Call the API Properly */
|
|
|
|
Status = LdrLoadDll(SearchPath,
|
|
|
|
&DllCharacteristics,
|
|
|
|
&DllName,
|
|
|
|
(PVOID*)&hInst);
|
2005-09-26 20:08:11 +00:00
|
|
|
}
|
2011-04-06 21:49:04 +00:00
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
2011-12-20 21:01:30 +00:00
|
|
|
} _SEH2_END;
|
2011-04-06 21:49:04 +00:00
|
|
|
|
2009-07-17 15:53:15 +00:00
|
|
|
|
2009-07-23 20:48:43 +00:00
|
|
|
done:
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Free SearchPath buffer */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath);
|
|
|
|
|
|
|
|
/* Free DllName string if it was dynamically allocated */
|
|
|
|
if (FreeString) RtlFreeUnicodeString(&DllName);
|
|
|
|
|
|
|
|
/* Set last error in failure case */
|
2011-04-08 09:21:41 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
2011-04-06 21:49:04 +00:00
|
|
|
{
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 21:49:04 +00:00
|
|
|
/* Return loaded module handle */
|
|
|
|
return hInst;
|
1999-10-12 19:45:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
1999-10-31 22:41:15 +00:00
|
|
|
FARPROC
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 19:03:20 +00:00
|
|
|
GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
|
1999-10-12 19:45:01 +00:00
|
|
|
{
|
2011-04-06 19:03:20 +00:00
|
|
|
ANSI_STRING ProcedureName, *ProcNamePtr = NULL;
|
|
|
|
FARPROC fnExp = NULL;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID hMapped;
|
|
|
|
ULONG Ordinal = 0;
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
if (HIWORD(lpProcName) != 0)
|
|
|
|
{
|
|
|
|
/* Look up by name */
|
|
|
|
RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName);
|
|
|
|
ProcNamePtr = &ProcedureName;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Look up by ordinal */
|
|
|
|
Ordinal = (ULONG)lpProcName;
|
|
|
|
}
|
2011-03-21 14:16:01 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Map provided handle */
|
|
|
|
hMapped = BasepMapModuleHandle(hModule, FALSE);
|
1999-10-12 19:45:01 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Get the proc address */
|
|
|
|
Status = LdrGetProcedureAddress(hMapped,
|
|
|
|
ProcNamePtr,
|
|
|
|
Ordinal,
|
|
|
|
(PVOID*)&fnExp);
|
2008-09-13 07:37:05 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for a special case when returned pointer is
|
|
|
|
the same as iamge's base address */
|
|
|
|
if (fnExp == hMapped)
|
|
|
|
{
|
|
|
|
/* Set correct error code */
|
|
|
|
if (HIWORD(lpProcName) != 0)
|
|
|
|
BaseSetLastNTError(STATUS_ENTRYPOINT_NOT_FOUND);
|
|
|
|
else
|
|
|
|
BaseSetLastNTError(STATUS_ORDINAL_NOT_FOUND);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* All good, return procedure pointer */
|
|
|
|
return fnExp;
|
1999-10-12 19:45:01 +00:00
|
|
|
}
|
|
|
|
|
1999-10-31 22:41:15 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2009-08-04 16:43:37 +00:00
|
|
|
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
|
1999-10-12 19:45:01 +00:00
|
|
|
{
|
2009-07-17 17:15:17 +00:00
|
|
|
NTSTATUS Status;
|
2011-04-03 21:46:42 +00:00
|
|
|
PIMAGE_NT_HEADERS NtHeaders;
|
2009-07-17 17:15:17 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
if (LDR_IS_DATAFILE(hLibModule))
|
2009-07-17 17:15:17 +00:00
|
|
|
{
|
2011-04-03 21:46:42 +00:00
|
|
|
// FIXME: This SEH should go inside RtlImageNtHeader instead
|
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* This is a LOAD_LIBRARY_AS_DATAFILE module, check if it's a valid one */
|
|
|
|
NtHeaders = RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1));
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
NtHeaders = NULL;
|
|
|
|
} _SEH2_END
|
|
|
|
|
|
|
|
if (NtHeaders)
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
|
|
|
/* Unmap view */
|
|
|
|
Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
|
2009-08-04 16:43:37 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Unload alternate resource module */
|
|
|
|
LdrUnloadAlternateResourceModule(hLibModule);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Status = STATUS_INVALID_IMAGE_FORMAT;
|
|
|
|
}
|
|
|
|
else
|
2009-07-17 17:15:17 +00:00
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Just unload it */
|
|
|
|
Status = LdrUnloadDll((PVOID)hLibModule);
|
2009-07-17 17:15:17 +00:00
|
|
|
}
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Check what kind of status we got */
|
2009-07-17 17:15:17 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Set last error */
|
|
|
|
BaseSetLastNTError(Status);
|
|
|
|
|
|
|
|
/* Return failure */
|
2009-07-17 17:15:17 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return success */
|
2009-07-17 17:15:17 +00:00
|
|
|
return TRUE;
|
1999-10-12 19:45:01 +00:00
|
|
|
}
|
|
|
|
|
2000-04-14 01:50:38 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
1999-10-17 18:18:44 +00:00
|
|
|
VOID
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-03 09:42:08 +00:00
|
|
|
FreeLibraryAndExitThread(HMODULE hLibModule,
|
|
|
|
DWORD dwExitCode)
|
1999-10-17 18:18:44 +00:00
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
if (LDR_IS_DATAFILE(hLibModule))
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
|
|
|
/* This is a LOAD_LIBRARY_AS_DATAFILE module */
|
|
|
|
if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)))
|
|
|
|
{
|
|
|
|
/* Unmap view */
|
2011-09-11 15:39:19 +00:00
|
|
|
NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
|
2011-04-03 09:42:08 +00:00
|
|
|
|
|
|
|
/* Unload alternate resource module */
|
|
|
|
LdrUnloadAlternateResourceModule(hLibModule);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Just unload it */
|
2011-09-11 15:39:19 +00:00
|
|
|
LdrUnloadDll((PVOID)hLibModule);
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Exit thread */
|
2009-07-17 17:53:37 +00:00
|
|
|
ExitThread(dwExitCode);
|
1999-10-17 18:18:44 +00:00
|
|
|
}
|
1999-10-12 19:45:01 +00:00
|
|
|
|
1999-10-31 22:41:15 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-09-01 17:09:50 +00:00
|
|
|
DWORD
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-03 09:42:08 +00:00
|
|
|
GetModuleFileNameA(HINSTANCE hModule,
|
|
|
|
LPSTR lpFilename,
|
|
|
|
DWORD nSize)
|
2000-09-01 17:09:50 +00:00
|
|
|
{
|
2011-04-03 21:46:42 +00:00
|
|
|
UNICODE_STRING FilenameW;
|
2011-04-03 09:42:08 +00:00
|
|
|
ANSI_STRING FilenameA;
|
|
|
|
NTSTATUS Status;
|
2011-04-03 21:46:42 +00:00
|
|
|
DWORD Length = 0, LengthToCopy;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Allocate a unicode buffer */
|
2011-04-03 21:46:42 +00:00
|
|
|
FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR));
|
|
|
|
if (!FilenameW.Buffer)
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
|
|
|
BaseSetLastNTError(STATUS_NO_MEMORY);
|
|
|
|
return 0;
|
|
|
|
}
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Call unicode API */
|
2011-04-03 21:46:42 +00:00
|
|
|
FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR);
|
|
|
|
FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR);
|
2001-02-10 22:29:35 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
if (FilenameW.Length)
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
|
|
|
/* Convert to ansi string */
|
2011-04-03 21:46:42 +00:00
|
|
|
Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE);
|
2011-04-03 09:42:08 +00:00
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Set last error, free string and retun failure */
|
|
|
|
BaseSetLastNTError(Status);
|
2011-04-03 21:46:42 +00:00
|
|
|
RtlFreeUnicodeString(&FilenameW);
|
2011-04-03 09:42:08 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Calculate size to copy */
|
|
|
|
Length = min(nSize, FilenameA.Length);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
/* Include terminating zero */
|
|
|
|
if (nSize > Length)
|
|
|
|
LengthToCopy = Length + 1;
|
|
|
|
else
|
|
|
|
LengthToCopy = nSize;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Now copy back to the caller amount he asked */
|
2011-04-03 21:46:42 +00:00
|
|
|
RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Free ansi filename */
|
|
|
|
RtlFreeAnsiString(&FilenameA);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free unicode filename */
|
2011-04-03 21:46:42 +00:00
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return length copied */
|
|
|
|
return Length;
|
|
|
|
}
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-09-01 17:09:50 +00:00
|
|
|
DWORD
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-03 09:42:08 +00:00
|
|
|
GetModuleFileNameW(HINSTANCE hModule,
|
|
|
|
LPWSTR lpFilename,
|
|
|
|
DWORD nSize)
|
2000-09-01 17:09:50 +00:00
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
PLIST_ENTRY ModuleListHead, Entry;
|
|
|
|
PLDR_DATA_TABLE_ENTRY Module;
|
|
|
|
ULONG Length = 0;
|
|
|
|
ULONG Cookie;
|
|
|
|
PPEB Peb;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
hModule = BasepMapModuleHandle(hModule, FALSE);
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Upscale nSize from chars to bytes */
|
|
|
|
nSize *= sizeof(WCHAR);
|
2008-09-13 07:37:05 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
/* We don't use per-thread cur dir now */
|
|
|
|
//PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
Peb = NtCurrentPeb ();
|
2008-09-13 07:37:05 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Acquire a loader lock */
|
2011-04-04 19:35:24 +00:00
|
|
|
LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Traverse the module list */
|
|
|
|
ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
|
|
|
|
Entry = ModuleListHead->Flink;
|
|
|
|
while (Entry != ModuleListHead)
|
|
|
|
{
|
|
|
|
Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
|
|
|
|
|
|
|
|
/* Check if this is the requested module */
|
|
|
|
if (Module->DllBase == (PVOID)hModule)
|
|
|
|
{
|
|
|
|
/* Calculate size to copy */
|
|
|
|
Length = min(nSize, Module->FullDllName.MaximumLength);
|
|
|
|
|
|
|
|
/* Copy contents */
|
|
|
|
RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length);
|
|
|
|
|
|
|
|
/* Subtract a terminating zero */
|
|
|
|
if (Length == Module->FullDllName.MaximumLength)
|
|
|
|
Length -= sizeof(WCHAR);
|
|
|
|
|
|
|
|
/* Break out of the loop */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Advance to the next entry */
|
|
|
|
Entry = Entry->Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
BaseSetLastNTError(_SEH2_GetExceptionCode());
|
|
|
|
Length = 0;
|
|
|
|
} _SEH2_END
|
|
|
|
|
|
|
|
/* Release the loader lock */
|
2011-04-04 19:35:24 +00:00
|
|
|
LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
|
2011-04-03 09:42:08 +00:00
|
|
|
|
2011-04-03 21:46:42 +00:00
|
|
|
return Length / sizeof(WCHAR);
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
HMODULE
|
|
|
|
WINAPI
|
|
|
|
GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
PVOID Module;
|
|
|
|
LPWSTR DllPath;
|
|
|
|
|
|
|
|
/* Try to get a handle with a magic value of 1 for DllPath */
|
|
|
|
Status = LdrGetDllHandle((LPWSTR)1, NULL, ModuleName, &Module);
|
|
|
|
|
|
|
|
/* If that succeeded - we're done */
|
|
|
|
if (NT_SUCCESS(Status)) return Module;
|
|
|
|
|
|
|
|
/* If not, then the path should be computed */
|
2011-12-04 19:30:12 +00:00
|
|
|
DllPath = BaseComputeProcessDllPath(NULL, 0);
|
|
|
|
if (!DllPath)
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
2011-12-04 19:30:12 +00:00
|
|
|
Status = STATUS_NO_MEMORY;
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
2011-12-04 19:30:12 +00:00
|
|
|
else
|
2011-04-03 09:42:08 +00:00
|
|
|
{
|
2011-12-04 19:30:12 +00:00
|
|
|
_SEH2_TRY
|
|
|
|
{
|
|
|
|
Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module);
|
|
|
|
}
|
|
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
/* Fail with the SEH error */
|
|
|
|
Status = _SEH2_GetExceptionCode();
|
|
|
|
}
|
|
|
|
_SEH2_END;
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Free the DllPath */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* In case of error set last win32 error and return NULL */
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
DPRINT("Failure acquiring DLL module '%wZ' handle, Status 0x%08X\n", ModuleName, Status);
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2011-04-03 09:42:08 +00:00
|
|
|
Module = 0;
|
|
|
|
}
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return module */
|
|
|
|
return (HMODULE)Module;
|
2000-09-01 17:09:50 +00:00
|
|
|
}
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
BOOLEAN
|
|
|
|
WINAPI
|
|
|
|
BasepGetModuleHandleExW(BOOLEAN NoLock, DWORD dwPublicFlags, LPCWSTR lpwModuleName, HMODULE *phModule)
|
|
|
|
{
|
|
|
|
DWORD Cookie;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS, Status2;
|
|
|
|
HANDLE hModule = 0;
|
|
|
|
UNICODE_STRING ModuleNameU;
|
|
|
|
DWORD dwValid;
|
|
|
|
BOOLEAN Redirected = FALSE; // FIXME
|
|
|
|
|
|
|
|
/* Validate parameters */
|
|
|
|
dwValid = BasepGetModuleHandleExParameterValidation(dwPublicFlags, lpwModuleName, phModule);
|
|
|
|
ASSERT(dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE);
|
|
|
|
|
|
|
|
/* Acquire lock if necessary */
|
|
|
|
if (!NoLock)
|
|
|
|
{
|
|
|
|
Status = LdrLockLoaderLock(0, NULL, &Cookie);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
/* Fail */
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2011-04-03 09:42:08 +00:00
|
|
|
if (phModule) *phModule = 0;
|
2011-08-24 12:31:08 +00:00
|
|
|
return NT_SUCCESS(Status);
|
2011-04-03 09:42:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
|
|
|
|
{
|
|
|
|
/* Create a unicode string out of module name */
|
|
|
|
RtlInitUnicodeString(&ModuleNameU, lpwModuleName);
|
|
|
|
|
|
|
|
// FIXME: Do some redirected DLL stuff?
|
|
|
|
if (Redirected)
|
|
|
|
{
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hModule)
|
|
|
|
{
|
|
|
|
hModule = GetModuleHandleForUnicodeString(&ModuleNameU);
|
|
|
|
if (!hModule)
|
|
|
|
{
|
2011-04-04 19:35:24 +00:00
|
|
|
/* Last error is already set, so just return failure by setting status */
|
|
|
|
Status = STATUS_DLL_NOT_FOUND;
|
2011-04-03 09:42:08 +00:00
|
|
|
goto quickie;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Perform Pc to file header to get module instance */
|
|
|
|
hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpwModuleName,
|
|
|
|
(PVOID*)&hModule);
|
|
|
|
|
|
|
|
/* Check if it succeeded */
|
|
|
|
if (!hModule)
|
|
|
|
{
|
|
|
|
/* Set "dll not found" status and quit */
|
|
|
|
Status = STATUS_DLL_NOT_FOUND;
|
|
|
|
goto quickie;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check if changing reference is not forbidden */
|
|
|
|
if (!(dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))
|
|
|
|
{
|
|
|
|
/* Add reference to this DLL */
|
2011-07-10 07:15:26 +00:00
|
|
|
Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_ADDREF_DLL_PIN : 0,
|
2011-04-03 09:42:08 +00:00
|
|
|
hModule);
|
|
|
|
}
|
|
|
|
|
2011-04-04 19:35:24 +00:00
|
|
|
/* Set last error in case of failure */
|
|
|
|
if (!NT_SUCCESS(Status))
|
2011-07-23 18:54:29 +00:00
|
|
|
BaseSetLastNTError(Status);
|
2011-04-04 19:35:24 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
quickie:
|
|
|
|
/* Unlock loader lock if it was acquired */
|
|
|
|
if (!NoLock)
|
|
|
|
{
|
|
|
|
Status2 = LdrUnlockLoaderLock(0, Cookie);
|
|
|
|
ASSERT(NT_SUCCESS(Status2));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set the module handle to the caller */
|
|
|
|
if (phModule) *phModule = hModule;
|
|
|
|
|
|
|
|
/* Return TRUE on success and FALSE otherwise */
|
|
|
|
return NT_SUCCESS(Status);
|
|
|
|
}
|
2000-09-01 17:09:50 +00:00
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
1999-10-31 22:41:15 +00:00
|
|
|
HMODULE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-03 09:42:08 +00:00
|
|
|
GetModuleHandleA(LPCSTR lpModuleName)
|
1999-10-12 19:45:01 +00:00
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
PUNICODE_STRING ModuleNameW;
|
|
|
|
PTEB pTeb = NtCurrentTeb();
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Check if we have no name to convert */
|
|
|
|
if (!lpModuleName)
|
|
|
|
return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress);
|
1999-11-17 21:30:00 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Convert module name to unicode */
|
|
|
|
ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Call W version if conversion was successful */
|
|
|
|
if (ModuleNameW)
|
|
|
|
return GetModuleHandleW(ModuleNameW->Buffer);
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return failure */
|
|
|
|
return 0;
|
1999-10-31 22:41:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-10 18:50:51 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
2000-08-27 22:37:45 +00:00
|
|
|
HMODULE
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-03 09:42:08 +00:00
|
|
|
GetModuleHandleW(LPCWSTR lpModuleName)
|
2000-08-27 22:37:45 +00:00
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
HMODULE hModule;
|
|
|
|
NTSTATUS Status;
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* If current module is requested - return it right away */
|
|
|
|
if (!lpModuleName)
|
|
|
|
return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Use common helper routine */
|
|
|
|
Status = BasepGetModuleHandleExW(TRUE,
|
|
|
|
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
|
|
|
lpModuleName,
|
|
|
|
&hModule);
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* If it wasn't successful - return 0 */
|
|
|
|
if (!NT_SUCCESS(Status)) hModule = 0;
|
2000-08-27 22:37:45 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return the handle */
|
|
|
|
return hModule;
|
2000-08-27 22:37:45 +00:00
|
|
|
}
|
|
|
|
|
2004-05-03 14:34:44 +00:00
|
|
|
|
2006-01-12 04:31:37 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2006-01-12 04:31:37 +00:00
|
|
|
GetModuleHandleExW(IN DWORD dwFlags,
|
2011-04-03 09:42:08 +00:00
|
|
|
IN LPCWSTR lpwModuleName OPTIONAL,
|
2006-01-12 04:31:37 +00:00
|
|
|
OUT HMODULE* phModule)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
2011-04-03 09:42:08 +00:00
|
|
|
DWORD dwValid;
|
2006-01-12 04:31:37 +00:00
|
|
|
BOOL Ret = FALSE;
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Validate parameters */
|
|
|
|
dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule);
|
2006-01-12 04:31:37 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* If result is invalid parameter - return failure */
|
2011-04-04 19:35:24 +00:00
|
|
|
if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
|
2006-01-12 04:31:37 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* If result is 2, there is no need to do anything - return success. */
|
|
|
|
if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE;
|
2006-01-12 04:31:37 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Use common helper routine */
|
|
|
|
Status = BasepGetModuleHandleExW(FALSE,
|
|
|
|
dwFlags,
|
|
|
|
lpwModuleName,
|
|
|
|
phModule);
|
|
|
|
|
|
|
|
/* Return TRUE in case of success */
|
|
|
|
if (NT_SUCCESS(Status)) Ret = TRUE;
|
2006-01-12 04:31:37 +00:00
|
|
|
|
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
BOOL
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2006-01-12 04:31:37 +00:00
|
|
|
GetModuleHandleExA(IN DWORD dwFlags,
|
2011-04-03 09:42:08 +00:00
|
|
|
IN LPCSTR lpModuleName OPTIONAL,
|
2006-01-12 04:31:37 +00:00
|
|
|
OUT HMODULE* phModule)
|
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
PUNICODE_STRING lpModuleNameW;
|
|
|
|
DWORD dwValid;
|
2011-04-04 19:35:24 +00:00
|
|
|
BOOL Ret = FALSE;
|
|
|
|
NTSTATUS Status;
|
2006-01-12 04:31:37 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Validate parameters */
|
|
|
|
dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule);
|
2007-10-10 23:14:20 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* If result is invalid parameter - return failure */
|
2011-04-04 19:35:24 +00:00
|
|
|
if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
|
2011-04-03 09:42:08 +00:00
|
|
|
|
|
|
|
/* If result is 2, there is no need to do anything - return success. */
|
|
|
|
if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS) return TRUE;
|
|
|
|
|
|
|
|
/* Check if we don't need to convert the name */
|
2006-01-12 04:31:37 +00:00
|
|
|
if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
|
|
|
|
{
|
2011-04-04 19:35:24 +00:00
|
|
|
/* Call the extended version of the API without conversion */
|
|
|
|
Status = BasepGetModuleHandleExW(FALSE,
|
|
|
|
dwFlags,
|
|
|
|
(LPCWSTR)lpModuleName,
|
|
|
|
phModule);
|
2006-01-12 04:31:37 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Convert module name to unicode */
|
|
|
|
lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
|
2007-10-10 23:14:20 +00:00
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return FALSE if conversion failed */
|
|
|
|
if (!lpModuleNameW) return FALSE;
|
2006-01-12 04:31:37 +00:00
|
|
|
|
2011-04-04 19:35:24 +00:00
|
|
|
/* Call the extended version of the API */
|
|
|
|
Status = BasepGetModuleHandleExW(FALSE,
|
|
|
|
dwFlags,
|
|
|
|
lpModuleNameW->Buffer,
|
|
|
|
phModule);
|
2006-01-12 04:31:37 +00:00
|
|
|
}
|
|
|
|
|
2011-04-04 19:35:24 +00:00
|
|
|
/* If result was successful - return true */
|
|
|
|
if (NT_SUCCESS(Status))
|
|
|
|
Ret = TRUE;
|
|
|
|
|
2011-04-03 09:42:08 +00:00
|
|
|
/* Return result */
|
2006-01-12 04:31:37 +00:00
|
|
|
return Ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-03 14:34:44 +00:00
|
|
|
/*
|
|
|
|
* @implemented
|
|
|
|
*/
|
|
|
|
DWORD
|
2008-11-30 11:42:05 +00:00
|
|
|
WINAPI
|
2011-04-06 19:03:20 +00:00
|
|
|
LoadModule(LPCSTR lpModuleName,
|
|
|
|
LPVOID lpParameterBlock)
|
2004-05-03 14:34:44 +00:00
|
|
|
{
|
2011-04-06 19:03:20 +00:00
|
|
|
STARTUPINFOA StartupInfo;
|
|
|
|
PROCESS_INFORMATION ProcessInformation;
|
|
|
|
LOADPARMS32 *LoadParams;
|
|
|
|
char FileName[MAX_PATH];
|
|
|
|
LPSTR CommandLine;
|
|
|
|
DWORD Length, Error;
|
|
|
|
BOOL ProcessStatus;
|
|
|
|
ANSI_STRING AnsiStr;
|
|
|
|
UNICODE_STRING UnicStr;
|
|
|
|
RTL_PATH_TYPE PathType;
|
|
|
|
HANDLE Handle;
|
|
|
|
|
|
|
|
LoadParams = (LOADPARMS32*)lpParameterBlock;
|
|
|
|
|
|
|
|
/* Check load parameters */
|
|
|
|
if (LoadParams->dwReserved || LoadParams->wMagicValue != 2)
|
|
|
|
{
|
|
|
|
/* Fail with invalid param error */
|
|
|
|
BaseSetLastNTError(STATUS_INVALID_PARAMETER);
|
|
|
|
return 0;
|
2004-05-03 14:34:44 +00:00
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Search path */
|
|
|
|
Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL);
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Check if path was found */
|
|
|
|
if (Length && Length < MAX_PATH)
|
|
|
|
{
|
|
|
|
/* Build StartupInfo */
|
|
|
|
RtlZeroMemory(&StartupInfo, sizeof(StartupInfo));
|
|
|
|
|
|
|
|
StartupInfo.cb = sizeof(STARTUPINFOA);
|
|
|
|
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
|
|
|
|
StartupInfo.wShowWindow = LoadParams->wCmdShow;
|
|
|
|
|
|
|
|
/* Allocate command line buffer */
|
|
|
|
CommandLine = RtlAllocateHeap(RtlGetProcessHeap(),
|
|
|
|
HEAP_ZERO_MEMORY,
|
|
|
|
(ULONG)LoadParams->lpCmdLine[0] + Length + 2);
|
|
|
|
|
|
|
|
/* Put module name there, then a space, and then copy provided command line,
|
|
|
|
and null-terminate it */
|
|
|
|
RtlCopyMemory(CommandLine, FileName, Length);
|
|
|
|
CommandLine[Length] = ' ';
|
|
|
|
RtlCopyMemory(&CommandLine[Length + 1], &LoadParams->lpCmdLine[1], (ULONG)LoadParams->lpCmdLine[0]);
|
|
|
|
CommandLine[Length + 1 + (ULONG)LoadParams->lpCmdLine[0]] = 0;
|
|
|
|
|
|
|
|
/* Create the process */
|
|
|
|
ProcessStatus = CreateProcessA(FileName,
|
|
|
|
CommandLine,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
FALSE,
|
|
|
|
0,
|
|
|
|
LoadParams->lpEnvAddress,
|
|
|
|
NULL,
|
|
|
|
&StartupInfo,
|
|
|
|
&ProcessInformation);
|
|
|
|
|
|
|
|
/* Free the command line buffer */
|
|
|
|
RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine);
|
|
|
|
|
|
|
|
if (!ProcessStatus)
|
|
|
|
{
|
|
|
|
/* Creating process failed, return right error code */
|
|
|
|
Error = GetLastError();
|
|
|
|
switch(Error)
|
|
|
|
{
|
|
|
|
case ERROR_BAD_EXE_FORMAT:
|
|
|
|
return ERROR_BAD_FORMAT;
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
case ERROR_FILE_NOT_FOUND:
|
|
|
|
case ERROR_PATH_NOT_FOUND:
|
|
|
|
return Error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 0 otherwise */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Wait up to 30 seconds for the process to become idle */
|
[KERNEL32]: Changes to proc.c:
- ReadProcessMemory/WriteProcessMemory only write to *lpNumberOfBytesRead/Written if user-mode passed in the parameter, as its an optional argument in Win32, but not in NT. Instead, use a local variable. This means that anyone calling ReadProcessMemory/WriteProcessMemory in ReactOS before with a NULL output argument (totally valid) was getting an error before!
- WriteProcessMemory actually returns STATUS_ACCESS_VIOLATION in a few cases, even if it's defined as a BOOL function. Code on Google shows major applications depending on this, which we weren't doing.
- Rewrite InitCommandLines to be much simpler. No normalization or copying or ANSi/OEM logic is needed.
- GetProcessAffinityMask should use the BaseStaticServerData from CSRSS instead of querying system information each time.
- GetProcessShutdownParameters and SetProcessShutdownParameters should use the LPC status code from CSRSS, not the LPC API status code.
- GetProcessWorkingSetSize now calls GetProcessWorkingSetSizeEx.
- Implement GetProcessWorkingSetSizeEx.
- SetProcessWorkingSetSize now calls SetProcessWorkingSetSizeEx.
- Implement SetProcessWorkingSetSizeEx.
- Acquire the required privilege in SetProcessWorkingSetSize(Ex).
- Fail with correct status code in SetProcessWorkingSetSize(Ex).
- GetExitCodeProcess should check if this is a VDM process and get the exit code that way.
- GetStartupInfoW should not fail if the input is NULL. It should crash.
- GetStartupInfoW was not filling out the lpReserved field, which should contain the ShellInfo buffer.
- GetStartupInfoW was always setting standard handles -- it should not do so if those are console handles.
- GetStartupInfoA was not thread-safe.
- GetStartupInfoA was assuming all Unicode->ANSI conversions will be successful.
- GetStartupInfoA was not filling out lpReserved either.
- ExitProcess was not using SEH and was not using the PEB lock.
- TerminateProcess was not setting ERROR_INVALID_HANDLE last error code.
- FatalAppExitA was not using static TEB buffer, and was always assuming success.
- FatalAppExitW was doing some sort of bizarre hack. It now raises as a hard error as it should.
- FatalExit now displays a debugger input interface on checked builds, just like Windows.
- SetPriorityClass now tries to acquire the real time privilege when needed, and handles failure to do so.
- GetProcessVersion rewritten to be cleaner and simpler.
- Annotate and reformat functions where needed.
- Rename lpfnGlobalRegisterWaitForInputIdle to UserWaitForInputIdleRoutine
- GetProcessPriorityBoost is now BOOL-safe.
- IsWow64Process now sets NT error code using only one API.
- CommandLineStringA/W -> BaseAnsiCommandLine/BaseUnicodeCommandLine.
svn path=/trunk/; revision=55092
2012-01-23 04:57:12 +00:00
|
|
|
if (UserWaitForInputIdleRoutine)
|
2011-04-06 19:03:20 +00:00
|
|
|
{
|
[KERNEL32]: Changes to proc.c:
- ReadProcessMemory/WriteProcessMemory only write to *lpNumberOfBytesRead/Written if user-mode passed in the parameter, as its an optional argument in Win32, but not in NT. Instead, use a local variable. This means that anyone calling ReadProcessMemory/WriteProcessMemory in ReactOS before with a NULL output argument (totally valid) was getting an error before!
- WriteProcessMemory actually returns STATUS_ACCESS_VIOLATION in a few cases, even if it's defined as a BOOL function. Code on Google shows major applications depending on this, which we weren't doing.
- Rewrite InitCommandLines to be much simpler. No normalization or copying or ANSi/OEM logic is needed.
- GetProcessAffinityMask should use the BaseStaticServerData from CSRSS instead of querying system information each time.
- GetProcessShutdownParameters and SetProcessShutdownParameters should use the LPC status code from CSRSS, not the LPC API status code.
- GetProcessWorkingSetSize now calls GetProcessWorkingSetSizeEx.
- Implement GetProcessWorkingSetSizeEx.
- SetProcessWorkingSetSize now calls SetProcessWorkingSetSizeEx.
- Implement SetProcessWorkingSetSizeEx.
- Acquire the required privilege in SetProcessWorkingSetSize(Ex).
- Fail with correct status code in SetProcessWorkingSetSize(Ex).
- GetExitCodeProcess should check if this is a VDM process and get the exit code that way.
- GetStartupInfoW should not fail if the input is NULL. It should crash.
- GetStartupInfoW was not filling out the lpReserved field, which should contain the ShellInfo buffer.
- GetStartupInfoW was always setting standard handles -- it should not do so if those are console handles.
- GetStartupInfoA was not thread-safe.
- GetStartupInfoA was assuming all Unicode->ANSI conversions will be successful.
- GetStartupInfoA was not filling out lpReserved either.
- ExitProcess was not using SEH and was not using the PEB lock.
- TerminateProcess was not setting ERROR_INVALID_HANDLE last error code.
- FatalAppExitA was not using static TEB buffer, and was always assuming success.
- FatalAppExitW was doing some sort of bizarre hack. It now raises as a hard error as it should.
- FatalExit now displays a debugger input interface on checked builds, just like Windows.
- SetPriorityClass now tries to acquire the real time privilege when needed, and handles failure to do so.
- GetProcessVersion rewritten to be cleaner and simpler.
- Annotate and reformat functions where needed.
- Rename lpfnGlobalRegisterWaitForInputIdle to UserWaitForInputIdleRoutine
- GetProcessPriorityBoost is now BOOL-safe.
- IsWow64Process now sets NT error code using only one API.
- CommandLineStringA/W -> BaseAnsiCommandLine/BaseUnicodeCommandLine.
svn path=/trunk/; revision=55092
2012-01-23 04:57:12 +00:00
|
|
|
UserWaitForInputIdleRoutine(ProcessInformation.hProcess, 30000);
|
2011-04-06 19:03:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Close handles */
|
|
|
|
NtClose(ProcessInformation.hThread);
|
|
|
|
NtClose(ProcessInformation.hProcess);
|
|
|
|
|
|
|
|
/* Return magic success value (33) */
|
|
|
|
return 33;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The path was not found, create an ansi string from
|
|
|
|
the module name and convert it to unicode */
|
|
|
|
RtlInitAnsiString(&AnsiStr, lpModuleName);
|
|
|
|
if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&UnicStr,&AnsiStr,TRUE)))
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
|
|
|
|
|
|
/* Determine path type */
|
|
|
|
PathType = RtlDetermineDosPathNameType_U(UnicStr.Buffer);
|
|
|
|
|
|
|
|
/* Free the unicode module name */
|
|
|
|
RtlFreeUnicodeString(&UnicStr);
|
|
|
|
|
|
|
|
/* If it's a relative path, return file not found */
|
|
|
|
if (PathType == RtlPathTypeRelative)
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
|
|
|
|
|
|
/* If not, try to open it */
|
|
|
|
Handle = CreateFile(lpModuleName,
|
|
|
|
GENERIC_READ,
|
|
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
|
|
NULL,
|
|
|
|
OPEN_EXISTING,
|
|
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (Handle != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
/* Opening file succeeded for some reason, close the handle and return file not found anyway */
|
|
|
|
CloseHandle(Handle);
|
|
|
|
return ERROR_FILE_NOT_FOUND;
|
|
|
|
}
|
2005-05-09 01:46:57 +00:00
|
|
|
|
2011-04-06 19:03:20 +00:00
|
|
|
/* Return last error which CreateFile set during an attempt to open it */
|
|
|
|
return GetLastError();
|
2004-05-03 14:34:44 +00:00
|
|
|
}
|
|
|
|
|
2011-07-22 02:13:57 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
FARPROC WINAPI DelayLoadFailureHook(LPCSTR pszDllName, LPCSTR pszProcName)
|
|
|
|
{
|
|
|
|
STUB;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
BOOL WINAPI UTRegister( HMODULE hModule, LPSTR lpsz16BITDLL,
|
|
|
|
LPSTR lpszInitName, LPSTR lpszProcName,
|
|
|
|
FARPROC *ppfn32Thunk, FARPROC pfnUT32CallBack,
|
|
|
|
LPVOID lpBuff )
|
|
|
|
{
|
|
|
|
STUB;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
VOID WINAPI UTUnRegister( HMODULE hModule )
|
|
|
|
{
|
|
|
|
STUB;
|
|
|
|
}
|
|
|
|
|
2011-11-03 00:30:44 +00:00
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
BOOL
|
|
|
|
WINAPI
|
|
|
|
BaseQueryModuleData(IN LPSTR ModuleName,
|
|
|
|
IN LPSTR Unknown,
|
|
|
|
IN PVOID Unknown2,
|
|
|
|
IN PVOID Unknown3,
|
|
|
|
IN PVOID Unknown4)
|
|
|
|
{
|
|
|
|
DPRINT1("BaseQueryModuleData called: %s %s %x %x %x\n",
|
|
|
|
ModuleName,
|
|
|
|
Unknown,
|
|
|
|
Unknown2,
|
|
|
|
Unknown3,
|
|
|
|
Unknown4);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @unimplemented
|
|
|
|
*/
|
|
|
|
NTSTATUS
|
|
|
|
WINAPI
|
|
|
|
BaseProcessInitPostImport(VOID)
|
|
|
|
{
|
|
|
|
/* FIXME: Initialize TS pointers */
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
1999-10-31 22:41:15 +00:00
|
|
|
/* EOF */
|