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.

165 lines
5.2 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. UltraWinCleaner2002.cpp
  5. Abstract:
  6. Ultra WinCleaner 2002 - WinJunk Cleaner removes files under
  7. %WINDIR%\Resource\Themes. This causes themes to fail to load. Fixed by
  8. hiding everything under %WINDIR%\Resource from FindFirstFileA.
  9. Notes:
  10. This is a application specific shim.
  11. History:
  12. 5/13/2002 mikrause Created
  13. --*/
  14. #include "precomp.h"
  15. #include "StrSafe.h"
  16. #include <nt.h>
  17. IMPLEMENT_SHIM_BEGIN(UltraWinCleaner2002)
  18. #include "ShimHookMacro.h"
  19. APIHOOK_ENUM_BEGIN
  20. APIHOOK_ENUM_ENTRY(NtQueryDirectoryFile)
  21. APIHOOK_ENUM_END
  22. UNICODE_STRING g_strWinResourceDir;
  23. typedef NTSTATUS (WINAPI *_pfn_NtQueryDirectoryFile)(HANDLE, HANDLE,
  24. PIO_APC_ROUTINE, PVOID, PIO_STATUS_BLOCK, PVOID, ULONG,
  25. FILE_INFORMATION_CLASS, BOOLEAN, PUNICODE_STRING, BOOLEAN);
  26. NTSTATUS
  27. APIHOOK(NtQueryDirectoryFile)(
  28. IN HANDLE FileHandle,
  29. IN HANDLE Event OPTIONAL,
  30. IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
  31. IN PVOID ApcContext OPTIONAL,
  32. OUT PIO_STATUS_BLOCK IoStatusBlock,
  33. OUT PVOID FileInformation,
  34. IN ULONG FileInformationLength,
  35. IN FILE_INFORMATION_CLASS FileInformationClass,
  36. IN BOOLEAN ReturnSingleEntry,
  37. IN PUNICODE_STRING FileName OPTIONAL,
  38. IN BOOLEAN RestartScan
  39. )
  40. {
  41. //
  42. // If caller wants any async behavior, skip.
  43. // FileName must be valid.
  44. //
  45. if (Event == NULL && ApcRoutine == NULL && ApcContext == NULL && FileName != NULL) {
  46. // Only trap complete wildcard searches.
  47. if (lstrcmpW(FileName->Buffer, L"*.*") == 0 ||
  48. lstrcmpW(FileName->Buffer, L"*") == 0) {
  49. DWORD dwSize = MAX_PATH * sizeof(WCHAR) + sizeof(OBJECT_NAME_INFORMATION);
  50. PBYTE pbBuffer = new BYTE[dwSize];
  51. if (pbBuffer) {
  52. ULONG RetLen;
  53. ZeroMemory(pbBuffer, dwSize);
  54. POBJECT_NAME_INFORMATION poni = (POBJECT_NAME_INFORMATION)pbBuffer;
  55. // Get the name of the directory
  56. NTSTATUS status = NtQueryObject(FileHandle, ObjectNameInformation,
  57. poni, dwSize, &RetLen);
  58. // Retry if not enough buffer
  59. if (status == STATUS_BUFFER_TOO_SMALL) {
  60. delete [] pbBuffer;
  61. pbBuffer = new BYTE[RetLen];
  62. if (pbBuffer) {
  63. poni = (POBJECT_NAME_INFORMATION)pbBuffer;
  64. status = NtQueryObject(FileHandle, ObjectNameInformation,
  65. poni, RetLen, &RetLen);
  66. }
  67. }
  68. // Check if it is the Windows Resource directory.
  69. if (NT_SUCCESS(status)) {
  70. if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE,
  71. poni->Name.Buffer, poni->Name.Length / sizeof(WCHAR),
  72. g_strWinResourceDir.Buffer, g_strWinResourceDir.Length / sizeof(WCHAR)) == CSTR_EQUAL) {
  73. // Pretend this directory doesn't exist.
  74. DPFN(eDbgLevelInfo, "[NtQueryDirectoryFile] Ignoring all file searches in %S",
  75. poni->Name.Buffer);
  76. delete [] pbBuffer;
  77. return STATUS_NO_SUCH_FILE;
  78. }
  79. }
  80. if (pbBuffer) {
  81. delete [] pbBuffer;
  82. }
  83. }
  84. }
  85. }
  86. return ORIGINAL_API(NtQueryDirectoryFile)(FileHandle, Event, ApcRoutine,
  87. ApcContext, IoStatusBlock, FileInformation, FileInformationLength,
  88. FileInformationClass, ReturnSingleEntry, FileName, RestartScan);
  89. }
  90. BOOL
  91. NOTIFY_FUNCTION(
  92. DWORD fdwReason
  93. )
  94. {
  95. if (fdwReason == DLL_PROCESS_ATTACH)
  96. {
  97. CSTRING_TRY
  98. {
  99. // Get the Windows Resource directory (which holds themes)
  100. CString csWinResourceDir;
  101. csWinResourceDir.GetWindowsDirectoryW();
  102. csWinResourceDir.AppendPath(L"Resources");
  103. //
  104. // Convert the DOS name like C:\Windows\Resources to
  105. // \Device\HarddiskVolume0\Windows\Resources which NT likes.
  106. //
  107. CString csWinDrive;
  108. csWinResourceDir.GetDrivePortion(csWinDrive);
  109. WCHAR wszBuffer[1024];
  110. if (QueryDosDeviceW(csWinDrive, wszBuffer, 1024)) {
  111. csWinResourceDir.Replace(csWinDrive, wszBuffer);
  112. ZeroMemory(&g_strWinResourceDir, sizeof(g_strWinResourceDir));
  113. PWSTR wsz = new WCHAR[csWinResourceDir.GetLength()+1];
  114. if (wsz) {
  115. StringCchCopyW(wsz, csWinResourceDir.GetLength() + 1, csWinResourceDir);
  116. DPFN(eDbgLevelInfo, "Ignoring all file searches in %S", wsz);
  117. RtlInitUnicodeString(&g_strWinResourceDir, wsz);
  118. } else {
  119. return FALSE;
  120. }
  121. } else {
  122. return FALSE;
  123. }
  124. }
  125. CSTRING_CATCH
  126. {
  127. DPFN(eDbgLevelError, "CString exception in NotifyFunc!\n");
  128. return FALSE;
  129. }
  130. }
  131. return TRUE;
  132. }
  133. HOOK_BEGIN
  134. CALL_NOTIFY_FUNCTION
  135. APIHOOK_ENTRY(NTDLL.DLL, NtQueryDirectoryFile)
  136. HOOK_END
  137. IMPLEMENT_SHIM_END