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.

252 lines
5.9 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. AddWritePermissionsToDeviceFiles.cpp
  5. Abstract:
  6. Add write permissions for IOCTL_SCSI_PASS_THROUGH under SECUROM.
  7. SecuRom can be debugged under a user-mode debugger but the following must
  8. be done before hitting 'g' after attach:
  9. 1. sxi av <- ignore access violations
  10. 2. sxi sse <- ignore single step exception
  11. 3. sxi ssec <- ignore single step exception continue
  12. 4. sxi dz <- ignore divide by zero
  13. It checksums it's executable, so breakpoints in certain places don't work.
  14. Notes:
  15. This is a general purpose shim.
  16. History:
  17. 09/03/1999 v-johnwh Created
  18. 03/09/2001 linstev Rewrote DeviceIoControl to handle bad buffers and added
  19. debugging comments
  20. --*/
  21. #include "precomp.h"
  22. #include "CharVector.h"
  23. IMPLEMENT_SHIM_BEGIN(AddWritePermissionsToDeviceFiles)
  24. #include "ShimHookMacro.h"
  25. APIHOOK_ENUM_BEGIN
  26. APIHOOK_ENUM_ENTRY(CreateFileA)
  27. APIHOOK_ENUM_ENTRY(DeviceIoControl)
  28. APIHOOK_ENUM_ENTRY(CloseHandle)
  29. APIHOOK_ENUM_END
  30. VectorT<HANDLE> * g_hDevices;
  31. /*++
  32. We need to add write permission to all CD-ROM devices
  33. --*/
  34. HANDLE
  35. APIHOOK(CreateFileA)(
  36. LPCSTR lpFileName,
  37. DWORD dwDesiredAccess,
  38. DWORD dwShareMode,
  39. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  40. DWORD dwCreationDisposition,
  41. DWORD dwFlagsAndAttributes,
  42. HANDLE hTemplateFile
  43. )
  44. {
  45. DWORD dwAccessMode = dwDesiredAccess;
  46. if ((lpFileName[0] == '\\') &&
  47. (lpFileName[1] == '\\') &&
  48. (lpFileName[2] == '.') &&
  49. (lpFileName[3] == '\\')) {
  50. //
  51. // This file starts with \\.\ so it must be a device file.
  52. //
  53. if (!(dwAccessMode & GENERIC_WRITE)) {
  54. //
  55. // Make sure this device is a CD-ROM
  56. //
  57. char diskRootName[4];
  58. diskRootName[0] = lpFileName[4];
  59. diskRootName[1] = ':';
  60. diskRootName[2] = '\\';
  61. diskRootName[3] = 0;
  62. DWORD dwDriveType = GetDriveTypeA(diskRootName);
  63. if (DRIVE_CDROM == dwDriveType) {
  64. //
  65. // Add write permissions to give us NT4 behavior for device
  66. // files
  67. //
  68. dwAccessMode |= GENERIC_WRITE;
  69. }
  70. }
  71. }
  72. HANDLE hRet = ORIGINAL_API(CreateFileA)(lpFileName, dwAccessMode,
  73. dwShareMode, lpSecurityAttributes, dwCreationDisposition,
  74. dwFlagsAndAttributes, hTemplateFile);
  75. if ((hRet != INVALID_HANDLE_VALUE) && (dwAccessMode != dwDesiredAccess)) {
  76. //
  77. // Add the handle to our list so we can clean it up later.
  78. //
  79. g_hDevices->Append(hRet);
  80. LOGN( eDbgLevelError, "[CreateFileA] Added GENERIC_WRITE permission on device(%s)", lpFileName);
  81. }
  82. return hRet;
  83. }
  84. /*++
  85. Since we added write permission to CD-ROM devices for IOCTL_SCSI_PASS_THROUGH,
  86. we need to remove the write permission for all other IOCTLs passed to that device.
  87. --*/
  88. BOOL
  89. APIHOOK(DeviceIoControl)(
  90. HANDLE hDevice,
  91. DWORD dwIoControlCode,
  92. LPVOID lpInBuffer,
  93. DWORD nInBufferSize,
  94. LPVOID lpOutBuffer,
  95. DWORD nOutBufferSize,
  96. LPDWORD lpBytesReturned,
  97. LPOVERLAPPED lpOverlapped
  98. )
  99. {
  100. LPVOID lpOut = lpOutBuffer;
  101. if (lpOutBuffer && nOutBufferSize && lpBytesReturned) {
  102. //
  103. // Create a new output buffer, if this fails we just keep the original
  104. // buffer.
  105. //
  106. lpOut = malloc(nOutBufferSize);
  107. if (lpOut) {
  108. MoveMemory(lpOut, lpOutBuffer, nOutBufferSize);
  109. } else {
  110. DPFN( eDbgLevelError, "Out of memory");
  111. lpOut = lpOutBuffer;
  112. }
  113. }
  114. BOOL bRet;
  115. if (IOCTL_SCSI_PASS_THROUGH != dwIoControlCode) {
  116. //
  117. // We don't care about IOCTL_SCSI_PASS_THROUGH
  118. //
  119. if (g_hDevices->Find(hDevice) >= 0) {
  120. //
  121. // Check to see if this is a device that we added Write permissions
  122. // If it is, we need to create a handle with only Read permissions
  123. //
  124. HANDLE hDupped;
  125. bRet = DuplicateHandle(GetCurrentProcess(), hDevice,
  126. GetCurrentProcess(), &hDupped, GENERIC_READ, FALSE, 0);
  127. if (bRet) {
  128. //
  129. // Call the IOCTL with the original (Read) permissions
  130. //
  131. bRet = ORIGINAL_API(DeviceIoControl)(hDupped, dwIoControlCode,
  132. lpInBuffer, nInBufferSize, lpOut, nOutBufferSize,
  133. lpBytesReturned, lpOverlapped);
  134. CloseHandle(hDupped);
  135. goto Exit;
  136. }
  137. }
  138. }
  139. bRet = ORIGINAL_API(DeviceIoControl)(hDevice, dwIoControlCode, lpInBuffer,
  140. nInBufferSize, lpOut, nOutBufferSize, lpBytesReturned, lpOverlapped);
  141. Exit:
  142. if (lpOut && (lpOut != lpOutBuffer)) {
  143. //
  144. // Need to copy the output back into the true output buffer
  145. //
  146. if (bRet && lpBytesReturned && *lpBytesReturned) {
  147. __try {
  148. MoveMemory(lpOutBuffer, lpOut, *lpBytesReturned);
  149. } __except(1) {
  150. DPFN( eDbgLevelError, "Failed to copy data into output buffer, perhaps it's read-only");
  151. }
  152. }
  153. free(lpOut);
  154. }
  155. return bRet;
  156. }
  157. /*++
  158. If this handle is in our list, remove it.
  159. --*/
  160. BOOL
  161. APIHOOK(CloseHandle)(
  162. HANDLE hObject
  163. )
  164. {
  165. int index = g_hDevices->Find(hObject);
  166. if (index >= 0) {
  167. g_hDevices->Remove(index);
  168. }
  169. return ORIGINAL_API(CloseHandle)(hObject);
  170. }
  171. /*++
  172. Register hooked functions
  173. --*/
  174. BOOL
  175. NOTIFY_FUNCTION(
  176. DWORD fdwReason)
  177. {
  178. if (fdwReason == DLL_PROCESS_ATTACH) {
  179. g_hDevices = new VectorT<HANDLE>;
  180. }
  181. return g_hDevices != NULL;
  182. }
  183. HOOK_BEGIN
  184. CALL_NOTIFY_FUNCTION
  185. APIHOOK_ENTRY(KERNEL32.DLL, CreateFileA)
  186. APIHOOK_ENTRY(KERNEL32.DLL, DeviceIoControl)
  187. APIHOOK_ENTRY(KERNEL32.DLL, CloseHandle)
  188. HOOK_END
  189. IMPLEMENT_SHIM_END