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.

460 lines
13 KiB

  1. /*++
  2. Copyright (c) 1991 - 2002 Microsoft Corporation
  3. Module Name:
  4. ## ## ### ##### #### ### ##### #### ##### #####
  5. ### ### ## # ## ## ## ## # ## ## ## # ## ## ## ##
  6. ######## ### ## ## ## ### ## ## ## ## ## ## ##
  7. # ### ## ### ## ## ## ### ## ## ## ## ## ## ##
  8. # # ## ### ## ## ## ### ##### ## ##### #####
  9. # ## # ## ## ## ## # ## ## ## ## # ## ##
  10. # ## ### ##### #### ### ## ## #### ## ##
  11. Abstract:
  12. This module contains the entire implementation of
  13. the Microsoft virtual display miniport driver.
  14. @@BEGIN_DDKSPLIT
  15. Author:
  16. Wesley Witt (wesw) 1-Oct-2001
  17. @@END_DDKSPLIT
  18. Environment:
  19. Kernel mode only.
  20. Notes:
  21. --*/
  22. #include "msdisp.h"
  23. #ifdef ALLOC_PRAGMA
  24. #pragma alloc_text(INIT,DriverEntry)
  25. #endif
  26. NTSTATUS
  27. MsDispHwInitialize(
  28. IN PDEVICE_OBJECT DeviceObject,
  29. IN PIRP Irp,
  30. IN PVOID DeviceExtensionIn,
  31. IN PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResources,
  32. IN ULONG PartialResourceCount
  33. )
  34. /*++
  35. Routine Description:
  36. This routine is the driver's entry point, called by the I/O system
  37. to load the driver. The driver's entry points are initialized and
  38. a mutex to control paging is initialized.
  39. In DBG mode, this routine also examines the registry for special
  40. debug parameters.
  41. Arguments:
  42. DeviceObject - Miniport's device object
  43. Irp - Current IRP in progress
  44. DeviceExtensionIn - Miniport's device extension
  45. PartialResources - List of resources that are assigned to the miniport
  46. PartialResourceCount - Number of assigned resources
  47. Return Value:
  48. NT status code
  49. --*/
  50. {
  51. PDEVICE_EXTENSION DeviceExtension;
  52. UNICODE_STRING EventName;
  53. DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  54. DeviceExtension->DeviceObject = DeviceObject;
  55. KeInitializeMutex( &DeviceExtension->DeviceLock, 0 );
  56. DeviceExtension->DisplayBufferLength = SA_DISPLAY_MAX_BITMAP_SIZE;
  57. DeviceExtension->DisplayBuffer = (PUCHAR) SaPortAllocatePool( DeviceExtension, DeviceExtension->DisplayBufferLength+128 );
  58. if (DeviceExtension->DisplayBuffer == NULL) {
  59. return STATUS_INSUFFICIENT_RESOURCES;
  60. }
  61. RtlZeroMemory( DeviceExtension->DisplayBuffer, DeviceExtension->DisplayBufferLength+128 );
  62. return STATUS_SUCCESS;
  63. }
  64. NTSTATUS
  65. MsDispCreate(
  66. IN PVOID DeviceExtensionIn,
  67. IN PIRP Irp,
  68. IN PVOID FsContextIn
  69. )
  70. {
  71. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  72. PMSDISP_FSCONTEXT FsContext = (PMSDISP_FSCONTEXT) FsContextIn;
  73. FsContext->HasLockedPages = 0;
  74. return STATUS_SUCCESS;
  75. }
  76. NTSTATUS
  77. MsDispClose(
  78. IN PVOID DeviceExtensionIn,
  79. IN PIRP Irp,
  80. IN PVOID FsContextIn
  81. )
  82. {
  83. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  84. PMSDISP_FSCONTEXT FsContext = (PMSDISP_FSCONTEXT) FsContextIn;
  85. if (FsContext->HasLockedPages) {
  86. KeAcquireMutex( &DeviceExtension->DeviceLock );
  87. IoFreeMdl( FsContext->Mdl );
  88. KeReleaseMutex( &DeviceExtension->DeviceLock, FALSE );
  89. }
  90. return STATUS_SUCCESS;
  91. }
  92. VOID
  93. MsDispCreateEventsWorker(
  94. IN PDEVICE_OBJECT DeviceObject,
  95. IN PVOID Context
  96. )
  97. /*++
  98. Routine Description:
  99. This delayed work routine creates the necessary events used
  100. to communicate with the user mode application.
  101. Arguments:
  102. DeviceObject - Display device object
  103. Context - Context pointer
  104. Return Value:
  105. None.
  106. --*/
  107. {
  108. PMSDISP_WORK_ITEM WorkItem = (PMSDISP_WORK_ITEM)Context;
  109. PDEVICE_EXTENSION DeviceExtension = WorkItem->DeviceExtension;
  110. NTSTATUS Status;
  111. WorkItem->Status = STATUS_SUCCESS;
  112. DeviceExtension->EventHandle = NULL;
  113. DeviceExtension->Event = NULL;
  114. KeAcquireMutex( &DeviceExtension->DeviceLock );
  115. Status = SaPortCreateBasenamedEvent(
  116. DeviceExtension,
  117. MSDISP_EVENT_NAME,
  118. &DeviceExtension->Event,
  119. &DeviceExtension->EventHandle
  120. );
  121. if (!NT_SUCCESS(Status)) {
  122. REPORT_ERROR( SA_DEVICE_DISPLAY, "SaPortCreateBasenamedEvent failed", Status );
  123. }
  124. WorkItem->Status = Status;
  125. KeReleaseMutex( &DeviceExtension->DeviceLock, FALSE );
  126. IoFreeWorkItem( WorkItem->WorkItem );
  127. KeSetEvent( &WorkItem->Event, IO_NO_INCREMENT, FALSE );
  128. }
  129. NTSTATUS
  130. MsDispDeviceIoctl(
  131. IN PVOID DeviceExtensionIn,
  132. IN PIRP Irp,
  133. IN PVOID FsContextIn,
  134. IN ULONG FunctionCode,
  135. IN PVOID InputBuffer,
  136. IN ULONG InputBufferLength,
  137. IN PVOID OutputBuffer,
  138. IN ULONG OutputBufferLength
  139. )
  140. /*++
  141. Routine Description:
  142. This routine processes the device control requests for the
  143. local display miniport.
  144. Arguments:
  145. DeviceExtension - Miniport's device extension
  146. FunctionCode - Device control function code
  147. InputBuffer - Pointer to the user's input buffer
  148. InputBufferLength - Length in bytes of the input buffer
  149. OutputBuffer - Pointer to the user's output buffer
  150. OutputBufferLength - Length in bytes of the output buffer
  151. Return Value:
  152. NT status code.
  153. --*/
  154. {
  155. NTSTATUS Status = STATUS_SUCCESS;
  156. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  157. PSA_DISPLAY_CAPS DeviceCaps;
  158. PMSDISP_BUFFER_DATA BufferData;
  159. PMSDISP_FSCONTEXT FsContext;
  160. MSDISP_WORK_ITEM WorkItem;
  161. switch (FunctionCode) {
  162. case FUNC_SA_GET_VERSION:
  163. *((PULONG)OutputBuffer) = SA_INTERFACE_VERSION;
  164. break;
  165. case FUNC_SA_GET_CAPABILITIES:
  166. DeviceCaps = (PSA_DISPLAY_CAPS)OutputBuffer;
  167. DeviceCaps->SizeOfStruct = sizeof(SA_DISPLAY_CAPS);
  168. DeviceCaps->DisplayType = SA_DISPLAY_TYPE_BIT_MAPPED_LCD;
  169. DeviceCaps->CharacterSet = SA_DISPLAY_CHAR_ASCII;
  170. DeviceCaps->DisplayHeight = DISPLAY_HEIGHT;
  171. DeviceCaps->DisplayWidth = DISPLAY_WIDTH;
  172. break;
  173. case FUNC_VDRIVER_INIT:
  174. if (DeviceExtension->Event == NULL) {
  175. WorkItem.DeviceExtension = DeviceExtension;
  176. WorkItem.Status = 0;
  177. WorkItem.WorkItem = IoAllocateWorkItem( DeviceExtension->DeviceObject );
  178. if (WorkItem.WorkItem) {
  179. KeInitializeEvent( &WorkItem.Event, NotificationEvent, FALSE );
  180. IoQueueWorkItem( WorkItem.WorkItem, MsDispCreateEventsWorker, DelayedWorkQueue, &WorkItem );
  181. KeWaitForSingleObject( &WorkItem.Event, Executive, KernelMode, FALSE, NULL );
  182. } else {
  183. WorkItem.Status = STATUS_INSUFFICIENT_RESOURCES;
  184. }
  185. } else {
  186. WorkItem.Status = STATUS_SUCCESS;
  187. }
  188. if (WorkItem.Status == STATUS_SUCCESS) {
  189. BufferData = (PMSDISP_BUFFER_DATA) OutputBuffer;
  190. FsContext = (PMSDISP_FSCONTEXT) FsContextIn;
  191. FsContext->Mdl = IoAllocateMdl( DeviceExtension->DisplayBuffer, DeviceExtension->DisplayBufferLength, FALSE, TRUE, NULL );
  192. if (FsContext->Mdl) {
  193. MmBuildMdlForNonPagedPool( FsContext->Mdl );
  194. BufferData->DisplayBuffer = MmMapLockedPagesSpecifyCache(
  195. FsContext->Mdl,
  196. UserMode,
  197. MmCached,
  198. NULL,
  199. FALSE,
  200. NormalPagePriority
  201. );
  202. if (BufferData->DisplayBuffer == NULL) {
  203. IoFreeMdl( FsContext->Mdl );
  204. Status = STATUS_INSUFFICIENT_RESOURCES;
  205. REPORT_ERROR( SA_DEVICE_DISPLAY, "MmMapLockedPagesSpecifyCache failed", Status );
  206. } else {
  207. FsContext->HasLockedPages = 1;
  208. }
  209. } else {
  210. Status = STATUS_INSUFFICIENT_RESOURCES;
  211. REPORT_ERROR( SA_DEVICE_DISPLAY, "IoAllocateMdl failed", Status );
  212. }
  213. } else {
  214. Status = WorkItem.Status;
  215. }
  216. break;
  217. default:
  218. Status = STATUS_NOT_SUPPORTED;
  219. REPORT_ERROR( SA_DEVICE_DISPLAY, "Unsupported device control", Status );
  220. break;
  221. }
  222. return Status;
  223. }
  224. VOID
  225. MsDispWriteWorker(
  226. IN PDEVICE_OBJECT DeviceObject,
  227. IN PVOID Context
  228. )
  229. /*++
  230. Routine Description:
  231. This delayed work routine completes a write operation.
  232. Arguments:
  233. DeviceObject - Display device object
  234. Context - Context pointer
  235. Return Value:
  236. None.
  237. --*/
  238. {
  239. PMSDISP_WORK_ITEM WorkItem = (PMSDISP_WORK_ITEM)Context;
  240. PDEVICE_EXTENSION DeviceExtension = WorkItem->DeviceExtension;
  241. NTSTATUS Status;
  242. KeAcquireMutex( &DeviceExtension->DeviceLock );
  243. RtlZeroMemory( DeviceExtension->DisplayBuffer, DeviceExtension->DisplayBufferLength );
  244. RtlCopyMemory( DeviceExtension->DisplayBuffer, WorkItem->SaDisplay->Bits, (WorkItem->SaDisplay->Width/8)*WorkItem->SaDisplay->Height );
  245. KeReleaseMutex( &DeviceExtension->DeviceLock, FALSE );
  246. if (DeviceExtension->Event) {
  247. KeSetEvent( DeviceExtension->Event, 0, FALSE );
  248. }
  249. IoFreeWorkItem( WorkItem->WorkItem );
  250. SaPortFreePool( DeviceExtension, WorkItem );
  251. SaPortCompleteRequest( DeviceExtension, NULL, 0, STATUS_SUCCESS, FALSE );
  252. }
  253. NTSTATUS
  254. MsDispWrite(
  255. IN PVOID DeviceExtensionIn,
  256. IN PIRP Irp,
  257. IN PVOID FsContextIn,
  258. IN LONGLONG StartingOffset,
  259. IN PVOID DataBuffer,
  260. IN ULONG DataBufferLength
  261. )
  262. /*++
  263. Routine Description:
  264. This routine processes the write request for the local display miniport.
  265. Arguments:
  266. DeviceExtensionIn - Miniport's device extension
  267. StartingOffset - Starting offset for the I/O
  268. DataBuffer - Pointer to the data buffer
  269. DataBufferLength - Length of the data buffer in bytes
  270. Return Value:
  271. NT status code.
  272. --*/
  273. {
  274. PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) DeviceExtensionIn;
  275. PSA_DISPLAY_SHOW_MESSAGE SaDisplay = (PSA_DISPLAY_SHOW_MESSAGE) DataBuffer;
  276. NTSTATUS Status = STATUS_SUCCESS;
  277. PMSDISP_WORK_ITEM WorkItem;
  278. if ((ULONG)((SaDisplay->Width/8)*SaDisplay->Height) > DeviceExtension->DisplayBufferLength) {
  279. return STATUS_INVALID_PARAMETER;
  280. }
  281. WorkItem = (PMSDISP_WORK_ITEM) SaPortAllocatePool( DeviceExtension, sizeof(MSDISP_WORK_ITEM) );
  282. if (WorkItem == NULL) {
  283. return STATUS_INSUFFICIENT_RESOURCES;
  284. }
  285. WorkItem->DeviceExtension = DeviceExtension;
  286. WorkItem->SaDisplay = (PSA_DISPLAY_SHOW_MESSAGE) DataBuffer;
  287. WorkItem->WorkItem = IoAllocateWorkItem( DeviceExtension->DeviceObject );
  288. if (WorkItem->WorkItem) {
  289. IoQueueWorkItem( WorkItem->WorkItem, MsDispWriteWorker, DelayedWorkQueue, WorkItem );
  290. Status = STATUS_PENDING;
  291. } else {
  292. Status = STATUS_INSUFFICIENT_RESOURCES;
  293. }
  294. return Status;
  295. }
  296. NTSTATUS
  297. DriverEntry(
  298. IN PDRIVER_OBJECT DriverObject,
  299. IN PUNICODE_STRING RegistryPath
  300. )
  301. /*++
  302. Routine Description:
  303. This routine is the driver's entry point, called by the I/O system
  304. to load the driver. The driver's entry points are initialized and
  305. a mutex to control paging is initialized.
  306. In DBG mode, this routine also examines the registry for special
  307. debug parameters.
  308. Arguments:
  309. DriverObject - a pointer to the object that represents this device
  310. driver.
  311. RegistryPath - a pointer to this driver's key in the Services tree.
  312. Return Value:
  313. STATUS_SUCCESS
  314. --*/
  315. {
  316. NTSTATUS Status;
  317. SAPORT_INITIALIZATION_DATA SaPortInitData;
  318. RtlZeroMemory( &SaPortInitData, sizeof(SAPORT_INITIALIZATION_DATA) );
  319. SaPortInitData.StructSize = sizeof(SAPORT_INITIALIZATION_DATA);
  320. SaPortInitData.DeviceType = SA_DEVICE_DISPLAY;
  321. SaPortInitData.HwInitialize = MsDispHwInitialize;
  322. SaPortInitData.Write = MsDispWrite;
  323. SaPortInitData.DeviceIoctl = MsDispDeviceIoctl;
  324. SaPortInitData.CloseRoutine = MsDispClose;
  325. SaPortInitData.CreateRoutine = MsDispCreate;
  326. SaPortInitData.DeviceExtensionSize = sizeof(DEVICE_EXTENSION);
  327. SaPortInitData.FileContextSize = sizeof(MSDISP_FSCONTEXT);
  328. Status = SaPortInitialize( DriverObject, RegistryPath, &SaPortInitData );
  329. if (!NT_SUCCESS(Status)) {
  330. REPORT_ERROR( SA_DEVICE_DISPLAY, "SaPortInitialize failed\n", Status );
  331. return Status;
  332. }
  333. return STATUS_SUCCESS;
  334. }