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