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.

414 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991 - 2001 Microsoft Corporation
  3. Module Name:
  4. #### ##### #### ###### ## #### ##### #####
  5. ## ## ## ## # ## ## ## # ## ## ## ##
  6. ## ## ## ## ## ## ## ## ## ## ##
  7. ## ## ## ## ## ## ## ## ## ## ##
  8. ## ## ## ## ## ## ## ##### #####
  9. ## ## ## ## # ## ## ## ## # ## ##
  10. #### ##### #### ## ##### ## #### ## ##
  11. Abstract:
  12. This module contains the dispatcher for processing all
  13. IOCTL requests. This module also contains all code for
  14. device controls that are global to all miniport drivers.
  15. Author:
  16. Wesley Witt (wesw) 1-Oct-2001
  17. Environment:
  18. Kernel mode only.
  19. Notes:
  20. --*/
  21. #include "internal.h"
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE,SaPortDeviceControl)
  24. #endif
  25. //
  26. // IOCTL dispatch table
  27. //
  28. typedef NTSTATUS (*PIOCTL_DISPATCH_FUNC)(
  29. IN PDEVICE_OBJECT DeviceObject,
  30. IN PIRP Irp,
  31. IN PDEVICE_EXTENSION DeviceExtension,
  32. IN PVOID InputBuffer,
  33. IN ULONG InputBufferLength,
  34. IN PVOID OutputBuffer,
  35. IN ULONG OutputBufferLength
  36. );
  37. //
  38. // All IOCTLs are dispatched through this table. There are 16 dispatch
  39. // entry points for the public miniports, all private IOCTLs must
  40. // follow these dispatch entry points.
  41. //
  42. PIOCTL_DISPATCH_FUNC IoctlDispatchTable[] =
  43. {
  44. HandleGetVersion, // 0 FUNC_SA_GET_VERSION,
  45. HandleGetCaps, // 1 FUNC_SA_GET_CAPABILITIES,
  46. HandleWdDisable, // 2 FUNC_SAWD_DISABLE,
  47. HandleWdQueryExpireBehavior, // 3 FUNC_SAWD_QUERY_EXPIRE_BEHAVIOR,
  48. HandleWdSetExpireBehavior, // 4 FUNC_SAWD_SET_EXPIRE_BEHAVIOR,
  49. HandleWdPing, // 5 FUNC_SAWD_PING,
  50. HandleWdQueryTimer, // 6 FUNC_SAWD_QUERY_TIMER,
  51. HandleWdSetTimer, // 7 FUNC_SAWD_SET_TIMER,
  52. HandleWdDelayBoot, // 8 FUNC_SAWD_DELAY_BOOT
  53. HandleNvramWriteBootCounter, // 9 FUNC_NVRAM_WRITE_BOOT_COUNTER,
  54. HandleNvramReadBootCounter, // A FUNC_NVRAM_READ_BOOT_COUNTER,
  55. DefaultIoctlHandler, // B
  56. HandleDisplayLock, // C FUNC_SADISPLAY_LOCK,
  57. HandleDisplayUnlock, // D FUNC_SADISPLAY_UNLOCK,
  58. HandleDisplayBusyMessage, // E FUNC_SADISPLAY_BUSY_MESSAGE,
  59. HandleDisplayShutdownMessage, // F FUNC_SADISPLAY_SHUTDOWN_MESSAGE,
  60. HandleDisplayChangeLanguage, // 10 FUNC_SADISPLAY_CHANGE_LANGUAGE,
  61. HandleDisplayStoreBitmap, // 11 FUNC_DISPLAY_STORE_BITMAP
  62. DefaultIoctlHandler, // 12
  63. DefaultIoctlHandler, // 13
  64. DefaultIoctlHandler, // 14
  65. DefaultIoctlHandler, // 15
  66. DefaultIoctlHandler, // 16
  67. DefaultIoctlHandler, // 17
  68. DefaultIoctlHandler, // 18
  69. DefaultIoctlHandler, // 19
  70. DefaultIoctlHandler, // 1A
  71. DefaultIoctlHandler, // 1B
  72. DefaultIoctlHandler, // 1C
  73. DefaultIoctlHandler, // 1D
  74. DefaultIoctlHandler, // 1E
  75. DefaultIoctlHandler, // 1F
  76. DefaultIoctlHandler // 20
  77. };
  78. DECLARE_IOCTL_HANDLER( UnsupportedIoctlHandler )
  79. /*++
  80. Routine Description:
  81. This routine handles all unsupported IOCTLs. It's job is to simply complete
  82. the IRP with the status code set to STATUS_INVALID_DEVICE_REQUEST.
  83. Arguments:
  84. DeviceObject - The device object for the target device.
  85. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  86. DeviceExtension - Pointer to the main port driver device extension.
  87. InputBuffer - Pointer to the user's input buffer
  88. InputBufferLength - Length in bytes of the input buffer
  89. OutputBuffer - Pointer to the user's output buffer
  90. OutputBufferLength - Length in bytes of the output buffer
  91. Return Value:
  92. Always STATUS_INVALID_DEVICE_REQUEST.
  93. --*/
  94. {
  95. return CompleteRequest( Irp, STATUS_INVALID_DEVICE_REQUEST, 0 );
  96. }
  97. DECLARE_IOCTL_HANDLER( DefaultIoctlHandler )
  98. /*++
  99. Routine Description:
  100. This routine is called by all of the subsequent IOCTL handlers. It's job
  101. is to call the IOCTL handler in the associated miniport driver and then
  102. complete the IRP.
  103. Arguments:
  104. DeviceObject - The device object for the target device.
  105. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  106. DeviceExtension - Pointer to the main port driver device extension.
  107. InputBuffer - Pointer to the user's input buffer
  108. InputBufferLength - Length in bytes of the input buffer
  109. OutputBuffer - Pointer to the user's output buffer
  110. OutputBufferLength - Length in bytes of the output buffer
  111. Return Value:
  112. NT status code.
  113. --*/
  114. {
  115. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  116. NTSTATUS Status = DeviceExtension->InitData->DeviceIoctl(
  117. DeviceExtension->MiniPortDeviceExtension,
  118. Irp,
  119. IrpSp->FileObject ? IrpSp->FileObject->FsContext : NULL,
  120. IoGetFunctionCodeFromCtlCode( IrpSp->Parameters.DeviceIoControl.IoControlCode ),
  121. InputBuffer,
  122. InputBufferLength,
  123. OutputBuffer,
  124. OutputBufferLength
  125. );
  126. if (Status != STATUS_PENDING) {
  127. if (!NT_SUCCESS(Status)) {
  128. REPORT_ERROR( DeviceExtension->DeviceType, "Miniport device control routine failed", Status );
  129. }
  130. Status = CompleteRequest( Irp, Status, OutputBufferLength );
  131. }
  132. return Status;
  133. }
  134. DECLARE_IOCTL_HANDLER( HandleGetVersion )
  135. /*++
  136. Routine Description:
  137. This routine processes the IOCTL_SA_GET_VERSION request for all
  138. miniport drivers. It is required that all miniports support
  139. this IOCTL.
  140. Arguments:
  141. DeviceObject - The device object for the target device.
  142. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  143. DeviceExtension - Pointer to the main port driver device extension.
  144. InputBuffer - Pointer to the user's input buffer
  145. InputBufferLength - Length in bytes of the input buffer
  146. OutputBuffer - Pointer to the user's output buffer
  147. OutputBufferLength - Length in bytes of the output buffer
  148. Return Value:
  149. NT status code.
  150. --*/
  151. {
  152. if (OutputBufferLength != sizeof(ULONG)) {
  153. REPORT_ERROR( DeviceExtension->DeviceType, "Output buffer length != sizeof(ULONG)", STATUS_INVALID_BUFFER_SIZE );
  154. return CompleteRequest( Irp, STATUS_INVALID_BUFFER_SIZE, 0 );
  155. }
  156. return DO_DEFAULT();
  157. }
  158. DECLARE_IOCTL_HANDLER( HandleGetCaps )
  159. /*++
  160. Routine Description:
  161. This routine processes the IOCTL_SA_GET_CAPABILITIES request for all
  162. miniport drivers. It is required that all miniports support
  163. this IOCTL. Eventhough this function process the IOCTL for all miniports
  164. the specifics of any given miniport driver is cased in various switch
  165. statements.
  166. Arguments:
  167. DeviceObject - The device object for the target device.
  168. Irp - Pointer to an IRP structure that describes the requested I/O operation.
  169. DeviceExtension - Pointer to the main port driver device extension.
  170. InputBuffer - Pointer to the user's input buffer
  171. InputBufferLength - Length in bytes of the input buffer
  172. OutputBuffer - Pointer to the user's output buffer
  173. OutputBufferLength - Length in bytes of the output buffer
  174. Return Value:
  175. NT status code.
  176. --*/
  177. {
  178. NTSTATUS Status;
  179. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  180. ULONG DeviceCapsSize = 0;
  181. switch (DeviceExtension->InitData->DeviceType) {
  182. case SA_DEVICE_DISPLAY:
  183. DeviceCapsSize = sizeof(SA_DISPLAY_CAPS);
  184. break;
  185. case SA_DEVICE_KEYPAD:
  186. DeviceCapsSize = 0;
  187. break;
  188. case SA_DEVICE_NVRAM:
  189. DeviceCapsSize = sizeof(SA_NVRAM_CAPS);
  190. break;
  191. case SA_DEVICE_WATCHDOG:
  192. DeviceCapsSize = sizeof(SA_WD_CAPS);
  193. break;
  194. default:
  195. DeviceCapsSize = 0;
  196. break;
  197. }
  198. if (OutputBufferLength != DeviceCapsSize) {
  199. REPORT_ERROR( DeviceExtension->DeviceType, "Output buffer wrong length", STATUS_INVALID_BUFFER_SIZE );
  200. return CompleteRequest( Irp, STATUS_INVALID_BUFFER_SIZE, DeviceCapsSize );
  201. }
  202. Status = DeviceExtension->InitData->DeviceIoctl(
  203. DeviceExtension->MiniPortDeviceExtension,
  204. Irp,
  205. NULL,
  206. IoGetFunctionCodeFromCtlCode( IrpSp->Parameters.DeviceIoControl.IoControlCode ),
  207. InputBuffer,
  208. InputBufferLength,
  209. OutputBuffer,
  210. OutputBufferLength
  211. );
  212. if (NT_SUCCESS(Status)) {
  213. switch (DeviceExtension->InitData->DeviceType) {
  214. case SA_DEVICE_DISPLAY:
  215. break;
  216. case SA_DEVICE_KEYPAD:
  217. break;
  218. case SA_DEVICE_NVRAM:
  219. {
  220. PSA_NVRAM_CAPS NvramCaps = (PSA_NVRAM_CAPS)OutputBuffer;
  221. if (NvramCaps->NvramSize < SA_NVRAM_MINIMUM_SIZE) {
  222. Status = STATUS_INVALID_BUFFER_SIZE;
  223. } else {
  224. NvramCaps->NvramSize -= NVRAM_RESERVED_BOOTCOUNTER_SLOTS;
  225. NvramCaps->NvramSize -= NVRAM_RESERVED_DRIVER_SLOTS;
  226. }
  227. }
  228. break;
  229. case SA_DEVICE_WATCHDOG:
  230. break;
  231. default:
  232. break;
  233. }
  234. } else {
  235. REPORT_ERROR( DeviceExtension->DeviceType, "Miniport device control routine failed", Status );
  236. }
  237. return CompleteRequest( Irp, Status, OutputBufferLength );
  238. }
  239. NTSTATUS
  240. SaPortDeviceControl(
  241. IN PDEVICE_OBJECT DeviceObject,
  242. IN PIRP Irp
  243. )
  244. /*++
  245. Routine Description:
  246. This routine is called by the I/O system to perform a device I/O
  247. control function.
  248. Arguments:
  249. DeviceObject - a pointer to the object that represents the device
  250. that I/O is to be done on.
  251. Irp - a pointer to the I/O Request Packet for this request.
  252. Return Value:
  253. STATUS_SUCCESS or STATUS_PENDING if recognized I/O control code,
  254. STATUS_INVALID_DEVICE_REQUEST otherwise.
  255. --*/
  256. {
  257. PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
  258. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
  259. NTSTATUS Status;
  260. ULONG FuncCode;
  261. ULONG Idx;
  262. PVOID OutputBuffer;
  263. ULONG OutputBufferLength;
  264. PIOCTL_DISPATCH_FUNC DispatchFunc;
  265. if (DeviceExtension->IsRemoved) {
  266. return CompleteRequest( Irp, STATUS_DELETE_PENDING, 0 );
  267. }
  268. if (!DeviceExtension->IsStarted) {
  269. return CompleteRequest( Irp, STATUS_NO_SUCH_DEVICE, 0 );
  270. }
  271. DebugPrint(( DeviceExtension->DeviceType, SAPORT_DEBUG_INFO_LEVEL, "IOCTL - [0x%08x] %s\n",
  272. IrpSp->Parameters.DeviceIoControl.IoControlCode,
  273. IoctlString(IrpSp->Parameters.DeviceIoControl.IoControlCode)
  274. ));
  275. if (DEVICE_TYPE_FROM_CTL_CODE(IrpSp->Parameters.DeviceIoControl.IoControlCode) != FILE_DEVICE_SERVER_AVAILABILITY) {
  276. return CompleteRequest( Irp, STATUS_INVALID_PARAMETER_1, 0 );
  277. }
  278. FuncCode = IoGetFunctionCodeFromCtlCode( IrpSp->Parameters.DeviceIoControl.IoControlCode );
  279. Idx = FuncCode - IOCTL_SERVERAVAILABILITY_BASE;
  280. if (Irp->MdlAddress) {
  281. OutputBuffer = (PVOID) MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
  282. if (OutputBuffer == NULL) {
  283. REPORT_ERROR( DeviceExtension->DeviceType, "MmGetSystemAddressForMdlSafe failed", STATUS_INSUFFICIENT_RESOURCES );
  284. return CompleteRequest( Irp, STATUS_INSUFFICIENT_RESOURCES, 0 );
  285. }
  286. OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  287. } else {
  288. OutputBuffer = NULL;
  289. OutputBufferLength = 0;
  290. }
  291. if ((Idx > sizeof(IoctlDispatchTable)/sizeof(PIOCTL_DISPATCH_FUNC)) || (DeviceExtension->InitData->DeviceIoctl == NULL)) {
  292. DispatchFunc = UnsupportedIoctlHandler;
  293. } else {
  294. DispatchFunc = IoctlDispatchTable[Idx];
  295. }
  296. Status = DispatchFunc(
  297. DeviceObject,
  298. Irp,
  299. DeviceExtension,
  300. Irp->AssociatedIrp.SystemBuffer,
  301. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  302. OutputBuffer,
  303. OutputBufferLength
  304. );
  305. if (!NT_SUCCESS(Status)) {
  306. REPORT_ERROR( DeviceExtension->DeviceType, "Device control dispatch routine failed", Status );
  307. }
  308. return Status;
  309. }