[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:
Alex Ionescu 2011-12-04 19:30:12 +00:00
parent 6764aa97c8
commit 37dc00b136
4 changed files with 502 additions and 330 deletions

View file

@ -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);

View file

@ -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
*/

View file

@ -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);

View file

@ -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