Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.4 KiB

  1. #define WIN
  2. #define FLAT_32
  3. #define TRUE_IF_WIN32 1
  4. #include <nt.h>
  5. #include <ntrtl.h>
  6. #include <nturtl.h>
  7. #define _WINDOWS
  8. #include <windows.h>
  9. #include "shimdb.h"
  10. //
  11. // Routine in ahcache.c
  12. //
  13. BOOL
  14. SDBAPI
  15. ApphelpUpdateCacheEntry(
  16. LPCWSTR pwszPath, // nt path
  17. HANDLE hFile, // file handle
  18. BOOL bDeleteEntry, // TRUE if we are to delete the entry
  19. BOOL bNTPath // if TRUE -- NT path, FALSE - dos path
  20. );
  21. //
  22. //
  23. // Global stuff used elsewhere
  24. //
  25. VOID
  26. InvalidateAppcompatCacheEntry(
  27. LPCWSTR pwszDosPath
  28. )
  29. {
  30. ApphelpUpdateCacheEntry(pwszDosPath, INVALID_HANDLE_VALUE, TRUE, FALSE);
  31. }
  32. //
  33. // Determine if a file is in the root or if the file is in the leaf
  34. //
  35. BOOL
  36. WINAPI
  37. CheckFileLocation(
  38. LPCWSTR pwszDosPath,
  39. BOOL* pbRoot,
  40. BOOL* pbLeaf
  41. )
  42. {
  43. BOOL TranslationStatus;
  44. UNICODE_STRING PathName;
  45. PWSTR FileName = NULL;
  46. RTL_PATH_TYPE PathType;
  47. WIN32_FIND_DATA FindData;
  48. BOOL bLeaf;
  49. BOOL bSuccess = FALSE;
  50. WCHAR wszFileName[MAX_PATH];
  51. PWSTR FreeBuffer = NULL;
  52. NTSTATUS Status;
  53. ULONG Length;
  54. HANDLE hFind = INVALID_HANDLE_VALUE;
  55. static LPCWSTR pwszPrefixWin32 = TEXT("\\??\\"); // std win32 path prefix
  56. static LPCWSTR pwszPrefixUNC = TEXT("\\UNC\\");
  57. UCHAR DosPathBuffer[MAX_PATH*2];
  58. RTL_UNICODE_STRING_BUFFER DosPath;
  59. RtlInitUnicodeStringBuffer(&DosPath, DosPathBuffer, sizeof(DosPathBuffer));
  60. TranslationStatus = RtlDosPathNameToNtPathName_U(pwszDosPath,
  61. &PathName,
  62. &FileName,
  63. NULL);
  64. if (!TranslationStatus) {
  65. goto cleanup;
  66. }
  67. FreeBuffer = PathName.Buffer;
  68. if (FileName == NULL) {
  69. goto cleanup;
  70. }
  71. PathName.Length = (USHORT)((ULONG_PTR)FileName - (ULONG_PTR)PathName.Buffer);
  72. wcscpy(wszFileName, FileName);
  73. //
  74. // path name is ready for open -- sanitize the '\\'
  75. //
  76. if (PathName.Length > 2 * sizeof(WCHAR)) {
  77. if (RTL_STRING_GET_LAST_CHAR(&PathName) == L'\\' &&
  78. RTL_STRING_GET_AT(&PathName, RTL_STRING_GET_LENGTH_CHARS(&PathName) - 2) != L':') {
  79. PathName.Length -= sizeof(UNICODE_NULL);
  80. }
  81. }
  82. Status = RtlGetLengthWithoutLastFullDosOrNtPathElement(0, &PathName, &Length);
  83. if (!NT_SUCCESS(Status)) {
  84. goto cleanup;
  85. }
  86. if (Length == wcslen(pwszPrefixWin32)) { // this is root path of whatever kind you think it is
  87. *pbRoot = TRUE;
  88. }
  89. //
  90. // check if this is a leaf node in fact
  91. // the way we know is this:
  92. // - if it's the only file in that node
  93. // - there are no other files / subdirectories in this directory
  94. //
  95. // append * to the path name
  96. if (PathName.MaximumLength < PathName.Length + 2 * sizeof(WCHAR)) {
  97. goto cleanup;
  98. }
  99. RtlAppendUnicodeToString(&PathName,
  100. RTL_STRING_GET_LAST_CHAR(&PathName) == TEXT('\\') ? TEXT("*") : TEXT("\\*"));
  101. // convert the string to dos path
  102. Status = RtlAssignUnicodeStringBuffer(&DosPath, &PathName);
  103. if (!NT_SUCCESS(Status)) {
  104. goto cleanup;
  105. }
  106. Status = RtlNtPathNameToDosPathName(0, &DosPath, NULL, NULL);
  107. if (!NT_SUCCESS(Status)) {
  108. goto cleanup;
  109. }
  110. hFind = FindFirstFileW(DosPath.String.Buffer, &FindData);
  111. if (hFind == INVALID_HANDLE_VALUE) {
  112. // we should at least have found a file we came here with
  113. goto cleanup;
  114. }
  115. bLeaf = TRUE;
  116. do {
  117. // check for . and ..
  118. if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
  119. if (wcscmp(FindData.cFileName, TEXT(".")) == 0 || wcscmp(FindData.cFileName, TEXT(".."))) {
  120. continue;
  121. }
  122. bLeaf = FALSE;
  123. break;
  124. }
  125. // ok, we are the file, make sure we're not the same file
  126. //
  127. if (_wcsicmp(FindData.cFileName, FileName) != 0) {
  128. bLeaf = FALSE;
  129. break;
  130. }
  131. } while (FindNextFileW(hFind, &FindData));
  132. *pbLeaf = bLeaf;
  133. bSuccess = TRUE;
  134. cleanup:
  135. if (hFind != INVALID_HANDLE_VALUE) {
  136. FindClose(hFind);
  137. }
  138. if (FreeBuffer) {
  139. RtlFreeHeap(RtlProcessHeap(), 0, FreeBuffer);
  140. }
  141. RtlFreeUnicodeStringBuffer(&DosPath);
  142. return bSuccess;
  143. }