180 lines
4.4 KiB
C
180 lines
4.4 KiB
C
|
#define WIN
|
||
|
#define FLAT_32
|
||
|
#define TRUE_IF_WIN32 1
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#define _WINDOWS
|
||
|
#include <windows.h>
|
||
|
#include "shimdb.h"
|
||
|
|
||
|
|
||
|
//
|
||
|
// Routine in ahcache.c
|
||
|
//
|
||
|
|
||
|
BOOL
|
||
|
SDBAPI
|
||
|
ApphelpUpdateCacheEntry(
|
||
|
LPCWSTR pwszPath, // nt path
|
||
|
HANDLE hFile, // file handle
|
||
|
BOOL bDeleteEntry, // TRUE if we are to delete the entry
|
||
|
BOOL bNTPath // if TRUE -- NT path, FALSE - dos path
|
||
|
);
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Global stuff used elsewhere
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
InvalidateAppcompatCacheEntry(
|
||
|
LPCWSTR pwszDosPath
|
||
|
)
|
||
|
{
|
||
|
ApphelpUpdateCacheEntry(pwszDosPath, INVALID_HANDLE_VALUE, TRUE, FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determine if a file is in the root or if the file is in the leaf
|
||
|
//
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
CheckFileLocation(
|
||
|
LPCWSTR pwszDosPath,
|
||
|
BOOL* pbRoot,
|
||
|
BOOL* pbLeaf
|
||
|
)
|
||
|
{
|
||
|
BOOL TranslationStatus;
|
||
|
UNICODE_STRING PathName;
|
||
|
PWSTR FileName = NULL;
|
||
|
RTL_PATH_TYPE PathType;
|
||
|
WIN32_FIND_DATA FindData;
|
||
|
BOOL bLeaf;
|
||
|
BOOL bSuccess = FALSE;
|
||
|
WCHAR wszFileName[MAX_PATH];
|
||
|
PWSTR FreeBuffer = NULL;
|
||
|
NTSTATUS Status;
|
||
|
ULONG Length;
|
||
|
HANDLE hFind = INVALID_HANDLE_VALUE;
|
||
|
static LPCWSTR pwszPrefixWin32 = TEXT("\\??\\"); // std win32 path prefix
|
||
|
static LPCWSTR pwszPrefixUNC = TEXT("\\UNC\\");
|
||
|
UCHAR DosPathBuffer[MAX_PATH*2];
|
||
|
RTL_UNICODE_STRING_BUFFER DosPath;
|
||
|
|
||
|
RtlInitUnicodeStringBuffer(&DosPath, DosPathBuffer, sizeof(DosPathBuffer));
|
||
|
|
||
|
TranslationStatus = RtlDosPathNameToNtPathName_U(pwszDosPath,
|
||
|
&PathName,
|
||
|
&FileName,
|
||
|
NULL);
|
||
|
if (!TranslationStatus) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
FreeBuffer = PathName.Buffer;
|
||
|
|
||
|
if (FileName == NULL) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
PathName.Length = (USHORT)((ULONG_PTR)FileName - (ULONG_PTR)PathName.Buffer);
|
||
|
wcscpy(wszFileName, FileName);
|
||
|
|
||
|
//
|
||
|
// path name is ready for open -- sanitize the '\\'
|
||
|
//
|
||
|
if (PathName.Length > 2 * sizeof(WCHAR)) {
|
||
|
if (RTL_STRING_GET_LAST_CHAR(&PathName) == L'\\' &&
|
||
|
RTL_STRING_GET_AT(&PathName, RTL_STRING_GET_LENGTH_CHARS(&PathName) - 2) != L':') {
|
||
|
PathName.Length -= sizeof(UNICODE_NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
Status = RtlGetLengthWithoutLastFullDosOrNtPathElement(0, &PathName, &Length);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
if (Length == wcslen(pwszPrefixWin32)) { // this is root path of whatever kind you think it is
|
||
|
*pbRoot = TRUE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check if this is a leaf node in fact
|
||
|
// the way we know is this:
|
||
|
// - if it's the only file in that node
|
||
|
// - there are no other files / subdirectories in this directory
|
||
|
//
|
||
|
|
||
|
// append * to the path name
|
||
|
|
||
|
if (PathName.MaximumLength < PathName.Length + 2 * sizeof(WCHAR)) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
RtlAppendUnicodeToString(&PathName,
|
||
|
RTL_STRING_GET_LAST_CHAR(&PathName) == TEXT('\\') ? TEXT("*") : TEXT("\\*"));
|
||
|
|
||
|
// convert the string to dos path
|
||
|
Status = RtlAssignUnicodeStringBuffer(&DosPath, &PathName);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
Status = RtlNtPathNameToDosPathName(0, &DosPath, NULL, NULL);
|
||
|
if (!NT_SUCCESS(Status)) {
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
hFind = FindFirstFileW(DosPath.String.Buffer, &FindData);
|
||
|
if (hFind == INVALID_HANDLE_VALUE) {
|
||
|
// we should at least have found a file we came here with
|
||
|
goto cleanup;
|
||
|
}
|
||
|
|
||
|
bLeaf = TRUE;
|
||
|
do {
|
||
|
// check for . and ..
|
||
|
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||
|
if (wcscmp(FindData.cFileName, TEXT(".")) == 0 || wcscmp(FindData.cFileName, TEXT(".."))) {
|
||
|
continue;
|
||
|
}
|
||
|
bLeaf = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// ok, we are the file, make sure we're not the same file
|
||
|
//
|
||
|
if (_wcsicmp(FindData.cFileName, FileName) != 0) {
|
||
|
bLeaf = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
} while (FindNextFileW(hFind, &FindData));
|
||
|
|
||
|
*pbLeaf = bLeaf;
|
||
|
bSuccess = TRUE;
|
||
|
|
||
|
cleanup:
|
||
|
|
||
|
|
||
|
if (hFind != INVALID_HANDLE_VALUE) {
|
||
|
FindClose(hFind);
|
||
|
}
|
||
|
|
||
|
if (FreeBuffer) {
|
||
|
RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
|
||
|
}
|
||
|
|
||
|
RtlFreeUnicodeStringBuffer(&DosPath);
|
||
|
|
||
|
return bSuccess;
|
||
|
}
|
||
|
|
||
|
|