#define WIN #define FLAT_32 #define TRUE_IF_WIN32 1 #include #include #include #define _WINDOWS #include #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; }