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.

237 lines
6.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. EmulateGetDiskFreeSpace.cpp
  5. Abstract:
  6. This shim APIHooks GetDiskFreeSpace and determines the true free space on
  7. FAT32/NTFS systems. If it is larger than 2GB, the stub will return 2GB as
  8. the available free space. If it is smaller than 2GB, it will return the
  9. actual free space.
  10. History:
  11. 10-Nov-99 v-johnwh Created
  12. 04-Oct-00 linstev Sanitized for layer
  13. --*/
  14. #include "precomp.h"
  15. IMPLEMENT_SHIM_BEGIN(EmulateGetDiskFreeSpace)
  16. #include "ShimHookMacro.h"
  17. APIHOOK_ENUM_BEGIN
  18. APIHOOK_ENUM_ENTRY(GetDiskFreeSpaceA)
  19. APIHOOK_ENUM_ENTRY(GetDiskFreeSpaceW)
  20. APIHOOK_ENUM_END
  21. #define WIN9X_TRUNCSIZE 2147483648 // 2 GB
  22. // Has this module called DPF yet, prevents millions of DPF calls
  23. BOOL g_bDPF = FALSE;
  24. BOOL
  25. APIHOOK(GetDiskFreeSpaceA)(
  26. LPCSTR lpRootPathName,
  27. LPDWORD lpSectorsPerCluster,
  28. LPDWORD lpBytesPerSector,
  29. LPDWORD lpNumberOfFreeClusters,
  30. LPDWORD lpTotalNumberOfClusters
  31. )
  32. /*++
  33. This stub function calls GetDiskFreeSpaceEx to determine the true free space
  34. on FAT32/NTFS systems. If it is larger than 2GB, the stub will return 2GB as
  35. the available free space. If it is smaller than 2GB, it will return the actual
  36. free space.
  37. --*/
  38. {
  39. LONG lRet;
  40. ULARGE_INTEGER liFreeBytesAvailableToCaller;
  41. ULARGE_INTEGER liTotalNumberOfBytes;
  42. ULARGE_INTEGER liTotalNumberOfFreeBytes;
  43. DWORD dwFreeClusters;
  44. DWORD dwOldSectorsPerClusters;
  45. DWORD dwOldBytesPerSector;
  46. //
  47. // Call the original API
  48. //
  49. lRet = ORIGINAL_API(GetDiskFreeSpaceA)(
  50. lpRootPathName,
  51. lpSectorsPerCluster,
  52. lpBytesPerSector,
  53. lpNumberOfFreeClusters,
  54. lpTotalNumberOfClusters);
  55. //
  56. // Find out how big the drive is.
  57. //
  58. if (GetDiskFreeSpaceExA(lpRootPathName,
  59. &liFreeBytesAvailableToCaller,
  60. &liTotalNumberOfBytes,
  61. &liTotalNumberOfFreeBytes) == FALSE) {
  62. return lRet;
  63. }
  64. if ((liFreeBytesAvailableToCaller.LowPart > (DWORD) WIN9X_TRUNCSIZE) ||
  65. (liFreeBytesAvailableToCaller.HighPart > 0)) {
  66. //
  67. // Drive bigger than 2GB. Give them the 2gb limit from Win9x
  68. //
  69. *lpSectorsPerCluster = 0x00000040;
  70. *lpBytesPerSector = 0x00000200;
  71. *lpNumberOfFreeClusters = 0x0000FFF6;
  72. *lpTotalNumberOfClusters = 0x0000FFF6;
  73. lRet = TRUE;
  74. } else {
  75. //
  76. // For drives less than 2gb, convert the disk geometry so it looks like Win9x.
  77. //
  78. dwOldSectorsPerClusters = *lpSectorsPerCluster;
  79. dwOldBytesPerSector = *lpBytesPerSector;
  80. *lpSectorsPerCluster = 0x00000040;
  81. *lpBytesPerSector = 0x00000200;
  82. //
  83. // Calculate the free and used cluster values now.
  84. //
  85. *lpNumberOfFreeClusters = (*lpNumberOfFreeClusters *
  86. dwOldSectorsPerClusters *
  87. dwOldBytesPerSector) / (0x00000040 * 0x00000200);
  88. *lpTotalNumberOfClusters = (*lpTotalNumberOfClusters *
  89. dwOldSectorsPerClusters *
  90. dwOldBytesPerSector) / (0x00000040 * 0x00000200);
  91. }
  92. if (!g_bDPF)
  93. {
  94. g_bDPF = TRUE;
  95. LOGN(
  96. eDbgLevelInfo,
  97. "[GetDiskFreeSpaceA] Called. Returning <=2GB free space");
  98. }
  99. return lRet;
  100. }
  101. BOOL
  102. APIHOOK(GetDiskFreeSpaceW)(
  103. LPCWSTR lpRootPathName,
  104. LPDWORD lpSectorsPerCluster,
  105. LPDWORD lpBytesPerSector,
  106. LPDWORD lpNumberOfFreeClusters,
  107. LPDWORD lpTotalNumberOfClusters
  108. )
  109. /*++
  110. This stub function calls GetDiskFreeSpaceEx to determine the true free space
  111. on FAT32/NTFS systems. If it is larger than 2GB, the stub will return 2GB as
  112. the available free space. If it is smaller than 2GB, it will return the actual
  113. free space.
  114. --*/
  115. {
  116. LONG lRet;
  117. ULARGE_INTEGER liFreeBytesAvailableToCaller;
  118. ULARGE_INTEGER liTotalNumberOfBytes;
  119. ULARGE_INTEGER liTotalNumberOfFreeBytes;
  120. DWORD dwFreeClusters;
  121. DWORD dwOldSectorsPerClusters;
  122. DWORD dwOldBytesPerSector;
  123. //
  124. // Call the original API
  125. //
  126. lRet = ORIGINAL_API(GetDiskFreeSpaceW)(
  127. lpRootPathName,
  128. lpSectorsPerCluster,
  129. lpBytesPerSector,
  130. lpNumberOfFreeClusters,
  131. lpTotalNumberOfClusters);
  132. //
  133. // Find out how big the drive is.
  134. //
  135. if (GetDiskFreeSpaceExW(lpRootPathName,
  136. &liFreeBytesAvailableToCaller,
  137. &liTotalNumberOfBytes,
  138. &liTotalNumberOfFreeBytes) == FALSE) {
  139. return lRet;
  140. }
  141. if ((liFreeBytesAvailableToCaller.LowPart > (DWORD) WIN9X_TRUNCSIZE) ||
  142. (liFreeBytesAvailableToCaller.HighPart > 0)) {
  143. //
  144. // Drive bigger than 2GB. Give them the 2gb limit from Win9x
  145. //
  146. *lpSectorsPerCluster = 0x00000040;
  147. *lpBytesPerSector = 0x00000200;
  148. *lpNumberOfFreeClusters = 0x0000FFF6;
  149. *lpTotalNumberOfClusters = 0x0000FFF6;
  150. lRet = TRUE;
  151. } else {
  152. //
  153. // For drives less than 2gb, convert the disk geometry so it looks like Win9x.
  154. //
  155. dwOldSectorsPerClusters = *lpSectorsPerCluster;
  156. dwOldBytesPerSector = *lpBytesPerSector;
  157. *lpSectorsPerCluster = 0x00000040;
  158. *lpBytesPerSector = 0x00000200;
  159. //
  160. // Calculate the free and used cluster values now.
  161. //
  162. *lpNumberOfFreeClusters = (*lpNumberOfFreeClusters *
  163. dwOldSectorsPerClusters *
  164. dwOldBytesPerSector) / (0x00000040 * 0x00000200);
  165. *lpTotalNumberOfClusters = (*lpTotalNumberOfClusters *
  166. dwOldSectorsPerClusters *
  167. dwOldBytesPerSector) / (0x00000040 * 0x00000200);
  168. }
  169. if (!g_bDPF)
  170. {
  171. g_bDPF = TRUE;
  172. LOGN(
  173. eDbgLevelInfo,
  174. "[GetDiskFreeSpaceW] Called. Returning <=2GB free space");
  175. }
  176. return lRet;
  177. }
  178. /*++
  179. Register hooked functions
  180. --*/
  181. HOOK_BEGIN
  182. APIHOOK_ENTRY(KERNEL32.DLL, GetDiskFreeSpaceA)
  183. APIHOOK_ENTRY(KERNEL32.DLL, GetDiskFreeSpaceW)
  184. HOOK_END
  185. IMPLEMENT_SHIM_END