Merge the following revisions from kernel-fun branch:
[reactos.git] / reactos / win32ss / drivers / videoprt / dispatch.c
1 /*
2 * VideoPort driver
3 *
4 * Copyright (C) 2002, 2003, 2004 ReactOS Team
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include "videoprt.h"
23
24 #include <ndk/inbvfuncs.h>
25 #include <ndk/psfuncs.h>
26
27 #define NDEBUG
28 #include <debug.h>
29
30 /* GLOBAL VARIABLES ***********************************************************/
31
32 PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
33 PVIDEO_WIN32K_CALLOUT Win32kCallout;
34
35 /* PRIVATE FUNCTIONS **********************************************************/
36
37 /*
38 * Reset display to blue screen
39 */
40 BOOLEAN
41 NTAPI
42 IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
43 {
44 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
45
46 if (ResetDisplayParametersDeviceExtension == NULL)
47 return FALSE;
48
49 DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
50
51 if (DriverExtension->InitializationData.HwResetHw != NULL)
52 {
53 if (DriverExtension->InitializationData.HwResetHw(
54 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
55 Columns, Rows))
56 {
57 ResetDisplayParametersDeviceExtension = NULL;
58 return TRUE;
59 }
60 }
61
62 ResetDisplayParametersDeviceExtension = NULL;
63 return FALSE;
64 }
65
66 NTSTATUS
67 NTAPI
68 IntVideoPortAddDevice(
69 IN PDRIVER_OBJECT DriverObject,
70 IN PDEVICE_OBJECT PhysicalDeviceObject)
71 {
72 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
73 PDEVICE_OBJECT DeviceObject;
74 NTSTATUS Status;
75
76 /* Get the initialization data we saved in VideoPortInitialize. */
77 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
78
79 /* Create adapter device object. */
80 Status = IntVideoPortCreateAdapterDeviceObject(DriverObject,
81 DriverExtension,
82 PhysicalDeviceObject,
83 &DeviceObject);
84 if (NT_SUCCESS(Status))
85 VideoPortDeviceNumber++;
86
87 return Status;
88 }
89
90 /*
91 * IntVideoPortDispatchOpen
92 *
93 * Answer requests for Open calls.
94 *
95 * Run Level
96 * PASSIVE_LEVEL
97 */
98 NTSTATUS
99 NTAPI
100 IntVideoPortDispatchOpen(
101 IN PDEVICE_OBJECT DeviceObject,
102 IN PIRP Irp)
103 {
104 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
105 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
106
107 TRACE_(VIDEOPRT, "IntVideoPortDispatchOpen\n");
108
109 if (CsrssInitialized == FALSE)
110 {
111 /*
112 * We know the first open call will be from the CSRSS process
113 * to let us know its handle.
114 */
115
116 INFO_(VIDEOPRT, "Referencing CSRSS\n");
117 Csrss = (PKPROCESS)PsGetCurrentProcess();
118 INFO_(VIDEOPRT, "Csrss %p\n", Csrss);
119
120 IntInitializeVideoAddressSpace();
121
122 CsrssInitialized = TRUE;
123 }
124
125 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
126 DriverExtension = DeviceExtension->DriverExtension;
127
128 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
129 {
130 Irp->IoStatus.Status = STATUS_SUCCESS;
131 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
132 }
133 else
134 {
135 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
136 }
137
138 Irp->IoStatus.Information = FILE_OPENED;
139 IoCompleteRequest(Irp, IO_NO_INCREMENT);
140
141 return STATUS_SUCCESS;
142 }
143
144 /*
145 * IntVideoPortDispatchClose
146 *
147 * Answer requests for Close calls.
148 *
149 * Run Level
150 * PASSIVE_LEVEL
151 */
152 NTSTATUS
153 NTAPI
154 IntVideoPortDispatchClose(
155 IN PDEVICE_OBJECT DeviceObject,
156 IN PIRP Irp)
157 {
158 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
159
160 TRACE_(VIDEOPRT, "IntVideoPortDispatchClose\n");
161
162 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
163 if ((DeviceExtension->DeviceOpened >= 1) &&
164 (InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0))
165 {
166 ResetDisplayParametersDeviceExtension = NULL;
167 InbvNotifyDisplayOwnershipLost(NULL);
168 ResetDisplayParametersDeviceExtension = DeviceExtension;
169 IntVideoPortResetDisplayParameters(80, 50);
170 }
171
172 Irp->IoStatus.Status = STATUS_SUCCESS;
173 IoCompleteRequest(Irp, IO_NO_INCREMENT);
174
175 return STATUS_SUCCESS;
176 }
177
178 PSTR
179 IoctlName(ULONG Ioctl)
180 {
181 switch(Ioctl)
182 {
183 case IOCTL_VIDEO_ENABLE_VDM:
184 return "IOCTL_VIDEO_ENABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS)
185 case IOCTL_VIDEO_DISABLE_VDM:
186 return "IOCTL_VIDEO_DISABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
187 case IOCTL_VIDEO_REGISTER_VDM:
188 return "IOCTL_VIDEO_REGISTER_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
189 case IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE:
190 return "IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
191 case IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE:
192 return "IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
193 case IOCTL_VIDEO_MONITOR_DEVICE:
194 return "IOCTL_VIDEO_MONITOR_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
195 case IOCTL_VIDEO_ENUM_MONITOR_PDO:
196 return "IOCTL_VIDEO_ENUM_MONITOR_PDO"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
197 case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
198 return "IOCTL_VIDEO_INIT_WIN32K_CALLBACKS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
199 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
200 return "IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
201 case IOCTL_VIDEO_IS_VGA_DEVICE:
202 return "IOCTL_VIDEO_IS_VGA_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
203 case IOCTL_VIDEO_USE_DEVICE_IN_SESSION:
204 return "IOCTL_VIDEO_USE_DEVICE_IN_SESSION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0a, METHOD_BUFFERED, FILE_ANY_ACCESS)
205 case IOCTL_VIDEO_PREPARE_FOR_EARECOVERY:
206 return "IOCTL_VIDEO_PREPARE_FOR_EARECOVERY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0b, METHOD_BUFFERED, FILE_ANY_ACCESS)
207 case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
208 return "IOCTL_VIDEO_SAVE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x80, METHOD_BUFFERED, FILE_ANY_ACCESS)
209 case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
210 return "IOCTL_VIDEO_RESTORE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x81, METHOD_BUFFERED, FILE_ANY_ACCESS)
211 case IOCTL_VIDEO_QUERY_AVAIL_MODES:
212 return "IOCTL_VIDEO_QUERY_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x100, METHOD_BUFFERED, FILE_ANY_ACCESS)
213 case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
214 return "IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x101, METHOD_BUFFERED, FILE_ANY_ACCESS)
215 case IOCTL_VIDEO_QUERY_CURRENT_MODE:
216 return "IOCTL_VIDEO_QUERY_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x102, METHOD_BUFFERED, FILE_ANY_ACCESS)
217 case IOCTL_VIDEO_SET_CURRENT_MODE:
218 return "IOCTL_VIDEO_SET_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x103, METHOD_BUFFERED, FILE_ANY_ACCESS)
219 case IOCTL_VIDEO_RESET_DEVICE:
220 return "IOCTL_VIDEO_RESET_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x104, METHOD_BUFFERED, FILE_ANY_ACCESS)
221 case IOCTL_VIDEO_LOAD_AND_SET_FONT:
222 return "IOCTL_VIDEO_LOAD_AND_SET_FONT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x105, METHOD_BUFFERED, FILE_ANY_ACCESS)
223 case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
224 return "IOCTL_VIDEO_SET_PALETTE_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x106, METHOD_BUFFERED, FILE_ANY_ACCESS)
225 case IOCTL_VIDEO_SET_COLOR_REGISTERS:
226 return "IOCTL_VIDEO_SET_COLOR_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x107, METHOD_BUFFERED, FILE_ANY_ACCESS)
227 case IOCTL_VIDEO_ENABLE_CURSOR:
228 return "IOCTL_VIDEO_ENABLE_CURSOR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x108, METHOD_BUFFERED, FILE_ANY_ACCESS)
229 case IOCTL_VIDEO_DISABLE_CURSOR:
230 return "IOCTL_VIDEO_DISABLE_CURSOR"; // CTL_CODE (FILE_DEVICE_VIDEO, 0x109, METHOD_BUFFERED, FILE_ANY_ACCESS)
231 case IOCTL_VIDEO_SET_CURSOR_ATTR:
232 return "IOCTL_VIDEO_SET_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10a, METHOD_BUFFERED, FILE_ANY_ACCESS)
233 case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
234 return "IOCTL_VIDEO_QUERY_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10b, METHOD_BUFFERED, FILE_ANY_ACCESS)
235 case IOCTL_VIDEO_SET_CURSOR_POSITION:
236 return "IOCTL_VIDEO_SET_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10c, METHOD_BUFFERED, FILE_ANY_ACCESS)
237 case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
238 return "IOCTL_VIDEO_QUERY_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10d, METHOD_BUFFERED, FILE_ANY_ACCESS)
239 case IOCTL_VIDEO_ENABLE_POINTER:
240 return "IOCTL_VIDEO_ENABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10e, METHOD_BUFFERED, FILE_ANY_ACCESS)
241 case IOCTL_VIDEO_DISABLE_POINTER:
242 return "IOCTL_VIDEO_DISABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10f, METHOD_BUFFERED, FILE_ANY_ACCESS)
243 case IOCTL_VIDEO_SET_POINTER_ATTR:
244 return "IOCTL_VIDEO_SET_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x110, METHOD_BUFFERED, FILE_ANY_ACCESS)
245 case IOCTL_VIDEO_QUERY_POINTER_ATTR:
246 return "IOCTL_VIDEO_QUERY_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x111, METHOD_BUFFERED, FILE_ANY_ACCESS)
247 case IOCTL_VIDEO_SET_POINTER_POSITION:
248 return "IOCTL_VIDEO_SET_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x112, METHOD_BUFFERED, FILE_ANY_ACCESS)
249 case IOCTL_VIDEO_QUERY_POINTER_POSITION:
250 return "IOCTL_VIDEO_QUERY_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x113, METHOD_BUFFERED, FILE_ANY_ACCESS)
251 case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
252 return "IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x114, METHOD_BUFFERED, FILE_ANY_ACCESS)
253 case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
254 return "IOCTL_VIDEO_GET_BANK_SELECT_CODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x115, METHOD_BUFFERED, FILE_ANY_ACCESS)
255 case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
256 return "IOCTL_VIDEO_MAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x116, METHOD_BUFFERED, FILE_ANY_ACCESS)
257 case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
258 return "IOCTL_VIDEO_UNMAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x117, METHOD_BUFFERED, FILE_ANY_ACCESS)
259 case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
260 return "IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x118, METHOD_BUFFERED, FILE_ANY_ACCESS)
261 case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
262 return "IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x119, METHOD_BUFFERED, FILE_ANY_ACCESS)
263 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
264 return "IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11a, METHOD_BUFFERED, FILE_ANY_ACCESS)
265 case IOCTL_VIDEO_SET_POWER_MANAGEMENT:
266 return "IOCTL_VIDEO_SET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11b, METHOD_BUFFERED, FILE_ANY_ACCESS)
267 case IOCTL_VIDEO_GET_POWER_MANAGEMENT:
268 return "IOCTL_VIDEO_GET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11c, METHOD_BUFFERED, FILE_ANY_ACCESS)
269 case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
270 return "IOCTL_VIDEO_SHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11d, METHOD_BUFFERED, FILE_ANY_ACCESS)
271 case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
272 return "IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11e, METHOD_BUFFERED, FILE_ANY_ACCESS)
273 case IOCTL_VIDEO_SET_COLOR_LUT_DATA:
274 return "IOCTL_VIDEO_SET_COLOR_LUT_DATA"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11f, METHOD_BUFFERED, FILE_ANY_ACCESS)
275 case IOCTL_VIDEO_GET_CHILD_STATE:
276 return "IOCTL_VIDEO_GET_CHILD_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x120, METHOD_BUFFERED, FILE_ANY_ACCESS)
277 case IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION:
278 return "IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x121, METHOD_BUFFERED, FILE_ANY_ACCESS)
279 case IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION:
280 return "IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x122, METHOD_BUFFERED, FILE_ANY_ACCESS)
281 case IOCTL_VIDEO_SWITCH_DUALVIEW:
282 return "IOCTL_VIDEO_SWITCH_DUALVIEW"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x123, METHOD_BUFFERED, FILE_ANY_ACCESS)
283 case IOCTL_VIDEO_SET_BANK_POSITION:
284 return "IOCTL_VIDEO_SET_BANK_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x124, METHOD_BUFFERED, FILE_ANY_ACCESS)
285 case IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS:
286 return "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS)
287 case IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS:
288 return "IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS)
289 case IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS:
290 return "IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS)
291 }
292
293 return "<unknown ioctl code";
294 }
295
296 static
297 NTSTATUS
298 VideoPortUseDeviceInSession(
299 _Inout_ PDEVICE_OBJECT DeviceObject,
300 _Inout_ PVIDEO_DEVICE_SESSION_STATUS SessionState,
301 _In_ ULONG BufferLength,
302 _Out_ PULONG_PTR Information)
303 {
304 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
305
306 /* Check buffer size */
307 *Information = sizeof(VIDEO_DEVICE_SESSION_STATUS);
308 if (BufferLength < sizeof(VIDEO_DEVICE_SESSION_STATUS))
309 {
310 ERR_(VIDEOPRT, "Buffer too small for VIDEO_DEVICE_SESSION_STATUS: %lx\n",
311 BufferLength);
312 return STATUS_BUFFER_TOO_SMALL;
313 }
314
315 /* Get the device extension */
316 DeviceExtension = DeviceObject->DeviceExtension;
317
318 /* Shall we enable the session? */
319 if (SessionState->bEnable)
320 {
321 /* Check if we have no session yet */
322 if (DeviceExtension->SessionId == -1)
323 {
324 /* Use this session and return success */
325 DeviceExtension->SessionId = PsGetCurrentProcessSessionId();
326 SessionState->bSuccess = TRUE;
327 }
328 else
329 {
330 ERR_(VIDEOPRT, "Requested to set session, but session is already set to: 0x%lx\n",
331 DeviceExtension->SessionId);
332 SessionState->bSuccess = FALSE;
333 }
334 }
335 else
336 {
337 /* Check if we belong to the current session */
338 if (DeviceExtension->SessionId == PsGetCurrentProcessSessionId())
339 {
340 /* Reset the session and return success */
341 DeviceExtension->SessionId = -1;
342 SessionState->bSuccess = TRUE;
343 }
344 else
345 {
346 ERR_(VIDEOPRT, "Requested to reset session, but session is not set\n");
347 SessionState->bSuccess = FALSE;
348 }
349 }
350
351 return STATUS_SUCCESS;
352 }
353
354 static
355 NTSTATUS
356 VideoPortInitWin32kCallbacks(
357 _In_ PDEVICE_OBJECT DeviceObject,
358 _Inout_ PVIDEO_WIN32K_CALLBACKS Win32kCallbacks,
359 _In_ ULONG BufferLength,
360 _Out_ PULONG_PTR Information)
361 {
362 *Information = sizeof(VIDEO_WIN32K_CALLBACKS);
363 if (BufferLength < sizeof(VIDEO_WIN32K_CALLBACKS))
364 {
365 ERR_(VIDEOPRT, "Buffer too small for VIDEO_WIN32K_CALLBACKS: %lx\n",
366 BufferLength);
367 return STATUS_BUFFER_TOO_SMALL;
368 }
369
370 /* Save the callout function globally */
371 Win32kCallout = Win32kCallbacks->Callout;
372
373 /* Return reasonable values to win32k */
374 Win32kCallbacks->bACPI = FALSE;
375 Win32kCallbacks->pPhysDeviceObject = DeviceObject;
376 Win32kCallbacks->DualviewFlags = 0;
377
378 return STATUS_SUCCESS;
379 }
380
381 static
382 NTSTATUS
383 VideoPortForwardDeviceControl(
384 IN PDEVICE_OBJECT DeviceObject,
385 IN PIRP Irp)
386 {
387 PIO_STACK_LOCATION IrpStack;
388 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
389 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
390 VIDEO_REQUEST_PACKET vrp;
391
392 TRACE_(VIDEOPRT, "VideoPortForwardDeviceControl\n");
393
394 IrpStack = IoGetCurrentIrpStackLocation(Irp);
395 DeviceExtension = DeviceObject->DeviceExtension;
396 DriverExtension = DeviceExtension->DriverExtension;
397
398 /* Translate the IRP to a VRP */
399 vrp.StatusBlock = (PSTATUS_BLOCK)&Irp->IoStatus;
400 vrp.IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
401
402 INFO_(VIDEOPRT, "- IoControlCode: %x\n", vrp.IoControlCode);
403
404 /* We're assuming METHOD_BUFFERED */
405 vrp.InputBuffer = Irp->AssociatedIrp.SystemBuffer;
406 vrp.InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
407 vrp.OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
408 vrp.OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
409
410 /* Call the Miniport Driver with the VRP */
411 DriverExtension->InitializationData.HwStartIO(&DeviceExtension->MiniPortDeviceExtension,
412 &vrp);
413
414 INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
415
416 /* Map from win32 error codes to NT status values. */
417 switch (Irp->IoStatus.Status)
418 {
419 case NO_ERROR:
420 return STATUS_SUCCESS;
421 case ERROR_NOT_ENOUGH_MEMORY:
422 return STATUS_INSUFFICIENT_RESOURCES;
423 case ERROR_MORE_DATA:
424 return STATUS_BUFFER_OVERFLOW;
425 case ERROR_INVALID_FUNCTION:
426 return STATUS_NOT_IMPLEMENTED;
427 case ERROR_INVALID_PARAMETER:
428 return STATUS_INVALID_PARAMETER;
429 case ERROR_INSUFFICIENT_BUFFER:
430 return STATUS_BUFFER_TOO_SMALL;
431 case ERROR_DEV_NOT_EXIST:
432 return STATUS_DEVICE_DOES_NOT_EXIST;
433 case ERROR_IO_PENDING:
434 return STATUS_PENDING;
435 default:
436 return STATUS_UNSUCCESSFUL;
437 }
438 }
439
440 /*
441 * IntVideoPortDispatchDeviceControl
442 *
443 * Answer requests for device control calls.
444 *
445 * Run Level
446 * PASSIVE_LEVEL
447 */
448 NTSTATUS
449 NTAPI
450 IntVideoPortDispatchDeviceControl(
451 IN PDEVICE_OBJECT DeviceObject,
452 IN PIRP Irp)
453 {
454 PIO_STACK_LOCATION IrpStack;
455 NTSTATUS Status;
456 ULONG IoControlCode;
457
458 TRACE_(VIDEOPRT, "IntVideoPortDispatchDeviceControl\n");
459
460 IrpStack = IoGetCurrentIrpStackLocation(Irp);
461
462 IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
463
464 INFO_(VIDEOPRT, "- IoControlCode: %x: %s\n", IoControlCode, IoctlName(IoControlCode));
465
466 switch(IoControlCode)
467 {
468 case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
469 INFO_(VIDEOPRT, "- IOCTL_VIDEO_INIT_WIN32K_CALLBACKS\n");
470 Status = VideoPortInitWin32kCallbacks(DeviceObject,
471 Irp->AssociatedIrp.SystemBuffer,
472 IrpStack->Parameters.DeviceIoControl.InputBufferLength,
473 &Irp->IoStatus.Information);
474 break;
475
476 case IOCTL_VIDEO_USE_DEVICE_IN_SESSION:
477 INFO_(VIDEOPRT, "- IOCTL_VIDEO_USE_DEVICE_IN_SESSION\n");
478 Status = VideoPortUseDeviceInSession(DeviceObject,
479 Irp->AssociatedIrp.SystemBuffer,
480 IrpStack->Parameters.DeviceIoControl.InputBufferLength,
481 &Irp->IoStatus.Information);
482 break;
483
484 default:
485 /* Forward to the Miniport Driver */
486 Status = VideoPortForwardDeviceControl(DeviceObject, Irp);
487 break;
488 }
489
490 INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
491
492 Irp->IoStatus.Status = Status;
493 IoCompleteRequest(Irp, IO_NO_INCREMENT);
494
495 return Status;
496 }
497
498 /*
499 * IntVideoPortWrite
500 *
501 * This is a bit of a hack. We want to take ownership of the display as late
502 * as possible, just before the switch to graphics mode. Win32k knows when
503 * this happens, we don't. So we need Win32k to inform us. This could be done
504 * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
505 * in the communication between GDI driver and miniport driver. So we use
506 * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
507 * since we know for certain that there is no read/write activity going on
508 * between GDI and miniport drivers.
509 * We don't actually need the data that is passed, we just trigger on the fact
510 * that an IRP_MJ_WRITE was sent.
511 *
512 * Run Level
513 * PASSIVE_LEVEL
514 */
515 NTSTATUS
516 NTAPI
517 IntVideoPortDispatchWrite(
518 IN PDEVICE_OBJECT DeviceObject,
519 IN PIRP Irp)
520 {
521 PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
522 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
523 NTSTATUS nErrCode;
524
525 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
526
527 /*
528 * Storing the device extension pointer in a static variable is an
529 * ugly hack. Unfortunately, we need it in IntVideoPortResetDisplayParameters
530 * and InbvNotifyDisplayOwnershipLost doesn't allow us to pass a userdata
531 * parameter. On the bright side, the DISPLAY device is opened
532 * exclusively, so there can be only one device extension active at
533 * any point in time.
534 *
535 * FIXME: We should process all opened display devices in
536 * IntVideoPortResetDisplayParameters.
537 */
538 ResetDisplayParametersDeviceExtension = DeviceExtension;
539 InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
540
541 nErrCode = STATUS_SUCCESS;
542 Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
543 Irp->IoStatus.Status = nErrCode;
544 IoCompleteRequest(Irp, IO_NO_INCREMENT);
545
546 return nErrCode;
547 }
548
549 NTSTATUS
550 NTAPI
551 IntVideoPortPnPStartDevice(
552 IN PDEVICE_OBJECT DeviceObject,
553 IN PIRP Irp)
554 {
555 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
556 PDRIVER_OBJECT DriverObject;
557 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
558 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
559 PCM_RESOURCE_LIST AllocatedResources;
560
561 /* Get the initialization data we saved in VideoPortInitialize.*/
562 DriverObject = DeviceObject->DriverObject;
563 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
564 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
565
566 /* Store some resources in the DeviceExtension. */
567 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
568 if (AllocatedResources != NULL)
569 {
570 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
571 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
572 ULONG ResourceCount;
573 ULONG ResourceListSize;
574
575 /* Save the resource list */
576 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
577 ResourceListSize =
578 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
579 PartialDescriptors[ResourceCount]);
580 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
581 if (DeviceExtension->AllocatedResources == NULL)
582 {
583 return STATUS_INSUFFICIENT_RESOURCES;
584 }
585
586 RtlCopyMemory(DeviceExtension->AllocatedResources,
587 AllocatedResources,
588 ResourceListSize);
589
590 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
591 for (FullList = AllocatedResources->List;
592 FullList < AllocatedResources->List + AllocatedResources->Count;
593 FullList++)
594 {
595 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
596 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
597
598 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
599 ASSERT(FullList->InterfaceType == PCIBus);
600 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
601 ASSERT(1 == FullList->PartialResourceList.Version);
602 ASSERT(1 == FullList->PartialResourceList.Revision);
603 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
604 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
605 Descriptor++)
606 {
607 if (Descriptor->Type == CmResourceTypeInterrupt)
608 {
609 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
610 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
611 if (Descriptor->ShareDisposition == CmResourceShareShared)
612 DeviceExtension->InterruptShared = TRUE;
613 else
614 DeviceExtension->InterruptShared = FALSE;
615 }
616 }
617 }
618 }
619
620 INFO_(VIDEOPRT, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
621 DeviceExtension->InterruptLevel,
622 DeviceExtension->InterruptVector);
623
624 /* Create adapter device object. */
625 return IntVideoPortFindAdapter(DriverObject,
626 DriverExtension,
627 DeviceObject);
628 }
629
630
631 NTSTATUS
632 NTAPI
633 IntVideoPortForwardIrpAndWaitCompletionRoutine(
634 PDEVICE_OBJECT Fdo,
635 PIRP Irp,
636 PVOID Context)
637 {
638 PKEVENT Event = Context;
639
640 if (Irp->PendingReturned)
641 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
642
643 return STATUS_MORE_PROCESSING_REQUIRED;
644 }
645
646 NTSTATUS
647 NTAPI
648 IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
649 {
650 PDEVICE_RELATIONS DeviceRelations;
651 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
652 PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
653 ULONG i;
654 PLIST_ENTRY CurrentEntry;
655
656 /* Count the children */
657 i = 0;
658 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
659 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
660 {
661 i++;
662 CurrentEntry = CurrentEntry->Flink;
663 }
664
665 if (i == 0)
666 return Irp->IoStatus.Status;
667
668 DeviceRelations = ExAllocatePool(PagedPool,
669 sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
670 if (!DeviceRelations) return STATUS_NO_MEMORY;
671
672 DeviceRelations->Count = i;
673
674 /* Add the children */
675 i = 0;
676 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
677 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
678 {
679 ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
680
681 ObReferenceObject(ChildExtension->PhysicalDeviceObject);
682 DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
683
684 i++;
685 CurrentEntry = CurrentEntry->Flink;
686 }
687
688 INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
689 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
690
691 return STATUS_SUCCESS;
692 }
693
694 NTSTATUS
695 NTAPI
696 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
697 {
698 KEVENT Event;
699 NTSTATUS Status;
700 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
701 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
702
703 KeInitializeEvent(&Event, NotificationEvent, FALSE);
704 IoCopyCurrentIrpStackLocationToNext(Irp);
705 IoSetCompletionRoutine(Irp,
706 IntVideoPortForwardIrpAndWaitCompletionRoutine,
707 &Event,
708 TRUE,
709 TRUE,
710 TRUE);
711
712 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
713 if (Status == STATUS_PENDING)
714 {
715 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
716 Status = Irp->IoStatus.Status;
717 }
718
719 return Status;
720 }
721
722 NTSTATUS
723 NTAPI
724 IntVideoPortDispatchFdoPnp(
725 IN PDEVICE_OBJECT DeviceObject,
726 IN PIRP Irp)
727 {
728 PIO_STACK_LOCATION IrpSp;
729 NTSTATUS Status;
730 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
731
732 IrpSp = IoGetCurrentIrpStackLocation(Irp);
733
734 switch (IrpSp->MinorFunction)
735 {
736 case IRP_MN_START_DEVICE:
737 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
738 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
739 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
740 Irp->IoStatus.Status = Status;
741 Irp->IoStatus.Information = 0;
742 IoCompleteRequest(Irp, IO_NO_INCREMENT);
743 break;
744
745 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
746 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
747 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
748 Status = IntVideoPortFilterResourceRequirements(DeviceObject, Irp);
749 Irp->IoStatus.Status = Status;
750 Irp->IoStatus.Information = 0;
751 IoCompleteRequest(Irp, IO_NO_INCREMENT);
752 break;
753
754 case IRP_MN_QUERY_DEVICE_RELATIONS:
755 if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
756 {
757 IoSkipCurrentIrpStackLocation(Irp);
758 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
759 }
760 else
761 {
762 Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
763 Irp->IoStatus.Status = Status;
764 IoCompleteRequest(Irp, IO_NO_INCREMENT);
765 }
766 break;
767
768 case IRP_MN_REMOVE_DEVICE:
769 case IRP_MN_QUERY_REMOVE_DEVICE:
770 case IRP_MN_CANCEL_REMOVE_DEVICE:
771 case IRP_MN_SURPRISE_REMOVAL:
772
773 case IRP_MN_STOP_DEVICE:
774 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
775 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
776 Status = STATUS_SUCCESS;
777 Irp->IoStatus.Status = Status;
778 Irp->IoStatus.Information = 0;
779 IoCompleteRequest(Irp, IO_NO_INCREMENT);
780 break;
781
782 case IRP_MN_QUERY_STOP_DEVICE:
783 case IRP_MN_CANCEL_STOP_DEVICE:
784 Status = STATUS_SUCCESS;
785 Irp->IoStatus.Status = STATUS_SUCCESS;
786 Irp->IoStatus.Information = 0;
787 IoCompleteRequest(Irp, IO_NO_INCREMENT);
788 break;
789
790 default:
791 Status = Irp->IoStatus.Status;
792 IoCompleteRequest(Irp, IO_NO_INCREMENT);
793 break;
794 }
795
796 return Status;
797 }
798
799 NTSTATUS
800 NTAPI
801 IntVideoPortDispatchPnp(
802 IN PDEVICE_OBJECT DeviceObject,
803 IN PIRP Irp)
804 {
805 PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
806
807 if (CommonExtension->Fdo)
808 return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
809 else
810 return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
811 }
812
813 NTSTATUS
814 NTAPI
815 IntVideoPortDispatchCleanup(
816 IN PDEVICE_OBJECT DeviceObject,
817 IN PIRP Irp)
818 {
819 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
820
821 DeviceExtension = DeviceObject->DeviceExtension;
822 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
823
824 Irp->IoStatus.Status = STATUS_SUCCESS;
825 Irp->IoStatus.Information = 0;
826 IoCompleteRequest(Irp, IO_NO_INCREMENT);
827
828 return STATUS_SUCCESS;
829 }
830
831 NTSTATUS
832 NTAPI
833 IntVideoPortDispatchPower(
834 IN PDEVICE_OBJECT DeviceObject,
835 IN PIRP Irp)
836 {
837 return STATUS_NOT_IMPLEMENTED;
838 }
839
840 NTSTATUS
841 NTAPI
842 IntVideoPortDispatchSystemControl(
843 IN PDEVICE_OBJECT DeviceObject,
844 IN PIRP Irp)
845 {
846 return STATUS_NOT_IMPLEMENTED;
847 }
848
849 VOID
850 NTAPI
851 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
852 {
853 }