mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 00:45:24 +00:00
[KERNEL32]: Implement BasepComputeProcessPath.
[KERNEL32]: Replace BasepGetDllPath with BasepComputeProcessDllPath. Paths now work right. This is step 1. SearchPatchW is next (BasepComputeProcessPath), followed by CreateProcessInternalW (BasepComputeProcessExePath). Then all paths will work right. svn path=/trunk/; revision=54592
This commit is contained in:
parent
6764aa97c8
commit
37dc00b136
4 changed files with 502 additions and 330 deletions
|
@ -69,105 +69,6 @@ BasepMapModuleHandle(HMODULE hModule, BOOLEAN AsDataFile)
|
|||
return hModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name GetDllLoadPath
|
||||
*
|
||||
* Internal function to compute the load path to use for a given dll.
|
||||
*
|
||||
* @remarks Returned pointer must be freed by caller.
|
||||
*/
|
||||
|
||||
LPWSTR
|
||||
GetDllLoadPath(LPCWSTR lpModule)
|
||||
{
|
||||
ULONG Pos = 0, Length = 4, Tmp;
|
||||
PWCHAR EnvironmentBufferW = NULL;
|
||||
LPCWSTR lpModuleEnd = NULL;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleName = NtCurrentPeb()->ProcessParameters->ImagePathName;
|
||||
lpModule = ModuleName.Buffer;
|
||||
lpModuleEnd = lpModule + (ModuleName.Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (lpModule != NULL)
|
||||
{
|
||||
while (lpModuleEnd > lpModule && *lpModuleEnd != L'/' &&
|
||||
*lpModuleEnd != L'\\' && *lpModuleEnd != L':')
|
||||
{
|
||||
--lpModuleEnd;
|
||||
}
|
||||
Length = (lpModuleEnd - lpModule) + 1;
|
||||
}
|
||||
|
||||
Length += GetCurrentDirectoryW(0, NULL);
|
||||
Length += GetDllDirectoryW(0, NULL);
|
||||
Length += GetSystemDirectoryW(NULL, 0);
|
||||
Length += GetWindowsDirectoryW(NULL, 0);
|
||||
Length += GetEnvironmentVariableW(L"PATH", NULL, 0);
|
||||
|
||||
EnvironmentBufferW = RtlAllocateHeap(RtlGetProcessHeap(), 0,
|
||||
(Length + 1) * sizeof(WCHAR));
|
||||
if (EnvironmentBufferW == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lpModule)
|
||||
{
|
||||
RtlCopyMemory(EnvironmentBufferW, lpModule,
|
||||
(lpModuleEnd - lpModule) * sizeof(WCHAR));
|
||||
Pos += lpModuleEnd - lpModule;
|
||||
EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetCurrentDirectoryW(Length, EnvironmentBufferW + Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetDllDirectoryW(Length - Pos, EnvironmentBufferW + Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetSystemDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetWindowsDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetEnvironmentVariableW(L"PATH", EnvironmentBufferW + Pos, Length - Pos);
|
||||
|
||||
/* Make sure buffer is null terminated */
|
||||
EnvironmentBufferW[Pos++] = UNICODE_NULL;
|
||||
|
||||
|
||||
SetLastError(LastError);
|
||||
return EnvironmentBufferW;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
@ -421,9 +322,9 @@ LoadLibraryExW(LPCWSTR lpLibFileName,
|
|||
}
|
||||
|
||||
/* Compute the load path */
|
||||
SearchPath = BasepGetDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ? (LPWSTR)lpLibFileName : NULL,
|
||||
NULL);
|
||||
|
||||
SearchPath = BaseComputeProcessDllPath((dwFlags & LOAD_WITH_ALTERED_SEARCH_PATH) ?
|
||||
DllName.Buffer : NULL,
|
||||
NULL);
|
||||
if (!SearchPath)
|
||||
{
|
||||
/* Getting DLL path failed, so set last error, free mem and return */
|
||||
|
@ -766,20 +667,24 @@ GetModuleHandleForUnicodeString(PUNICODE_STRING ModuleName)
|
|||
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
|
||||
DllPath = BaseComputeProcessDllPath(NULL, 0);
|
||||
if (!DllPath)
|
||||
{
|
||||
Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module);
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
else
|
||||
{
|
||||
/* Fail with the SEH error */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
_SEH2_TRY
|
||||
{
|
||||
Status = LdrGetDllHandle(DllPath, NULL, ModuleName, &Module);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
/* Fail with the SEH error */
|
||||
Status = _SEH2_GetExceptionCode();
|
||||
}
|
||||
_SEH2_END;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
/* Free the DllPath */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, DllPath);
|
||||
|
|
|
@ -33,7 +33,7 @@ DWORD IllegalMask[4] =
|
|||
0x10000000 // 7C not allowed
|
||||
};
|
||||
|
||||
BASE_SEARCH_PATH_TYPE BaseDllOrderCurrent[BaseCurrentDirMax][BaseSearchPathMax] =
|
||||
BASE_SEARCH_PATH_TYPE BaseDllOrderCurrent[BaseCurrentDirPlacementMax][BaseSearchPathMax] =
|
||||
{
|
||||
{
|
||||
BaseSearchPathApp,
|
||||
|
@ -78,15 +78,313 @@ BASE_SEARCH_PATH_TYPE BaseProcessOrder[BaseSearchPathMax] =
|
|||
BaseSearchPathInvalid
|
||||
};
|
||||
|
||||
BASE_CURRENT_DIR_PLACEMENT BasepDllCurrentDirPlacement = BaseCurrentDirPlacementInvalid;
|
||||
|
||||
extern UNICODE_STRING BasePathVariableName;
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
PWCHAR
|
||||
WINAPI
|
||||
BasepEndOfDirName(IN PWCHAR FileName)
|
||||
{
|
||||
PWCHAR FileNameEnd, FileNameSeparator;
|
||||
|
||||
/* Find the first slash */
|
||||
FileNameSeparator = wcschr(FileName, OBJ_NAME_PATH_SEPARATOR);
|
||||
if (FileNameSeparator)
|
||||
{
|
||||
/* Find the last one */
|
||||
FileNameEnd = wcsrchr(FileNameSeparator, OBJ_NAME_PATH_SEPARATOR);
|
||||
ASSERT(FileNameEnd);
|
||||
|
||||
/* Handle the case where they are one and the same */
|
||||
if (FileNameEnd == FileNameSeparator) FileNameEnd++;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No directory was specified */
|
||||
FileNameEnd = NULL;
|
||||
}
|
||||
|
||||
/* Return where the directory ends and the filename starts */
|
||||
return FileNameEnd;
|
||||
}
|
||||
|
||||
LPWSTR
|
||||
WINAPI
|
||||
BasepComputeProcessPath(IN PBASE_SEARCH_PATH_TYPE PathOrder,
|
||||
IN LPWSTR AppName,
|
||||
IN LPVOID Environment)
|
||||
{
|
||||
return NULL;
|
||||
PWCHAR PathBuffer, Buffer, AppNameEnd, PathCurrent;
|
||||
ULONG PathLengthInBytes;
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING EnvPath;
|
||||
PBASE_SEARCH_PATH_TYPE Order;
|
||||
|
||||
/* Initialize state */
|
||||
AppNameEnd = Buffer = PathBuffer = NULL;
|
||||
Status = STATUS_SUCCESS;
|
||||
PathLengthInBytes = 0;
|
||||
|
||||
/* Loop the ordering array */
|
||||
for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
|
||||
switch (*Order)
|
||||
{
|
||||
/* Compute the size of the DLL path */
|
||||
case BaseSearchPathDll:
|
||||
|
||||
/* This path only gets called if SetDllDirectory was called */
|
||||
ASSERT(BaseDllDirectory.Buffer != NULL);
|
||||
|
||||
/* Make sure there's a DLL directory size */
|
||||
if (BaseDllDirectory.Length)
|
||||
{
|
||||
/* Add it, plus the separator */
|
||||
PathLengthInBytes += BaseDllDirectory.Length + sizeof(L';');
|
||||
}
|
||||
break;
|
||||
|
||||
/* Compute the size of the current path */
|
||||
case BaseSearchPathCurrent:
|
||||
|
||||
/* Add ".;" */
|
||||
PathLengthInBytes += (2 * sizeof(WCHAR));
|
||||
break;
|
||||
|
||||
/* Compute the size of the "PATH" environment variable */
|
||||
case BaseSearchPathEnv:
|
||||
|
||||
/* Grab PEB lock if one wasn't passed in */
|
||||
if (!Environment) RtlAcquirePebLock();
|
||||
|
||||
/* Query the size first */
|
||||
EnvPath.MaximumLength = 0;
|
||||
Status = RtlQueryEnvironmentVariable_U(Environment,
|
||||
&BasePathVariableName,
|
||||
&EnvPath);
|
||||
if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Compute the size we'll need for the environment */
|
||||
EnvPath.MaximumLength = EnvPath.Length + sizeof(WCHAR);
|
||||
if ((EnvPath.Length + sizeof(WCHAR)) > UNICODE_STRING_MAX_BYTES)
|
||||
{
|
||||
/* Don't let it overflow */
|
||||
EnvPath.MaximumLength = EnvPath.Length;
|
||||
}
|
||||
|
||||
/* Allocate the environment buffer */
|
||||
Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
|
||||
0,
|
||||
EnvPath.MaximumLength);
|
||||
if (Buffer)
|
||||
{
|
||||
/* Now query the PATH environment variable */
|
||||
EnvPath.Buffer = Buffer;
|
||||
Status = RtlQueryEnvironmentVariable_U(Environment,
|
||||
&BasePathVariableName,
|
||||
&EnvPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Failure case */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/* Release the PEB lock from above */
|
||||
if (!Environment) RtlReleasePebLock();
|
||||
|
||||
/* There might not be a PATH */
|
||||
if (Status == STATUS_VARIABLE_NOT_FOUND)
|
||||
{
|
||||
/* In this case, skip this PathOrder */
|
||||
EnvPath.Length = EnvPath.MaximumLength = 0;
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* An early failure, go to exit code */
|
||||
goto Quickie;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Add the length of the PATH variable */
|
||||
ASSERT(!(EnvPath.Length & 1));
|
||||
PathLengthInBytes += (EnvPath.Length + sizeof(L';'));
|
||||
}
|
||||
break;
|
||||
|
||||
/* Compute the size of the default search path */
|
||||
case BaseSearchPathDefault:
|
||||
|
||||
/* Just add it... it already has a ';' at the end */
|
||||
ASSERT(!(BaseDefaultPath.Length & 1));
|
||||
PathLengthInBytes += BaseDefaultPath.Length;
|
||||
break;
|
||||
|
||||
/* Compute the size of the current app directory */
|
||||
case BaseSearchPathApp:
|
||||
/* Find out where the app name ends, to get only the directory */
|
||||
if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
|
||||
|
||||
/* Check if there was no application name passed in */
|
||||
if (!(AppName) || !(AppNameEnd))
|
||||
{
|
||||
/* Do we have a per-thread CURDIR to use? */
|
||||
if (NtCurrentTeb()->NtTib.SubSystemTib)
|
||||
{
|
||||
/* This means someone added RTL_PERTHREAD_CURDIR */
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
}
|
||||
|
||||
/* We do not. Do we have the LDR_ENTRY for the executable? */
|
||||
if (!BasepExeLdrEntry)
|
||||
{
|
||||
/* We do not. Grab it */
|
||||
LdrEnumerateLoadedModules(0,
|
||||
BasepLocateExeLdrEntry,
|
||||
NtCurrentPeb()->ImageBaseAddress);
|
||||
}
|
||||
|
||||
/* Now do we have it? */
|
||||
if (BasepExeLdrEntry)
|
||||
{
|
||||
/* Yes, so read the name out of it */
|
||||
AppName = BasepExeLdrEntry->FullDllName.Buffer;
|
||||
}
|
||||
|
||||
/* Find out where the app name ends, to get only the directory */
|
||||
if (AppName) AppNameEnd = BasepEndOfDirName(AppName);
|
||||
}
|
||||
|
||||
/* So, do we have an application name and its directory? */
|
||||
if ((AppName) && (AppNameEnd))
|
||||
{
|
||||
/* Add the size of the app's directory, plus the separator */
|
||||
PathLengthInBytes += ((AppNameEnd - AppName) * sizeof(WCHAR)) + sizeof(L';');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Bam, all done, we now have the final path size */
|
||||
ASSERT(PathLengthInBytes > 0);
|
||||
ASSERT(!(PathLengthInBytes & 1));
|
||||
|
||||
/* Allocate the buffer to hold it */
|
||||
PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, PathLengthInBytes);
|
||||
if (!PathBuffer)
|
||||
{
|
||||
/* Failure path */
|
||||
Status = STATUS_NO_MEMORY;
|
||||
goto Quickie;
|
||||
}
|
||||
|
||||
/* Now we loop again, this time to copy the data */
|
||||
PathCurrent = PathBuffer;
|
||||
for (Order = PathOrder; *Order != BaseSearchPathInvalid; Order++) {
|
||||
switch (*Order)
|
||||
{
|
||||
/* Add the DLL path */
|
||||
case BaseSearchPathDll:
|
||||
if (BaseDllDirectory.Length)
|
||||
{
|
||||
/* Copy it in the buffer, ASSERT there's enough space */
|
||||
ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + BaseDllDirectory.Length) <= PathLengthInBytes);
|
||||
RtlCopyMemory(PathCurrent,
|
||||
BaseDllDirectory.Buffer,
|
||||
BaseDllDirectory.Length);
|
||||
|
||||
/* Update the current pointer, add a separator */
|
||||
PathCurrent += (BaseDllDirectory.Length / sizeof(WCHAR));
|
||||
*PathCurrent++ = ';';
|
||||
}
|
||||
break;
|
||||
|
||||
/* Add the current applicaiton path */
|
||||
case BaseSearchPathApp:
|
||||
if ((AppName) && (AppNameEnd))
|
||||
{
|
||||
/* Copy it in the buffer, ASSERT there's enough space */
|
||||
ASSERT(((PathCurrent - PathBuffer + 1 + (AppNameEnd - AppName)) * sizeof(WCHAR)) <= PathLengthInBytes);
|
||||
RtlCopyMemory(PathCurrent,
|
||||
AppName,
|
||||
(AppNameEnd - AppName) * sizeof(WCHAR));
|
||||
|
||||
/* Update the current pointer, add a separator */
|
||||
PathCurrent += AppNameEnd - AppName;
|
||||
*PathCurrent++ = ';';
|
||||
}
|
||||
break;
|
||||
|
||||
/* Add the default search path */
|
||||
case BaseSearchPathDefault:
|
||||
/* Copy it in the buffer, ASSERT there's enough space */
|
||||
ASSERT((((PathCurrent - PathBuffer) * sizeof(WCHAR)) + BaseDefaultPath.Length) <= PathLengthInBytes);
|
||||
RtlCopyMemory(PathCurrent, BaseDefaultPath.Buffer, BaseDefaultPath.Length);
|
||||
|
||||
/* Update the current pointer. The default path already has a ";" */
|
||||
PathCurrent += (BaseDefaultPath.Length / sizeof(WCHAR));
|
||||
break;
|
||||
|
||||
/* Add the path in the PATH environment variable */
|
||||
case BaseSearchPathEnv:
|
||||
if (EnvPath.Length)
|
||||
{
|
||||
/* Copy it in the buffer, ASSERT there's enough space */
|
||||
ASSERT((((PathCurrent - PathBuffer + 1) * sizeof(WCHAR)) + EnvPath.Length) <= PathLengthInBytes);
|
||||
RtlCopyMemory(PathCurrent, EnvPath.Buffer, EnvPath.Length);
|
||||
|
||||
/* Update the current pointer, add a separator */
|
||||
PathCurrent += (EnvPath.Length / sizeof(WCHAR));
|
||||
*PathCurrent++ = ';';
|
||||
}
|
||||
break;
|
||||
|
||||
/* Add the current dierctory */
|
||||
case BaseSearchPathCurrent:
|
||||
|
||||
/* Copy it in the buffer, ASSERT there's enough space */
|
||||
ASSERT(((PathCurrent - PathBuffer + 2) * sizeof(WCHAR)) <= PathLengthInBytes);
|
||||
*PathCurrent++ = '.';
|
||||
|
||||
/* Add the path separator */
|
||||
*PathCurrent++ = ';';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Everything should've perfectly fit in there */
|
||||
ASSERT((PathCurrent - PathBuffer) * sizeof(WCHAR) == PathLengthInBytes);
|
||||
ASSERT(PathCurrent > PathBuffer);
|
||||
|
||||
/* Terminate the whole thing */
|
||||
PathCurrent[-1] = UNICODE_NULL;
|
||||
|
||||
Quickie:
|
||||
/* Exit path: free our buffers */
|
||||
if (Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
|
||||
if (PathBuffer)
|
||||
{
|
||||
/* This only gets freed in the failure path, since caller wants it */
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer);
|
||||
PathBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the path! */
|
||||
return PathBuffer;
|
||||
}
|
||||
|
||||
LPWSTR
|
||||
|
@ -94,7 +392,7 @@ WINAPI
|
|||
BaseComputeProcessSearchPath(VOID)
|
||||
{
|
||||
DPRINT1("Computing Process Search path\n");
|
||||
|
||||
|
||||
/* Compute the path using default process order */
|
||||
return BasepComputeProcessPath(BaseProcessOrder, NULL, NULL);
|
||||
}
|
||||
|
@ -120,7 +418,14 @@ BaseComputeProcessDllPath(IN LPWSTR FullPath,
|
|||
IN PVOID Environment)
|
||||
{
|
||||
LPWSTR DllPath = NULL;
|
||||
DPRINT1("Computing DLL path: %wZ with BaseDll: %wZ\n", FullPath, &BaseDllDirectory);
|
||||
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\MACHINE\\System\\CurrentControlSet\\Control\\Session Manager");
|
||||
UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"SafeDllSearchMode");
|
||||
OBJECT_ATTRIBUTES ObjectAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(&KeyName, OBJ_CASE_INSENSITIVE);
|
||||
KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
ULONG ResultLength;
|
||||
BASE_CURRENT_DIR_PLACEMENT CurrentDirPlacement, OldCurrentDirPlacement;
|
||||
|
||||
/* Acquire DLL directory lock */
|
||||
RtlEnterCriticalSection(&BaseDllDirectoryLock);
|
||||
|
@ -141,8 +446,65 @@ BaseComputeProcessDllPath(IN LPWSTR FullPath,
|
|||
/* Release DLL directory lock */
|
||||
RtlLeaveCriticalSection(&BaseDllDirectoryLock);
|
||||
|
||||
/* There is no base DLL directory */
|
||||
UNIMPLEMENTED;
|
||||
/* Read the current placement */
|
||||
CurrentDirPlacement = BasepDllCurrentDirPlacement;
|
||||
if (CurrentDirPlacement == BaseCurrentDirPlacementInvalid)
|
||||
{
|
||||
/* Open the configuration key */
|
||||
Status = NtOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Query if safe search is enabled */
|
||||
Status = NtQueryValueKey(KeyHandle,
|
||||
&ValueName,
|
||||
KeyValuePartialInformation,
|
||||
&PartialInfo,
|
||||
sizeof(PartialInfo),
|
||||
&ResultLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Read the value if the size is OK */
|
||||
if (ResultLength == sizeof(PartialInfo))
|
||||
{
|
||||
CurrentDirPlacement = *(PULONG)PartialInfo.Data;
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the handle */
|
||||
NtClose(KeyHandle);
|
||||
|
||||
/* Validate the registry value */
|
||||
if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
|
||||
(CurrentDirPlacement >= BaseCurrentDirPlacementMax))
|
||||
{
|
||||
/* Default to safe search */
|
||||
CurrentDirPlacement = BaseCurrentDirPlacementSafe;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the placement and read the old one */
|
||||
OldCurrentDirPlacement = InterlockedCompareExchange((PLONG)&BasepDllCurrentDirPlacement,
|
||||
CurrentDirPlacement,
|
||||
BaseCurrentDirPlacementInvalid);
|
||||
if (OldCurrentDirPlacement != BaseCurrentDirPlacementInvalid)
|
||||
{
|
||||
/* If there already was a placement, use it */
|
||||
CurrentDirPlacement = OldCurrentDirPlacement;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the placement is invalid or not set */
|
||||
if ((CurrentDirPlacement <= BaseCurrentDirPlacementInvalid) ||
|
||||
(CurrentDirPlacement >= BaseCurrentDirPlacementMax))
|
||||
{
|
||||
/* Default to safe search */
|
||||
CurrentDirPlacement = BaseCurrentDirPlacementSafe;
|
||||
}
|
||||
|
||||
/* Compute the process path using either normal or safe search */
|
||||
DllPath = BasepComputeProcessPath(BaseDllOrderCurrent[CurrentDirPlacement],
|
||||
FullPath,
|
||||
Environment);
|
||||
|
||||
/* Return dll path */
|
||||
return DllPath;
|
||||
|
@ -939,6 +1301,105 @@ ContainsPath(LPCWSTR name)
|
|||
return (name[1] == '.' && (name[2] == '/' || name[2] == '\\'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name GetDllLoadPath
|
||||
*
|
||||
* Internal function to compute the load path to use for a given dll.
|
||||
*
|
||||
* @remarks Returned pointer must be freed by caller.
|
||||
*/
|
||||
|
||||
LPWSTR
|
||||
GetDllLoadPath(LPCWSTR lpModule)
|
||||
{
|
||||
ULONG Pos = 0, Length = 4, Tmp;
|
||||
PWCHAR EnvironmentBufferW = NULL;
|
||||
LPCWSTR lpModuleEnd = NULL;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
ModuleName = NtCurrentPeb()->ProcessParameters->ImagePathName;
|
||||
lpModule = ModuleName.Buffer;
|
||||
lpModuleEnd = lpModule + (ModuleName.Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (lpModule != NULL)
|
||||
{
|
||||
while (lpModuleEnd > lpModule && *lpModuleEnd != L'/' &&
|
||||
*lpModuleEnd != L'\\' && *lpModuleEnd != L':')
|
||||
{
|
||||
--lpModuleEnd;
|
||||
}
|
||||
Length = (lpModuleEnd - lpModule) + 1;
|
||||
}
|
||||
|
||||
Length += GetCurrentDirectoryW(0, NULL);
|
||||
Length += GetDllDirectoryW(0, NULL);
|
||||
Length += GetSystemDirectoryW(NULL, 0);
|
||||
Length += GetWindowsDirectoryW(NULL, 0);
|
||||
Length += GetEnvironmentVariableW(L"PATH", NULL, 0);
|
||||
|
||||
EnvironmentBufferW = RtlAllocateHeap(RtlGetProcessHeap(), 0,
|
||||
(Length + 1) * sizeof(WCHAR));
|
||||
if (EnvironmentBufferW == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lpModule)
|
||||
{
|
||||
RtlCopyMemory(EnvironmentBufferW, lpModule,
|
||||
(lpModuleEnd - lpModule) * sizeof(WCHAR));
|
||||
Pos += lpModuleEnd - lpModule;
|
||||
EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetCurrentDirectoryW(Length, EnvironmentBufferW + Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetDllDirectoryW(Length - Pos, EnvironmentBufferW + Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetSystemDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetWindowsDirectoryW(EnvironmentBufferW + Pos, Length - Pos);
|
||||
if(Tmp > 0 && Tmp < Length - Pos)
|
||||
{
|
||||
Pos += Tmp;
|
||||
if(Pos < Length) EnvironmentBufferW[Pos++] = L';';
|
||||
}
|
||||
|
||||
Tmp = GetEnvironmentVariableW(L"PATH", EnvironmentBufferW + Pos, Length - Pos);
|
||||
|
||||
/* Make sure buffer is null terminated */
|
||||
EnvironmentBufferW[Pos++] = UNICODE_NULL;
|
||||
|
||||
|
||||
SetLastError(LastError);
|
||||
return EnvironmentBufferW;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
|
|
|
@ -375,201 +375,6 @@ BasepDuplicateAndWriteHandle(IN HANDLE ProcessHandle,
|
|||
}
|
||||
}
|
||||
|
||||
LPWSTR
|
||||
WINAPI
|
||||
BasepGetProcessPath(DWORD Reserved,
|
||||
LPWSTR FullPath,
|
||||
PVOID Environment)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
LPWSTR AllocatedPath = NULL, ch;
|
||||
ULONG DefaultLength = BaseDefaultPath.Length;
|
||||
ULONG AppLength = 0;
|
||||
UNICODE_STRING EnvPath;
|
||||
LPWSTR NamePtr;
|
||||
LPWSTR PathBuffer;
|
||||
BOOLEAN SecondAttempt = FALSE;
|
||||
PPEB Peb = NtCurrentPeb();
|
||||
|
||||
if (!Environment) RtlAcquirePebLock();
|
||||
|
||||
/* Query PATH env var into append path */
|
||||
Status = RtlQueryEnvironmentVariable_U(Environment,
|
||||
&BasePathVariableName,
|
||||
&BaseDefaultPathAppend);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
/* Add up PATH environment length */
|
||||
DefaultLength += BaseDefaultPathAppend.Length;
|
||||
}
|
||||
else if (Status == STATUS_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* We have to allocate path dynamically */
|
||||
AllocatedPath = RtlAllocateHeap(RtlGetProcessHeap(), 0, BaseDefaultPathAppend.Length + sizeof(UNICODE_NULL));
|
||||
|
||||
if (AllocatedPath)
|
||||
{
|
||||
/* Set up EnvPath */
|
||||
EnvPath.Buffer = AllocatedPath;
|
||||
EnvPath.Length = BaseDefaultPathAppend.Length + sizeof(UNICODE_NULL);
|
||||
EnvPath.MaximumLength = EnvPath.Length;
|
||||
|
||||
/* Query PATH env var into newly allocated path */
|
||||
Status = RtlQueryEnvironmentVariable_U(Environment,
|
||||
&BasePathVariableName,
|
||||
&EnvPath);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DefaultLength += EnvPath.Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Free newly allocated path, it didn't work */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
|
||||
AllocatedPath = NULL;
|
||||
Status = STATUS_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
secondattempt:
|
||||
if (!FullPath)
|
||||
{
|
||||
/* Initialize BasepExeLdrEntry if necessary */
|
||||
if (!BasepExeLdrEntry)
|
||||
LdrEnumerateLoadedModules(0, BasepLocateExeLdrEntry, Peb->ImageBaseAddress);
|
||||
|
||||
DPRINT("Found BasepExeLdrEntry %wZ\n", &BasepExeLdrEntry->FullDllName);
|
||||
|
||||
/* Set name pointer to the full dll path */
|
||||
NamePtr = BasepExeLdrEntry->FullDllName.Buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set name pointer to the provided path */
|
||||
NamePtr = FullPath;
|
||||
}
|
||||
|
||||
/* Determine application path length */
|
||||
if (NamePtr)
|
||||
{
|
||||
ch = NamePtr;
|
||||
while (*ch)
|
||||
{
|
||||
/* Check if there is a slash */
|
||||
if (*ch == L'\\')
|
||||
{
|
||||
/* Update app length */
|
||||
AppLength = (ULONG_PTR)ch - (ULONG_PTR)NamePtr + sizeof(WCHAR);
|
||||
}
|
||||
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now check, if we found a valid path in the provided full path */
|
||||
if (!AppLength && FullPath && !SecondAttempt)
|
||||
{
|
||||
/* We were provided with a bad full path, retry again using just this app's path */
|
||||
FullPath = NULL;
|
||||
SecondAttempt = TRUE;
|
||||
goto secondattempt;
|
||||
}
|
||||
|
||||
/* Allocate the path buffer */
|
||||
PathBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, DefaultLength + AppLength + 2*sizeof(WCHAR));
|
||||
if (!PathBuffer)
|
||||
{
|
||||
/* Fail */
|
||||
if (!Environment) RtlReleasePebLock();
|
||||
if (AllocatedPath) RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Copy contents there */
|
||||
if (AppLength)
|
||||
{
|
||||
/* Remove trailing slashes if it's not root dir */
|
||||
if (AppLength != 3*sizeof(WCHAR))
|
||||
AppLength -= sizeof(WCHAR);
|
||||
|
||||
/* Copy contents */
|
||||
RtlMoveMemory(PathBuffer, NamePtr, AppLength);
|
||||
}
|
||||
|
||||
/* Release the lock */
|
||||
if (!Environment) RtlReleasePebLock();
|
||||
|
||||
/* Finish preparing the path string */
|
||||
NamePtr = &PathBuffer[AppLength / sizeof(WCHAR)];
|
||||
|
||||
/* Put a separating ";" if something was added */
|
||||
if (AppLength)
|
||||
{
|
||||
*NamePtr = L';';
|
||||
NamePtr++;
|
||||
}
|
||||
|
||||
if (AllocatedPath)
|
||||
{
|
||||
/* Dynamically allocated env path, copy from the static buffer,
|
||||
concatenate with dynamic buffer and free it */
|
||||
RtlMoveMemory(NamePtr, BaseDefaultPath.Buffer, BaseDefaultPath.Length);
|
||||
RtlMoveMemory(&NamePtr[BaseDefaultPath.Length / sizeof(WCHAR)], AllocatedPath, EnvPath.Length);
|
||||
|
||||
/* Free it */
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, AllocatedPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Static env path string, copy directly from BaseDefaultPath */
|
||||
RtlMoveMemory(NamePtr, BaseDefaultPath.Buffer, DefaultLength);
|
||||
}
|
||||
|
||||
/* Null terminate the string */
|
||||
NamePtr[DefaultLength / sizeof(WCHAR)] = 0;
|
||||
|
||||
return PathBuffer;
|
||||
}
|
||||
|
||||
LPWSTR
|
||||
WINAPI
|
||||
BasepGetDllPath(LPWSTR FullPath,
|
||||
PVOID Environment)
|
||||
{
|
||||
#if 0
|
||||
LPWSTR DllPath = NULL;
|
||||
|
||||
/* Acquire DLL directory lock */
|
||||
RtlEnterCriticalSection(&BaseDllDirectoryLock);
|
||||
|
||||
/* Check if we have a base dll directory */
|
||||
if (BaseDllDirectory.Buffer)
|
||||
{
|
||||
/* Then get process path */
|
||||
DllPath = BasepGetProcessPath(0, FullPath, Environment);
|
||||
|
||||
/* Release DLL directory lock */
|
||||
RtlLeaveCriticalSection(&BaseDllDirectoryLock);
|
||||
|
||||
/* Return dll path */
|
||||
return DllPath;
|
||||
}
|
||||
|
||||
/* Release DLL directory lock */
|
||||
RtlLeaveCriticalSection(&BaseDllDirectoryLock);
|
||||
|
||||
/* There is no base DLL directory */
|
||||
UNIMPLEMENTED;
|
||||
|
||||
/* Return dll path */
|
||||
return DllPath;
|
||||
#else
|
||||
return BasepGetProcessPath(0, FullPath, Environment);
|
||||
#endif
|
||||
}
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
BasepCopyHandles(IN PRTL_USER_PROCESS_PARAMETERS Params,
|
||||
|
@ -631,7 +436,9 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
|
|||
if ((Size) && (Size <= (MAX_PATH + 4)))
|
||||
{
|
||||
/* Get the DLL Path */
|
||||
DllPathString = BasepGetDllPath(ApplicationPathName, Environment);
|
||||
DllPathString = BaseComputeProcessDllPath(ApplicationPathName,
|
||||
Environment);
|
||||
if (!DllPathString) return STATUS_NO_MEMORY;
|
||||
|
||||
/* Initialize Strings */
|
||||
RtlInitUnicodeString(&DllPath, DllPathString);
|
||||
|
@ -640,7 +447,8 @@ BasePushProcessParameters(IN HANDLE ProcessHandle,
|
|||
else
|
||||
{
|
||||
/* Get the DLL Path */
|
||||
DllPathString = BasepGetDllPath(FullPath, Environment);
|
||||
DllPathString = BaseComputeProcessDllPath(FullPath, Environment);
|
||||
if (!DllPathString) return STATUS_NO_MEMORY;
|
||||
|
||||
/* Initialize Strings */
|
||||
RtlInitUnicodeString(&DllPath, DllPathString);
|
||||
|
|
|
@ -88,14 +88,6 @@ typedef struct tagLOADPARMS32 {
|
|||
DWORD dwReserved;
|
||||
} LOADPARMS32;
|
||||
|
||||
typedef enum _BASE_CURRENT_DIR_PRIORITY
|
||||
{
|
||||
BaseCurrentDirInvalid = -1,
|
||||
BaseCurrentDirFirst,
|
||||
BaseCurrentDirLast,
|
||||
BaseCurrentDirMax
|
||||
} BASE_CURRENT_DIR_PRIORITY;
|
||||
|
||||
typedef enum _BASE_SEARCH_PATH_TYPE
|
||||
{
|
||||
BaseSearchPathInvalid,
|
||||
|
@ -107,6 +99,14 @@ typedef enum _BASE_SEARCH_PATH_TYPE
|
|||
BaseSearchPathMax
|
||||
} BASE_SEARCH_PATH_TYPE, *PBASE_SEARCH_PATH_TYPE;
|
||||
|
||||
typedef enum _BASE_CURRENT_DIR_PLACEMENT
|
||||
{
|
||||
BaseCurrentDirPlacementInvalid = -1,
|
||||
BaseCurrentDirPlacementDefault,
|
||||
BaseCurrentDirPlacementSafe,
|
||||
BaseCurrentDirPlacementMax
|
||||
} BASE_CURRENT_DIR_PLACEMENT;
|
||||
|
||||
#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
|
||||
|
@ -289,17 +289,15 @@ BasepMapFile(IN LPCWSTR lpApplicationName,
|
|||
OUT PHANDLE hSection,
|
||||
IN PUNICODE_STRING ApplicationName);
|
||||
|
||||
LPWSTR
|
||||
WINAPI
|
||||
BasepGetDllPath(LPWSTR FullPath,
|
||||
PVOID Environment);
|
||||
|
||||
|
||||
PCODEPAGE_ENTRY FASTCALL
|
||||
IntGetCodePageEntry(UINT CodePage);
|
||||
|
||||
LPWSTR
|
||||
GetDllLoadPath(LPCWSTR lpModule);
|
||||
WINAPI
|
||||
BaseComputeProcessDllPath(
|
||||
IN LPWSTR FullPath,
|
||||
IN PVOID Environment
|
||||
);
|
||||
|
||||
VOID
|
||||
WINAPI
|
||||
|
|
Loading…
Reference in a new issue