Leaked source code of windows server 2003
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.

730 lines
20 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. EmulateCDFS.cpp
  5. Abstract:
  6. Removes read only attributes from CD directories: just like Win9x.
  7. This shim has gone through several revisions. Originally it was thought
  8. that win9x simply ignored the ReadOnly, DesiredAccess and ShareMode
  9. parameters, but after some testing, it turns out that this is only true
  10. for the CDRom drive.
  11. Unfortunately we have to check every file to see if it's on the CD first,
  12. just in case someone opens with exclusive access and then tries to open
  13. again.
  14. Notes:
  15. This is a general purpose shim.
  16. History:
  17. 01/03/2000 a-jamd Created
  18. 12/02/2000 linstev Separated into 2 shims: RemoveReadOnlyAttribute and this one
  19. Added CreateFile hooks
  20. 02/14/2002 mnikkel Changed InitializeCriticalSection to InitializeCriticalSectionAndSpinCount
  21. --*/
  22. #include "precomp.h"
  23. #include "CharVector.h"
  24. IMPLEMENT_SHIM_BEGIN(EmulateCDFS)
  25. #include "ShimHookMacro.h"
  26. APIHOOK_ENUM_BEGIN
  27. APIHOOK_ENUM_ENTRY(OpenFile)
  28. APIHOOK_ENUM_ENTRY(CreateFileA)
  29. APIHOOK_ENUM_ENTRY(CreateFileW)
  30. APIHOOK_ENUM_ENTRY(CreateFileMappingA)
  31. APIHOOK_ENUM_ENTRY(MapViewOfFile)
  32. APIHOOK_ENUM_ENTRY(MapViewOfFileEx)
  33. APIHOOK_ENUM_ENTRY(DuplicateHandle)
  34. APIHOOK_ENUM_ENTRY(CloseHandle)
  35. APIHOOK_ENUM_ENTRY(GetFileAttributesW)
  36. APIHOOK_ENUM_ENTRY(GetFileAttributesA)
  37. APIHOOK_ENUM_ENTRY(FindFirstFileW)
  38. APIHOOK_ENUM_ENTRY(FindFirstFileA)
  39. APIHOOK_ENUM_ENTRY(FindNextFileW)
  40. APIHOOK_ENUM_ENTRY(FindNextFileA)
  41. APIHOOK_ENUM_ENTRY(GetFileInformationByHandle)
  42. APIHOOK_ENUM_ENTRY(GetDiskFreeSpaceA)
  43. APIHOOK_ENUM_END
  44. typedef struct _FINDFILE_HANDLE
  45. {
  46. HANDLE DirectoryHandle;
  47. PVOID FindBufferBase;
  48. PVOID FindBufferNext;
  49. ULONG FindBufferLength;
  50. ULONG FindBufferValidLength;
  51. RTL_CRITICAL_SECTION FindBufferLock;
  52. } FINDFILE_HANDLE, *PFINDFILE_HANDLE;
  53. class RO_FileMappingList
  54. {
  55. private:
  56. static VectorT<HANDLE> * g_phROHandles; // File mapping handles that we have forced to Read only
  57. static RO_FileMappingList * g_RO_Handles;
  58. static CRITICAL_SECTION critSec;
  59. inline int GetIndex(HANDLE handle) const;
  60. RO_FileMappingList();
  61. ~RO_FileMappingList();
  62. public:
  63. static void Add(HANDLE roHandle);
  64. static void Remove(HANDLE roHandle);
  65. static BOOL Exist(HANDLE handle);
  66. static BOOL Initialize();
  67. };
  68. // A global list of file mapping handles that we have forced to readonly
  69. RO_FileMappingList * RO_FileMappingList::g_RO_Handles = NULL;
  70. VectorT<HANDLE> * RO_FileMappingList::g_phROHandles = NULL; // File mapping handles that we have forced to Read only
  71. CRITICAL_SECTION RO_FileMappingList::critSec;
  72. RO_FileMappingList::RO_FileMappingList()
  73. {
  74. }
  75. RO_FileMappingList::~RO_FileMappingList()
  76. {
  77. DeleteCriticalSection(&critSec);
  78. }
  79. void RO_FileMappingList::Add(HANDLE roHandle)
  80. {
  81. if (roHandle != NULL)
  82. {
  83. EnterCriticalSection(&critSec);
  84. int index = g_RO_Handles->GetIndex(roHandle);
  85. if (index == -1) // not found
  86. {
  87. DPFN(eDbgLevelSpew, "[RO_FileMappingList::Add] Handle 0x%08x", roHandle);
  88. g_phROHandles->Append(roHandle);
  89. }
  90. LeaveCriticalSection(&critSec);
  91. }
  92. }
  93. void RO_FileMappingList::Remove(HANDLE roHandle)
  94. {
  95. if (roHandle != NULL)
  96. {
  97. EnterCriticalSection(&critSec);
  98. int index = g_RO_Handles->GetIndex(roHandle);
  99. if (index >= 0) // found it
  100. {
  101. DPFN(eDbgLevelSpew, "[RO_FileMappingList::Remove] Handle 0x%08x", roHandle);
  102. g_phROHandles->Remove(index);
  103. }
  104. LeaveCriticalSection(&critSec);
  105. }
  106. }
  107. inline int RO_FileMappingList::GetIndex(HANDLE handle) const
  108. {
  109. int index = g_phROHandles->Find(handle);
  110. return index;
  111. }
  112. BOOL RO_FileMappingList::Exist(HANDLE handle)
  113. {
  114. EnterCriticalSection(&critSec);
  115. BOOL bExist = g_RO_Handles->GetIndex(handle) >= 0;
  116. LeaveCriticalSection(&critSec);
  117. return bExist;
  118. }
  119. BOOL RO_FileMappingList::Initialize()
  120. {
  121. g_RO_Handles = new RO_FileMappingList;
  122. g_phROHandles = new VectorT<HANDLE>;
  123. if (g_RO_Handles && g_phROHandles)
  124. {
  125. return InitializeCriticalSectionAndSpinCount(&(g_RO_Handles->critSec),0x80000000);
  126. }
  127. return FALSE;
  128. }
  129. /*++
  130. Remove write attributes for read-only devices.
  131. --*/
  132. HFILE
  133. APIHOOK(OpenFile)(
  134. LPCSTR lpFileName, // file name
  135. LPOFSTRUCT lpReOpenBuff, // file information
  136. UINT uStyle // action and attributes
  137. )
  138. {
  139. if ((uStyle & OF_READWRITE) && IsOnCDRomA(lpFileName))
  140. {
  141. // Remove the Read/Write bits
  142. uStyle &= ~OF_READWRITE;
  143. uStyle |= OF_READ;
  144. LOGN(eDbgLevelInfo, "[OpenFile] \"%s\": attributes modified for read-only device", lpFileName);
  145. }
  146. HFILE returnValue = ORIGINAL_API(OpenFile)(lpFileName, lpReOpenBuff, uStyle);
  147. return returnValue;
  148. }
  149. /*++
  150. Remove write attributes for read-only devices.
  151. --*/
  152. HANDLE
  153. APIHOOK(CreateFileA)(
  154. LPSTR lpFileName,
  155. DWORD dwDesiredAccess,
  156. DWORD dwShareMode,
  157. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  158. DWORD dwCreationDisposition,
  159. DWORD dwFlagsAndAttributes,
  160. HANDLE hTemplateFile
  161. )
  162. {
  163. if (((dwCreationDisposition == OPEN_EXISTING) ||
  164. (dwCreationDisposition == OPEN_ALWAYS)) &&
  165. ((dwDesiredAccess & GENERIC_WRITE) ||
  166. (dwShareMode != FILE_SHARE_READ)) &&
  167. IsOnCDRomA(lpFileName))
  168. {
  169. dwDesiredAccess &= ~GENERIC_WRITE;
  170. dwShareMode = FILE_SHARE_READ;
  171. LOGN(eDbgLevelInfo, "[CreateFileA] \"%s\": attributes modified for read-only device", lpFileName);
  172. }
  173. if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
  174. {
  175. dwFlagsAndAttributes &= ~FILE_FLAG_NO_BUFFERING;
  176. LOGN(eDbgLevelInfo, "[CreateFileA] \"%s\": removed NO_BUFFERING flag", lpFileName);
  177. }
  178. HANDLE hRet = ORIGINAL_API(CreateFileA)(
  179. lpFileName,
  180. dwDesiredAccess,
  181. dwShareMode,
  182. lpSecurityAttributes,
  183. dwCreationDisposition,
  184. dwFlagsAndAttributes,
  185. hTemplateFile);
  186. DPFN(eDbgLevelSpew,
  187. "[CreateFileA] -File: \"%s\" -GENERIC_WRITE:%c -FILE_SHARE_WRITE:%c%s",
  188. lpFileName,
  189. (dwDesiredAccess & GENERIC_WRITE) ? 'Y' : 'N',
  190. (dwShareMode & FILE_SHARE_WRITE) ? 'Y' : 'N',
  191. (hRet == INVALID_HANDLE_VALUE) ? "\n\t***********Failed***********" : "");
  192. return hRet;
  193. }
  194. /*++
  195. Remove write attributes for read-only devices.
  196. --*/
  197. HANDLE
  198. APIHOOK(CreateFileW)(
  199. LPWSTR lpFileName,
  200. DWORD dwDesiredAccess,
  201. DWORD dwShareMode,
  202. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  203. DWORD dwCreationDisposition,
  204. DWORD dwFlagsAndAttributes,
  205. HANDLE hTemplateFile
  206. )
  207. {
  208. if (((dwCreationDisposition == OPEN_EXISTING) ||
  209. (dwCreationDisposition == OPEN_ALWAYS)) &&
  210. ((dwDesiredAccess & GENERIC_WRITE) ||
  211. (dwShareMode != FILE_SHARE_READ)) &&
  212. IsOnCDRomW(lpFileName))
  213. {
  214. dwDesiredAccess &= ~GENERIC_WRITE;
  215. dwShareMode = FILE_SHARE_READ;
  216. LOGN(eDbgLevelError, "[CreateFileW] \"%S\": attributes modified for read-only device", lpFileName);
  217. }
  218. if (dwFlagsAndAttributes & FILE_FLAG_NO_BUFFERING)
  219. {
  220. dwFlagsAndAttributes &= ~FILE_FLAG_NO_BUFFERING;
  221. LOGN(eDbgLevelInfo, "[CreateFileW] \"%S\": removed NO_BUFFERING flag", lpFileName);
  222. }
  223. HANDLE hRet = ORIGINAL_API(CreateFileW)(
  224. lpFileName,
  225. dwDesiredAccess,
  226. dwShareMode,
  227. lpSecurityAttributes,
  228. dwCreationDisposition,
  229. dwFlagsAndAttributes,
  230. hTemplateFile);
  231. DPFN(eDbgLevelSpew,
  232. "[CreateFileW] -File: \"%S\" -GENERIC_WRITE:%c -FILE_SHARE_WRITE:%c%s",
  233. lpFileName,
  234. (dwDesiredAccess & GENERIC_WRITE) ? 'Y' : 'N',
  235. (dwShareMode & FILE_SHARE_WRITE) ? 'Y' : 'N',
  236. (hRet == INVALID_HANDLE_VALUE) ? "\n\t***********Failed***********" : "");
  237. return hRet;
  238. }
  239. HANDLE
  240. APIHOOK(CreateFileMappingA)(
  241. HANDLE hFile, // handle to file
  242. LPSECURITY_ATTRIBUTES lpAttributes, // security
  243. DWORD flProtect, // protection
  244. DWORD dwMaximumSizeHigh, // high-order DWORD of size
  245. DWORD dwMaximumSizeLow, // low-order DWORD of size
  246. LPCSTR lpName // object name
  247. )
  248. {
  249. BOOL bChangedProtect = FALSE;
  250. if (!(flProtect & PAGE_READONLY) && IsOnCDRom(hFile))
  251. {
  252. // This handle is on a CD-ROM, force the protection to READONLY
  253. flProtect = PAGE_READONLY;
  254. bChangedProtect = TRUE;
  255. LOGN(eDbgLevelError, "[CreateFileMappingA] Handle 0x%08x: attributes modified for read-only device", hFile);
  256. }
  257. HANDLE hRet = ORIGINAL_API(CreateFileMappingA)(
  258. hFile,
  259. lpAttributes,
  260. flProtect,
  261. dwMaximumSizeHigh,
  262. dwMaximumSizeLow,
  263. lpName);
  264. // If the handle is on a CD-ROM, rember it
  265. if (bChangedProtect)
  266. {
  267. RO_FileMappingList::Add(hRet);
  268. }
  269. DPFN(eDbgLevelSpew,
  270. "[CreateFileMappingA] Handle 0x%08x -PAGE_READWRITE:%c -PAGE_WRITECOPY:%c%s",
  271. lpName,
  272. (flProtect & PAGE_READWRITE) ? 'Y' : 'N',
  273. (flProtect & PAGE_WRITECOPY) ? 'Y' : 'N',
  274. (hRet == INVALID_HANDLE_VALUE) ? "\n\t***********Failed***********" : "");
  275. return hRet;
  276. }
  277. LPVOID
  278. APIHOOK(MapViewOfFile)(
  279. HANDLE hFileMappingObject, // handle to file-mapping object
  280. DWORD dwDesiredAccess, // access mode
  281. DWORD dwFileOffsetHigh, // high-order DWORD of offset
  282. DWORD dwFileOffsetLow, // low-order DWORD of offset
  283. SIZE_T dwNumberOfBytesToMap // number of bytes to map
  284. )
  285. {
  286. //
  287. // Check to see if we need to force Read access for CD-ROM files
  288. // Only the FILE_MAP_READ bit may be enabled for CD-ROM access
  289. //
  290. if ((dwDesiredAccess != FILE_MAP_READ) &&
  291. RO_FileMappingList::Exist(hFileMappingObject))
  292. {
  293. dwDesiredAccess = FILE_MAP_READ;
  294. LOGN(eDbgLevelError, "[MapViewOfFile] Handle 0x%08x: attributes modified for read-only device", hFileMappingObject);
  295. }
  296. HANDLE hRet = ORIGINAL_API(MapViewOfFile)(
  297. hFileMappingObject,
  298. dwDesiredAccess,
  299. dwFileOffsetHigh,
  300. dwFileOffsetLow,
  301. dwNumberOfBytesToMap);
  302. return hRet;
  303. }
  304. LPVOID
  305. APIHOOK(MapViewOfFileEx)(
  306. HANDLE hFileMappingObject, // handle to file-mapping object
  307. DWORD dwDesiredAccess, // access mode
  308. DWORD dwFileOffsetHigh, // high-order DWORD of offset
  309. DWORD dwFileOffsetLow, // low-order DWORD of offset
  310. SIZE_T dwNumberOfBytesToMap, // number of bytes to map
  311. LPVOID lpBaseAddress // starting addres
  312. )
  313. {
  314. //
  315. // Check to see if we need to force Read access for CD-ROM files
  316. // Only the FILE_MAP_READ bit may be enabled for CD-ROM access
  317. //
  318. if ((dwDesiredAccess != FILE_MAP_READ) &&
  319. RO_FileMappingList::Exist(hFileMappingObject))
  320. {
  321. dwDesiredAccess = FILE_MAP_READ;
  322. LOGN(eDbgLevelError,
  323. "[MapViewOfFile] Handle 0x%08x: attributes modified for read-only device", hFileMappingObject);
  324. }
  325. HANDLE hRet = ORIGINAL_API(MapViewOfFileEx)(
  326. hFileMappingObject,
  327. dwDesiredAccess,
  328. dwFileOffsetHigh,
  329. dwFileOffsetLow,
  330. dwNumberOfBytesToMap,
  331. lpBaseAddress);
  332. return hRet;
  333. }
  334. /*++
  335. If hSourceHandle has been mucked with, add the duplicated handle to our list
  336. --*/
  337. BOOL
  338. APIHOOK(DuplicateHandle)(
  339. HANDLE hSourceProcessHandle, // handle to source process
  340. HANDLE hSourceHandle, // handle to duplicate
  341. HANDLE hTargetProcessHandle, // handle to target process
  342. LPHANDLE lpTargetHandle, // duplicate handle
  343. DWORD dwDesiredAccess, // requested access
  344. BOOL bInheritHandle, // handle inheritance option
  345. DWORD dwOptions // optional actions
  346. )
  347. {
  348. BOOL retval = ORIGINAL_API(DuplicateHandle)(
  349. hSourceProcessHandle,
  350. hSourceHandle,
  351. hTargetProcessHandle,
  352. lpTargetHandle,
  353. dwDesiredAccess,
  354. bInheritHandle,
  355. dwOptions);
  356. if (retval && RO_FileMappingList::Exist(hSourceHandle))
  357. {
  358. RO_FileMappingList::Add(hTargetProcessHandle);
  359. }
  360. return retval;
  361. }
  362. /*++
  363. If hObject has been mucked with, remove it from the list.
  364. --*/
  365. BOOL
  366. APIHOOK(CloseHandle)(
  367. HANDLE hObject // handle to object
  368. )
  369. {
  370. RO_FileMappingList::Remove(hObject);
  371. return ORIGINAL_API(CloseHandle)(hObject);
  372. }
  373. /*++
  374. Remove read only attribute if it's a directory
  375. --*/
  376. DWORD
  377. APIHOOK(GetFileAttributesA)(LPCSTR lpFileName)
  378. {
  379. DWORD dwFileAttributes = ORIGINAL_API(GetFileAttributesA)(lpFileName);
  380. // Check for READONLY and DIRECTORY attributes
  381. if ((dwFileAttributes != INT_PTR(-1)) &&
  382. (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  383. (dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  384. IsOnCDRomA(lpFileName))
  385. {
  386. // Flip the read-only bit.
  387. LOGN(eDbgLevelWarning, "[GetFileAttributesA] Removing FILE_ATTRIBUTE_READONLY");
  388. dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  389. }
  390. return dwFileAttributes;
  391. }
  392. /*++
  393. Remove read only attribute if it's a directory
  394. --*/
  395. DWORD
  396. APIHOOK(GetFileAttributesW)(LPCWSTR wcsFileName)
  397. {
  398. DWORD dwFileAttributes = ORIGINAL_API(GetFileAttributesW)(wcsFileName);
  399. // Check for READONLY and DIRECTORY attributes
  400. if ((dwFileAttributes != INT_PTR(-1)) &&
  401. (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  402. (dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  403. IsOnCDRomW(wcsFileName))
  404. {
  405. // Flip the read-only bit.
  406. LOGN(eDbgLevelWarning, "[GetFileAttributesW] Removing FILE_ATTRIBUTE_READONLY");
  407. dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  408. }
  409. return dwFileAttributes;
  410. }
  411. /*++
  412. Remove read only attribute if it's a directory
  413. --*/
  414. HANDLE
  415. APIHOOK(FindFirstFileA)(
  416. LPCSTR lpFileName,
  417. LPWIN32_FIND_DATAA lpFindFileData
  418. )
  419. {
  420. HANDLE hFindFile = ORIGINAL_API(FindFirstFileA)(lpFileName, lpFindFileData);
  421. if ((hFindFile != INVALID_HANDLE_VALUE) &&
  422. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  423. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  424. IsOnCDRom(((PFINDFILE_HANDLE) hFindFile)->DirectoryHandle))
  425. {
  426. // Flip the read-only bit
  427. LOGN(eDbgLevelWarning, "[FindFirstFileA] Removing FILE_ATTRIBUTE_READONLY");
  428. lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  429. }
  430. return hFindFile;
  431. }
  432. /*++
  433. Remove read only attribute if it's a directory.
  434. --*/
  435. HANDLE
  436. APIHOOK(FindFirstFileW)(
  437. LPCWSTR wcsFileName,
  438. LPWIN32_FIND_DATAW lpFindFileData
  439. )
  440. {
  441. HANDLE hFindFile = ORIGINAL_API(FindFirstFileW)(wcsFileName, lpFindFileData);
  442. if ((hFindFile != INVALID_HANDLE_VALUE) &&
  443. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  444. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  445. IsOnCDRom(((PFINDFILE_HANDLE) hFindFile)->DirectoryHandle))
  446. {
  447. // It's a directory: flip the read-only bit
  448. LOGN(eDbgLevelInfo, "[FindFirstFileW] Removing FILE_ATTRIBUTE_READONLY");
  449. lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  450. }
  451. return hFindFile;
  452. }
  453. /*++
  454. Remove read only attribute if it's a directory.
  455. --*/
  456. BOOL
  457. APIHOOK(FindNextFileA)(
  458. HANDLE hFindFile,
  459. LPWIN32_FIND_DATAA lpFindFileData
  460. )
  461. {
  462. BOOL bRet = ORIGINAL_API(FindNextFileA)(hFindFile, lpFindFileData);
  463. if (bRet &&
  464. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  465. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  466. IsOnCDRom(((PFINDFILE_HANDLE) hFindFile)->DirectoryHandle))
  467. {
  468. // Flip the read-only bit.
  469. LOGN(eDbgLevelWarning, "[FindNextFileA] Removing FILE_ATTRIBUTE_READONLY");
  470. lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  471. }
  472. return bRet;
  473. }
  474. /*++
  475. Remove read only attribute if it's a directory.
  476. --*/
  477. BOOL
  478. APIHOOK(FindNextFileW)(
  479. HANDLE hFindFile,
  480. LPWIN32_FIND_DATAW lpFindFileData
  481. )
  482. {
  483. BOOL bRet = ORIGINAL_API(FindNextFileW)(hFindFile, lpFindFileData);
  484. if (bRet &&
  485. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  486. (lpFindFileData->dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  487. IsOnCDRom(((PFINDFILE_HANDLE) hFindFile)->DirectoryHandle))
  488. {
  489. // Flip the read-only bit
  490. LOGN(eDbgLevelWarning, "[FindNextFileW] Removing FILE_ATTRIBUTE_READONLY");
  491. lpFindFileData->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  492. }
  493. return bRet;
  494. }
  495. /*++
  496. Remove read only attribute if it's a directory.
  497. --*/
  498. BOOL
  499. APIHOOK(GetFileInformationByHandle)(
  500. HANDLE hFile,
  501. LPBY_HANDLE_FILE_INFORMATION lpFileInformation
  502. )
  503. {
  504. BOOL bRet = ORIGINAL_API(GetFileInformationByHandle)(hFile, lpFileInformation);
  505. if (bRet &&
  506. (lpFileInformation->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
  507. (lpFileInformation->dwFileAttributes & FILE_ATTRIBUTE_READONLY) &&
  508. IsOnCDRom(hFile))
  509. {
  510. // It's a CDROM: flip the read-only bit.
  511. LOGN(eDbgLevelWarning, "[GetFileInformationByHandle] Removing FILE_ATTRIBUTE_READONLY");
  512. lpFileInformation->dwFileAttributes ^= FILE_ATTRIBUTE_READONLY;
  513. }
  514. return bRet;
  515. }
  516. /*++
  517. If the disk is a CDROM, return the same wrong numbers as Win9x
  518. --*/
  519. BOOL
  520. APIHOOK(GetDiskFreeSpaceA)(
  521. LPCSTR lpRootPathName,
  522. LPDWORD lpSectorsPerCluster,
  523. LPDWORD lpBytesPerSector,
  524. LPDWORD lpNumberOfFreeClusters,
  525. LPDWORD lpTotalNumberOfClusters
  526. )
  527. {
  528. if (IsOnCDRomA(lpRootPathName))
  529. {
  530. // Hard code values to match Win9x (wrong) description of CDROM
  531. *lpSectorsPerCluster = 0x10;
  532. *lpBytesPerSector = 0x800;
  533. *lpNumberOfFreeClusters = 0;
  534. *lpTotalNumberOfClusters = 0x2b7;
  535. return TRUE;
  536. }
  537. else
  538. {
  539. // Call the original API
  540. BOOL lRet = ORIGINAL_API(GetDiskFreeSpaceA)(
  541. lpRootPathName,
  542. lpSectorsPerCluster,
  543. lpBytesPerSector,
  544. lpNumberOfFreeClusters,
  545. lpTotalNumberOfClusters);
  546. return lRet;
  547. }
  548. }
  549. /*++
  550. Initialize all the registry hooks
  551. --*/
  552. BOOL
  553. NOTIFY_FUNCTION(
  554. DWORD fdwReason
  555. )
  556. {
  557. if (fdwReason == DLL_PROCESS_ATTACH)
  558. {
  559. // This forces the allocation of the array:
  560. return RO_FileMappingList::Initialize();
  561. }
  562. return TRUE;
  563. }
  564. /*++
  565. Register hooked functions
  566. --*/
  567. HOOK_BEGIN
  568. CALL_NOTIFY_FUNCTION
  569. APIHOOK_ENTRY(KERNEL32.DLL, OpenFile)
  570. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA)
  571. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileW)
  572. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileMappingA)
  573. APIHOOK_ENTRY(KERNEL32.DLL, MapViewOfFile)
  574. APIHOOK_ENTRY(KERNEL32.DLL, MapViewOfFileEx)
  575. APIHOOK_ENTRY(KERNEL32.DLL, DuplicateHandle)
  576. APIHOOK_ENTRY(KERNEL32.DLL, CloseHandle)
  577. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesA)
  578. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesW)
  579. APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileA)
  580. APIHOOK_ENTRY(KERNEL32.DLL, FindFirstFileW)
  581. APIHOOK_ENTRY(KERNEL32.DLL, FindNextFileA)
  582. APIHOOK_ENTRY(KERNEL32.DLL, FindNextFileW)
  583. APIHOOK_ENTRY(KERNEL32.DLL, GetFileInformationByHandle)
  584. APIHOOK_ENTRY(KERNEL32.DLL, GetDiskFreeSpaceA)
  585. HOOK_END
  586. IMPLEMENT_SHIM_END