-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT : ReactOS user mode libraries
+ * PROJECT : ReactOS system libraries
* MODULE : kernel32.dll
- * FILE : reactos/lib/kernel32/misc/ldr.c
- * AUTHOR : Ariadne
+ * FILE : reactos/dll/win32/kernel32/misc/ldr.c
+ * AUTHOR : Aleksey Bragin <aleksey@reactos.org>
*/
#include <k32.h>
typedef struct tagLOADPARMS32 {
LPSTR lpEnvAddress;
LPSTR lpCmdLine;
- LPSTR lpCmdShow;
+ WORD wMagicValue;
+ WORD wCmdShow;
DWORD dwReserved;
} LOADPARMS32;
extern BOOLEAN InWindows;
extern WaitForInputIdleType lpfnGlobalRegisterWaitForInputIdle;
+#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR 1
+#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_SUCCESS 2
+#define BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_CONTINUE 3
+
+VOID
+NTAPI
+BasepLocateExeLdrEntry(IN PLDR_DATA_TABLE_ENTRY Entry,
+ IN PVOID Context,
+ OUT BOOLEAN *StopEnumeration);
+
/* FUNCTIONS ****************************************************************/
+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) ||
+ ((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) &&
+ (dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ||
+ (!lpwModuleName && (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS))
+ )
+ {
+ BaseSetLastNTError(STATUS_INVALID_PARAMETER_1);
+ return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
+ }
+
+ /* Check 2nd parameter */
+ if (!phModule)
+ {
+ BaseSetLastNTError(STATUS_INVALID_PARAMETER_2);
+ return BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR;
+ }
+
+ /* 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;
+}
+
+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;
+}
+
/**
* @name GetDllLoadPath
*
UNICODE_STRING ModuleName;
DWORD LastError = GetLastError(); /* GetEnvironmentVariable changes LastError */
+ // FIXME: This function is used only by SearchPathW, and is deprecated and will be deleted ASAP.
+
if ((lpModule != NULL) && (wcslen(lpModule) > 2) && (lpModule[1] == ':'))
{
lpModuleEnd = lpModule + wcslen(lpModule);
*/
BOOL
WINAPI
-DisableThreadLibraryCalls (
- HMODULE hLibModule
- )
+DisableThreadLibraryCalls(
+ IN HMODULE hLibModule)
{
- NTSTATUS Status;
+ NTSTATUS Status;
- Status = LdrDisableThreadCalloutsForDll ((PVOID)hLibModule);
- if (!NT_SUCCESS (Status))
- {
- SetLastErrorByStatus (Status);
- return FALSE;
- }
- return TRUE;
+ /* Disable thread library calls */
+ Status = LdrDisableThreadCalloutsForDll((PVOID)hLibModule);
+
+ /* If it wasn't success - set last error and return failure */
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return FALSE;
+ }
+
+ /* Return success */
+ return TRUE;
}
*/
HINSTANCE
WINAPI
-LoadLibraryA (
- LPCSTR lpLibFileName
- )
+LoadLibraryA(LPCSTR lpLibFileName)
{
- return LoadLibraryExA (lpLibFileName, 0, 0);
-}
+ 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;
+ }
+ }
+
+ /* Free allocated buffer */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
+ }
+ }
+
+ /* Call the Ex version of the API */
+ return LoadLibraryExA(lpLibFileName, 0, 0);
+}
/*
* @implemented
*/
HINSTANCE
WINAPI
-LoadLibraryExA (
- LPCSTR lpLibFileName,
- HANDLE hFile,
- DWORD dwFlags
- )
+LoadLibraryExA(LPCSTR lpLibFileName,
+ HANDLE hFile,
+ DWORD dwFlags)
{
- PWCHAR FileNameW;
+ PUNICODE_STRING FileNameW;
- if (!(FileNameW = FilenameA2W(lpLibFileName, FALSE)))
- return FALSE;
+ /* Convert file name to unicode */
+ if (!(FileNameW = Basep8BitStringToStaticUnicodeString(lpLibFileName)))
+ return NULL;
- return LoadLibraryExW(FileNameW, hFile, dwFlags);
+ /* And call W version of the API */
+ return LoadLibraryExW(FileNameW->Buffer, hFile, dwFlags);
}
-
/*
* @implemented
*/
HINSTANCE
WINAPI
-LoadLibraryW (
- LPCWSTR lpLibFileName
- )
+LoadLibraryW(LPCWSTR lpLibFileName)
{
- return LoadLibraryExW (lpLibFileName, 0, 0);
+ /* Call Ex version of the API */
+ return LoadLibraryExW (lpLibFileName, 0, 0);
}
static
NTSTATUS
-LoadLibraryAsDatafile(PWSTR path, LPCWSTR name, HMODULE* hmod)
+BasepLoadLibraryAsDatafile(PWSTR Path, LPCWSTR Name, HMODULE *hModule)
{
- static const WCHAR dotDLL[] = {'.','d','l','l',0};
-
- WCHAR filenameW[MAX_PATH];
+ WCHAR FilenameW[MAX_PATH];
HANDLE hFile = INVALID_HANDLE_VALUE;
- HANDLE mapping;
- HMODULE module;
-
- *hmod = 0;
-
- if (!SearchPathW( path, name, dotDLL, sizeof(filenameW) / sizeof(filenameW[0]),
- filenameW, NULL ))
+ HANDLE hMapping;
+ NTSTATUS Status;
+ PVOID lpBaseAddress = NULL;
+ SIZE_T ViewSize = 0;
+ //PUNICODE_STRING OriginalName;
+ //UNICODE_STRING dotDLL = RTL_CONSTANT_STRING(L".DLL");
+
+ /* Zero out handle value */
+ *hModule = 0;
+
+ DPRINT("BasepLoadLibraryAsDatafile(%S %S %p)\n", Path, Name, hModule);
+
+ /*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))
{
+ /* Return last status value directly */
return NtCurrentTeb()->LastStatusValue;
}
- hFile = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, 0, 0 );
+ /* Open this file we found */
+ hFile = CreateFileW(FilenameW,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ 0,
+ 0);
+ /* If opening failed - return last status value */
if (hFile == INVALID_HANDLE_VALUE) return NtCurrentTeb()->LastStatusValue;
- mapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
- CloseHandle( hFile );
- if (!mapping) return NtCurrentTeb()->LastStatusValue;
+ /* Create file mapping */
+ hMapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
+
+ /* Close the file handle */
+ CloseHandle(hFile);
+
+ /* If creating file mapping failed - return last status value */
+ if (!hMapping) return NtCurrentTeb()->LastStatusValue;
- module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
- CloseHandle( mapping );
- if (!module) return NtCurrentTeb()->LastStatusValue;
+ /* Map view of section */
+ Status = NtMapViewOfSection(hMapping,
+ NtCurrentProcess(),
+ &lpBaseAddress,
+ 0,
+ 0,
+ 0,
+ &ViewSize,
+ ViewShare,
+ 0,
+ PAGE_READONLY);
- /* make sure it's a valid PE file */
- if (!RtlImageNtHeader(module))
+ /* 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))
{
- UnmapViewOfFile( module );
+ /* Unmap the view and return failure status */
+ UnmapViewOfFile(lpBaseAddress);
return STATUS_INVALID_IMAGE_FORMAT;
}
- *hmod = (HMODULE)((char *)module + 1); /* set low bit of handle to indicate datafile module */
+
+ /* Set low bit of handle to indicate datafile module */
+ *hModule = (HMODULE)((ULONG_PTR)lpBaseAddress | 1);
+
+ /* Load alternate resource module */
+ //LdrLoadAlternateResourceModule(*hModule, FilenameW);
+
return STATUS_SUCCESS;
}
-
/*
* @implemented
*/
HINSTANCE
WINAPI
-LoadLibraryExW (
- LPCWSTR lpLibFileName,
- HANDLE hFile,
- DWORD dwFlags
- )
+LoadLibraryExW(LPCWSTR lpLibFileName,
+ HANDLE hFile,
+ DWORD dwFlags)
{
- UNICODE_STRING DllName;
- HINSTANCE hInst;
- NTSTATUS Status;
- PWSTR SearchPath;
- ULONG DllCharacteristics;
- BOOL FreeString = FALSE;
-
- (void)hFile;
-
- if ( lpLibFileName == NULL )
- return NULL;
+ UNICODE_STRING DllName;
+ HINSTANCE hInst;
+ NTSTATUS Status;
+ PWSTR SearchPath;
+ ULONG DllCharacteristics = 0;
+ BOOL FreeString = FALSE;
/* Check for any flags LdrLoadDll might be interested in */
if (dwFlags & DONT_RESOLVE_DLL_REFERENCES)
DllCharacteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
}
- dwFlags &=
- DONT_RESOLVE_DLL_REFERENCES |
- LOAD_LIBRARY_AS_DATAFILE |
- LOAD_WITH_ALTERED_SEARCH_PATH;
-
- SearchPath = GetDllLoadPath(
- dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH ? lpLibFileName : NULL);
+ /* Build up a unicode dll name from null-terminated string */
+ RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
- RtlInitUnicodeString(&DllName, (LPWSTR)lpLibFileName);
+ /* Lazy-initialize BasepExeLdrEntry */
+ if (!BasepExeLdrEntry)
+ LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, NtCurrentPeb()->ImageBaseAddress);
- if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
- {
- RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName);
- while (DllName.Length > sizeof(WCHAR) &&
- DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
- {
- DllName.Length -= sizeof(WCHAR);
- }
- DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL;
- FreeString = TRUE;
- }
+ /* 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;
+ }
+ }
- if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
+ /* Check for trailing spaces and remove them if necessary */
+ if (DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
{
- Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst);
- if (!NT_SUCCESS(Status))
+ RtlCreateUnicodeString(&DllName, (LPWSTR)lpLibFileName);
+ while (DllName.Length > sizeof(WCHAR) &&
+ DllName.Buffer[DllName.Length/sizeof(WCHAR) - 1] == L' ')
{
- /* The method in load_library_as_datafile allows searching for the
- * 'native' libraries only
- */
- Status = LoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst);
- goto done;
+ DllName.Length -= sizeof(WCHAR);
}
+ DllName.Buffer[DllName.Length/sizeof(WCHAR)] = UNICODE_NULL;
+ FreeString = TRUE;
}
- /* HACK!!! FIXME */
- if (InWindows)
+ /* Compute the load path */
+ SearchPath = BasepGetDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? (LPWSTR)lpLibFileName : NULL,
+ NULL);
+
+ if (!SearchPath)
{
- /* Call the API Properly */
- Status = LdrLoadDll(SearchPath,
- &DllCharacteristics,
- &DllName,
- (PVOID*)&hInst);
+ /* Getting DLL path failed, so set last error, free mem and return */
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ if (FreeString) RtlFreeUnicodeString(&DllName);
+ return NULL;
}
- else
+
+ _SEH2_TRY
{
- /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */
- Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst);
+ if (dwFlags & LOAD_LIBRARY_AS_DATAFILE)
+ {
+ /* If the image is loaded as a datafile, try to get its handle */
+ Status = LdrGetDllHandle(SearchPath, NULL, &DllName, (PVOID*)&hInst);
+ if (!NT_SUCCESS(Status))
+ {
+ /* It's not loaded yet - so load it up */
+ Status = BasepLoadLibraryAsDatafile(SearchPath, DllName.Buffer, &hInst);
+ _SEH2_YIELD(goto done;)
+ }
+ }
+
+ /* HACK!!! FIXME */
+ if (InWindows)
+ {
+ /* Call the API Properly */
+ Status = LdrLoadDll(SearchPath,
+ &DllCharacteristics,
+ &DllName,
+ (PVOID*)&hInst);
+ }
+ else
+ {
+ /* Call the ROS API. NOTE: Don't fix this, I have a patch to merge later. */
+ Status = LdrLoadDll(SearchPath, &dwFlags, &DllName, (PVOID*)&hInst);
+ }
}
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ } _SEH2_END
+
done:
- RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath);
- if (FreeString)
- RtlFreeUnicodeString(&DllName);
- if ( !NT_SUCCESS(Status))
- {
- SetLastErrorByStatus (Status);
- return NULL;
- }
+ /* 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 */
+ if (!NT_SUCCESS(Status))
+ {
+ BaseSetLastNTError(Status);
+ return NULL;
+ }
- return hInst;
+ /* Return loaded module handle */
+ return hInst;
}
*/
FARPROC
WINAPI
-GetProcAddress( HMODULE hModule, LPCSTR lpProcName )
+GetProcAddress(HMODULE hModule, LPCSTR lpProcName)
{
- ANSI_STRING ProcedureName;
- FARPROC fnExp = NULL;
- NTSTATUS Status;
+ ANSI_STRING ProcedureName, *ProcNamePtr = NULL;
+ FARPROC fnExp = NULL;
+ NTSTATUS Status;
+ PVOID hMapped;
+ ULONG Ordinal = 0;
- if (HIWORD(lpProcName) != 0)
- {
- RtlInitAnsiString (&ProcedureName,
- (LPSTR)lpProcName);
- Status = LdrGetProcedureAddress ((PVOID)hModule,
- &ProcedureName,
- 0,
- (PVOID*)&fnExp);
- }
- else
- {
- Status = LdrGetProcedureAddress ((PVOID)hModule,
- NULL,
- (ULONG)lpProcName,
- (PVOID*)&fnExp);
- }
+ if (HIWORD(lpProcName) != 0)
+ {
+ /* Look up by name */
+ RtlInitAnsiString(&ProcedureName, (LPSTR)lpProcName);
+ ProcNamePtr = &ProcedureName;
+ }
+ else
+ {
+ /* Look up by ordinal */
+ Ordinal = (ULONG)lpProcName;
+ }
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- fnExp = NULL;
- }
+ /* Map provided handle */
+ hMapped = BasepMapModuleHandle(hModule, FALSE);
- return fnExp;
+ /* Get the proc address */
+ Status = LdrGetProcedureAddress(hMapped,
+ ProcNamePtr,
+ Ordinal,
+ (PVOID*)&fnExp);
+
+ 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;
}
BOOL WINAPI FreeLibrary(HINSTANCE hLibModule)
{
NTSTATUS Status;
+ PIMAGE_NT_HEADERS NtHeaders;
- if (!hLibModule)
+ if (LDR_IS_DATAFILE(hLibModule))
{
- SetLastError(ERROR_INVALID_HANDLE);
- return FALSE;
- }
+ // 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 ((ULONG_PTR)hLibModule & 1)
+ if (NtHeaders)
+ {
+ /* Unmap view */
+ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
+
+ /* Unload alternate resource module */
+ LdrUnloadAlternateResourceModule(hLibModule);
+ }
+ else
+ Status = STATUS_INVALID_IMAGE_FORMAT;
+ }
+ else
{
- /* this is a LOAD_LIBRARY_AS_DATAFILE module */
- char *ptr = (char *)hLibModule - 1;
- UnmapViewOfFile(ptr);
- return TRUE;
+ /* Just unload it */
+ Status = LdrUnloadDll((PVOID)hLibModule);
}
- Status = LdrUnloadDll(hLibModule);
+ /* Check what kind of status we got */
if (!NT_SUCCESS(Status))
{
- SetLastErrorByStatus(Status);
+ /* Set last error */
+ BaseSetLastNTError(Status);
+
+ /* Return failure */
return FALSE;
}
+ /* Return success */
return TRUE;
}
*/
VOID
WINAPI
-FreeLibraryAndExitThread (
- HMODULE hLibModule,
- DWORD dwExitCode
- )
+FreeLibraryAndExitThread(HMODULE hLibModule,
+ DWORD dwExitCode)
{
- FreeLibrary(hLibModule);
+ NTSTATUS Status;
+
+ if (LDR_IS_DATAFILE(hLibModule))
+ {
+ /* This is a LOAD_LIBRARY_AS_DATAFILE module */
+ if (RtlImageNtHeader((PVOID)((ULONG_PTR)hLibModule & ~1)))
+ {
+ /* Unmap view */
+ Status = NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)((ULONG_PTR)hLibModule & ~1));
+
+ /* Unload alternate resource module */
+ LdrUnloadAlternateResourceModule(hLibModule);
+ }
+ }
+ else
+ {
+ /* Just unload it */
+ Status = LdrUnloadDll((PVOID)hLibModule);
+ }
+
+ /* Exit thread */
ExitThread(dwExitCode);
}
*/
DWORD
WINAPI
-GetModuleFileNameA (
- HINSTANCE hModule,
- LPSTR lpFilename,
- DWORD nSize
- )
+GetModuleFileNameA(HINSTANCE hModule,
+ LPSTR lpFilename,
+ DWORD nSize)
{
- ANSI_STRING FileName;
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- PPEB Peb;
- ULONG Length = 0;
+ UNICODE_STRING FilenameW;
+ ANSI_STRING FilenameA;
+ NTSTATUS Status;
+ DWORD Length = 0, LengthToCopy;
- Peb = NtCurrentPeb ();
- RtlEnterCriticalSection (Peb->LoaderLock);
+ /* Allocate a unicode buffer */
+ FilenameW.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, nSize * sizeof(WCHAR));
+ if (!FilenameW.Buffer)
+ {
+ BaseSetLastNTError(STATUS_NO_MEMORY);
+ return 0;
+ }
- if (hModule == NULL)
- hModule = Peb->ImageBaseAddress;
+ /* Call unicode API */
+ FilenameW.Length = GetModuleFileNameW(hModule, FilenameW.Buffer, nSize) * sizeof(WCHAR);
+ FilenameW.MaximumLength = FilenameW.Length + sizeof(WCHAR);
- ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
+ if (FilenameW.Length)
+ {
+ /* Convert to ansi string */
+ Status = BasepUnicodeStringTo8BitString(&FilenameA, &FilenameW, TRUE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Set last error, free string and retun failure */
+ BaseSetLastNTError(Status);
+ RtlFreeUnicodeString(&FilenameW);
+ return 0;
+ }
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
- if (Module->DllBase == (PVOID)hModule)
- {
- Length = min(nSize, Module->FullDllName.Length / sizeof(WCHAR));
- FileName.Length = 0;
- FileName.MaximumLength = (USHORT)Length * sizeof(WCHAR);
- FileName.Buffer = lpFilename;
-
- /* convert unicode string to ansi (or oem) */
- if (bIsFileApiAnsi)
- RtlUnicodeStringToAnsiString (&FileName,
- &Module->FullDllName,
- FALSE);
- else
- RtlUnicodeStringToOemString (&FileName,
- &Module->FullDllName,
- FALSE);
-
- if (nSize < Length)
- SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
- else
- lpFilename[Length] = '\0';
-
- RtlLeaveCriticalSection (Peb->LoaderLock);
- return Length;
- }
+ /* Calculate size to copy */
+ Length = min(nSize, FilenameA.Length);
- Entry = Entry->Flink;
- }
+ /* Include terminating zero */
+ if (nSize > Length)
+ LengthToCopy = Length + 1;
+ else
+ LengthToCopy = nSize;
- SetLastErrorByStatus (STATUS_DLL_NOT_FOUND);
- RtlLeaveCriticalSection (Peb->LoaderLock);
+ /* Now copy back to the caller amount he asked */
+ RtlMoveMemory(lpFilename, FilenameA.Buffer, LengthToCopy);
- return 0;
-}
+ /* Free ansi filename */
+ RtlFreeAnsiString(&FilenameA);
+ }
+
+ /* Free unicode filename */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, FilenameW.Buffer);
+ /* Return length copied */
+ return Length;
+}
/*
* @implemented
*/
DWORD
WINAPI
-GetModuleFileNameW (
- HINSTANCE hModule,
- LPWSTR lpFilename,
- DWORD nSize
- )
+GetModuleFileNameW(HINSTANCE hModule,
+ LPWSTR lpFilename,
+ DWORD nSize)
{
- UNICODE_STRING FileName;
- PLIST_ENTRY ModuleListHead;
- PLIST_ENTRY Entry;
- PLDR_DATA_TABLE_ENTRY Module;
- PPEB Peb;
- ULONG Length = 0;
-
- Peb = NtCurrentPeb ();
- RtlEnterCriticalSection (Peb->LoaderLock);
-
- if (hModule == NULL)
- hModule = Peb->ImageBaseAddress;
-
- ModuleListHead = &Peb->Ldr->InLoadOrderModuleList;
- Entry = ModuleListHead->Flink;
- while (Entry != ModuleListHead)
- {
- Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
+ PLIST_ENTRY ModuleListHead, Entry;
+ PLDR_DATA_TABLE_ENTRY Module;
+ ULONG Length = 0;
+ ULONG Cookie;
+ PPEB Peb;
- if (Module->DllBase == (PVOID)hModule)
- {
- Length = min(nSize, Module->FullDllName.Length / sizeof(WCHAR));
- FileName.Length = 0;
- FileName.MaximumLength = (USHORT) Length * sizeof(WCHAR);
- FileName.Buffer = lpFilename;
+ hModule = BasepMapModuleHandle(hModule, FALSE);
- RtlCopyUnicodeString (&FileName,
- &Module->FullDllName);
- if (nSize < Length)
- SetLastErrorByStatus (STATUS_BUFFER_TOO_SMALL);
- else
- lpFilename[Length] = L'\0';
+ /* Upscale nSize from chars to bytes */
+ nSize *= sizeof(WCHAR);
- RtlLeaveCriticalSection (Peb->LoaderLock);
+ _SEH2_TRY
+ {
+ /* We don't use per-thread cur dir now */
+ //PRTL_PERTHREAD_CURDIR PerThreadCurdir = (PRTL_PERTHREAD_CURDIR)teb->NtTib.SubSystemTib;
- return Length;
- }
+ Peb = NtCurrentPeb ();
- Entry = Entry->Flink;
- }
+ /* Acquire a loader lock */
+ LdrLockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, NULL, &Cookie);
+
+ /* 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);
- SetLastErrorByStatus (STATUS_DLL_NOT_FOUND);
- RtlLeaveCriticalSection (Peb->LoaderLock);
+ /* Copy contents */
+ RtlMoveMemory(lpFilename, Module->FullDllName.Buffer, Length);
- return 0;
+ /* 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 */
+ LdrUnlockLoaderLock(LDR_LOCK_LOADER_LOCK_FLAG_RAISE_ON_ERRORS, Cookie);
+
+ return Length / sizeof(WCHAR);
}
+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 */
+ DllPath = BasepGetDllPath(NULL, 0);
+
+ /* Call LdrGetHandle() again providing the computed DllPath
+ and wrapped into SEH */
+ _SEH2_TRY
+ {
+ Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* Fail with the SEH error */
+ Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
+
+ /* Free the DllPath */
+ RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
+
+ /* 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);
+ SetLastErrorByStatus(Status);
+ Module = 0;
+ }
+
+ /* Return module */
+ return (HMODULE)Module;
+}
+
+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 */
+ SetLastErrorByStatus(Status);
+ if (phModule) *phModule = 0;
+ return Status;
+ }
+ }
+
+ 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)
+ {
+ /* Last error is already set, so just return failure by setting status */
+ Status = STATUS_DLL_NOT_FOUND;
+ 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 */
+ Status = LdrAddRefDll((dwPublicFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0,
+ hModule);
+ }
+
+ /* Set last error in case of failure */
+ if (!NT_SUCCESS(Status))
+ SetLastErrorByStatus(Status);
+
+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);
+}
/*
* @implemented
*/
HMODULE
WINAPI
-GetModuleHandleA ( LPCSTR lpModuleName )
+GetModuleHandleA(LPCSTR lpModuleName)
{
- ANSI_STRING ModuleName;
- NTSTATUS Status;
- PTEB pTeb = NtCurrentTeb();
-
- if (lpModuleName == NULL)
- {
- return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress);
- }
+ PUNICODE_STRING ModuleNameW;
+ PTEB pTeb = NtCurrentTeb();
- RtlInitAnsiString(&ModuleName, lpModuleName);
+ /* Check if we have no name to convert */
+ if (!lpModuleName)
+ return ((HMODULE)pTeb->ProcessEnvironmentBlock->ImageBaseAddress);
- Status = RtlAnsiStringToUnicodeString(&pTeb->StaticUnicodeString,
- &ModuleName,
- FALSE);
+ /* Convert module name to unicode */
+ ModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
- if (NT_SUCCESS(Status))
- {
- return GetModuleHandleW(pTeb->StaticUnicodeString.Buffer);
- }
+ /* Call W version if conversion was successful */
+ if (ModuleNameW)
+ return GetModuleHandleW(ModuleNameW->Buffer);
- SetLastErrorByStatus(Status);
- return FALSE;
+ /* Return failure */
+ return 0;
}
*/
HMODULE
WINAPI
-GetModuleHandleW (LPCWSTR lpModuleName)
+GetModuleHandleW(LPCWSTR lpModuleName)
{
- UNICODE_STRING ModuleName;
- PVOID BaseAddress;
- NTSTATUS Status;
+ HMODULE hModule;
+ NTSTATUS Status;
- if (lpModuleName == NULL)
- return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
+ /* If current module is requested - return it right away */
+ if (!lpModuleName)
+ return ((HMODULE)NtCurrentPeb()->ImageBaseAddress);
- RtlInitUnicodeString (&ModuleName,
- (LPWSTR)lpModuleName);
+ /* Use common helper routine */
+ Status = BasepGetModuleHandleExW(TRUE,
+ GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
+ lpModuleName,
+ &hModule);
- Status = LdrGetDllHandle (0,
- 0,
- &ModuleName,
- &BaseAddress);
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus (Status);
- return NULL;
- }
+ /* If it wasn't successful - return 0 */
+ if (!NT_SUCCESS(Status)) hModule = 0;
- return ((HMODULE)BaseAddress);
+ /* Return the handle */
+ return hModule;
}
BOOL
WINAPI
GetModuleHandleExW(IN DWORD dwFlags,
- IN LPCWSTR lpModuleName OPTIONAL,
+ IN LPCWSTR lpwModuleName OPTIONAL,
OUT HMODULE* phModule)
{
- HMODULE hModule;
NTSTATUS Status;
+ DWORD dwValid;
BOOL Ret = FALSE;
- if (phModule == NULL ||
- ((dwFlags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) ==
- (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)))
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
+ /* Validate parameters */
+ dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, lpwModuleName, phModule);
- if (lpModuleName == NULL)
- {
- hModule = NtCurrentPeb()->ImageBaseAddress;
- }
- else
- {
- if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
- {
- hModule = (HMODULE)RtlPcToFileHeader((PVOID)lpModuleName,
- (PVOID*)&hModule);
- if (hModule == NULL)
- {
- SetLastErrorByStatus(STATUS_DLL_NOT_FOUND);
- }
- }
- else
- {
- hModule = GetModuleHandleW(lpModuleName);
- }
- }
+ /* If result is invalid parameter - return failure */
+ if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
- if (hModule != NULL)
- {
- if (!(dwFlags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT))
- {
- Status = LdrAddRefDll((dwFlags & GET_MODULE_HANDLE_EX_FLAG_PIN) ? LDR_PIN_MODULE : 0,
- hModule);
+ /* 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;
- if (NT_SUCCESS(Status))
- {
- Ret = TRUE;
- }
- else
- {
- SetLastErrorByStatus(Status);
- hModule = NULL;
- }
- }
- else
- Ret = TRUE;
- }
+ /* Use common helper routine */
+ Status = BasepGetModuleHandleExW(FALSE,
+ dwFlags,
+ lpwModuleName,
+ phModule);
+
+ /* Return TRUE in case of success */
+ if (NT_SUCCESS(Status)) Ret = TRUE;
- *phModule = hModule;
return Ret;
}
BOOL
WINAPI
GetModuleHandleExA(IN DWORD dwFlags,
- IN LPCSTR lpModuleName OPTIONAL,
+ IN LPCSTR lpModuleName OPTIONAL,
OUT HMODULE* phModule)
{
- ANSI_STRING ModuleName;
- LPCWSTR lpModuleNameW;
+ PUNICODE_STRING lpModuleNameW;
+ DWORD dwValid;
+ BOOL Ret = FALSE;
NTSTATUS Status;
- BOOL Ret;
- PTEB pTeb = NtCurrentTeb();
+ /* Validate parameters */
+ dwValid = BasepGetModuleHandleExParameterValidation(dwFlags, (LPCWSTR)lpModuleName, phModule);
+
+ /* If result is invalid parameter - return failure */
+ if (dwValid == BASEP_GET_MODULE_HANDLE_EX_PARAMETER_VALIDATION_ERROR) return FALSE;
+ /* 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 */
if (dwFlags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)
{
- lpModuleNameW = (LPCWSTR)lpModuleName;
+ /* Call the extended version of the API without conversion */
+ Status = BasepGetModuleHandleExW(FALSE,
+ dwFlags,
+ (LPCWSTR)lpModuleName,
+ phModule);
}
else
{
- RtlInitAnsiString(&ModuleName, lpModuleName);
+ /* Convert module name to unicode */
+ lpModuleNameW = Basep8BitStringToStaticUnicodeString(lpModuleName);
- Status = RtlAnsiStringToUnicodeString(&pTeb->StaticUnicodeString,
- &ModuleName,
- FALSE);
+ /* Return FALSE if conversion failed */
+ if (!lpModuleNameW) return FALSE;
- if (!NT_SUCCESS(Status))
- {
- SetLastErrorByStatus(Status);
- return FALSE;
- }
-
- lpModuleNameW = pTeb->StaticUnicodeString.Buffer;
+ /* Call the extended version of the API */
+ Status = BasepGetModuleHandleExW(FALSE,
+ dwFlags,
+ lpModuleNameW->Buffer,
+ phModule);
}
- Ret = GetModuleHandleExW(dwFlags,
- lpModuleNameW,
- phModule);
+ /* If result was successful - return true */
+ if (NT_SUCCESS(Status))
+ Ret = TRUE;
+ /* Return result */
return Ret;
}
*/
DWORD
WINAPI
-LoadModule (
- LPCSTR lpModuleName,
- LPVOID lpParameterBlock
- )
+LoadModule(LPCSTR lpModuleName,
+ LPVOID lpParameterBlock)
{
- STARTUPINFOA StartupInfo;
- PROCESS_INFORMATION ProcessInformation;
- LOADPARMS32 *LoadParams;
- char FileName[MAX_PATH];
- char *CommandLine, *t;
- BYTE Length;
-
- LoadParams = (LOADPARMS32*)lpParameterBlock;
- if(!lpModuleName || !LoadParams || (((WORD*)LoadParams->lpCmdShow)[0] != 2))
- {
- /* windows doesn't check parameters, we do */
- SetLastError(ERROR_INVALID_PARAMETER);
- return 0;
- }
-
- if(!SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL) &&
- !SearchPathA(NULL, lpModuleName, NULL, MAX_PATH, FileName, NULL))
- {
- return ERROR_FILE_NOT_FOUND;
- }
-
- Length = (BYTE)LoadParams->lpCmdLine[0];
- if(!(CommandLine = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY,
- strlen(lpModuleName) + Length + 2)))
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return 0;
- }
-
- /* Create command line string */
- strcpy(CommandLine, lpModuleName);
- t = CommandLine + strlen(CommandLine);
- *(t++) = ' ';
- memcpy(t, LoadParams->lpCmdLine + 1, Length);
-
- /* Build StartupInfo */
- RtlZeroMemory(&StartupInfo, sizeof(STARTUPINFOA));
- StartupInfo.cb = sizeof(STARTUPINFOA);
- StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
- StartupInfo.wShowWindow = ((WORD*)LoadParams->lpCmdShow)[1];
-
- if(!CreateProcessA(FileName, CommandLine, NULL, NULL, FALSE, 0, LoadParams->lpEnvAddress,
- NULL, &StartupInfo, &ProcessInformation))
- {
- DWORD Error;
-
- RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine);
- /* return the right value */
- Error = GetLastError();
- switch(Error)
- {
- case ERROR_BAD_EXE_FORMAT:
- {
- return ERROR_BAD_FORMAT;
- }
- case ERROR_FILE_NOT_FOUND:
- case ERROR_PATH_NOT_FOUND:
- {
- return Error;
- }
+ 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;
}
- return 0;
- }
- RtlFreeHeap(RtlGetProcessHeap(), 0, CommandLine);
+ /* Search path */
+ Length = SearchPathA(NULL, lpModuleName, ".exe", MAX_PATH, FileName, NULL);
+
+ /* 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;
+
+ 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 */
+ if (lpfnGlobalRegisterWaitForInputIdle)
+ {
+ lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 30000);
+ }
- /* Wait up to 15 seconds for the process to become idle */
- if (NULL != lpfnGlobalRegisterWaitForInputIdle)
- {
- lpfnGlobalRegisterWaitForInputIdle(ProcessInformation.hProcess, 15000);
- }
+ /* Close handles */
+ NtClose(ProcessInformation.hThread);
+ NtClose(ProcessInformation.hProcess);
- 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;
+ }
- return 33;
+ /* Return last error which CreateFile set during an attempt to open it */
+ return GetLastError();
}
/* EOF */