[HNETCFG] Sync with Wine 3.0. CORE-14225
[reactos.git] / 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 FullList = AllocatedResources->List;
592 ASSERT(AllocatedResources->Count == 1);
593 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
594 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
595
596 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
597 ASSERT(FullList->InterfaceType == PCIBus);
598 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
599 ASSERT(1 == FullList->PartialResourceList.Version);
600 ASSERT(1 == FullList->PartialResourceList.Revision);
601 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
602 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
603 Descriptor++)
604 {
605 if (Descriptor->Type == CmResourceTypeInterrupt)
606 {
607 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
608 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
609 if (Descriptor->ShareDisposition == CmResourceShareShared)
610 DeviceExtension->InterruptShared = TRUE;
611 else
612 DeviceExtension->InterruptShared = FALSE;
613 }
614 }
615 }
616
617 INFO_(VIDEOPRT, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
618 DeviceExtension->InterruptLevel,
619 DeviceExtension->InterruptVector);
620
621 /* Create adapter device object. */
622 return IntVideoPortFindAdapter(DriverObject,
623 DriverExtension,
624 DeviceObject);
625 }
626
627
628 NTSTATUS
629 NTAPI
630 IntVideoPortForwardIrpAndWaitCompletionRoutine(
631 PDEVICE_OBJECT Fdo,
632 PIRP Irp,
633 PVOID Context)
634 {
635 PKEVENT Event = Context;
636
637 if (Irp->PendingReturned)
638 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
639
640 return STATUS_MORE_PROCESSING_REQUIRED;
641 }
642
643 NTSTATUS
644 NTAPI
645 IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
646 {
647 PDEVICE_RELATIONS DeviceRelations;
648 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
649 PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
650 ULONG i;
651 PLIST_ENTRY CurrentEntry;
652
653 /* Count the children */
654 i = 0;
655 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
656 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
657 {
658 i++;
659 CurrentEntry = CurrentEntry->Flink;
660 }
661
662 if (i == 0)
663 return Irp->IoStatus.Status;
664
665 DeviceRelations = ExAllocatePool(PagedPool,
666 sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
667 if (!DeviceRelations) return STATUS_NO_MEMORY;
668
669 DeviceRelations->Count = i;
670
671 /* Add the children */
672 i = 0;
673 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
674 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
675 {
676 ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
677
678 ObReferenceObject(ChildExtension->PhysicalDeviceObject);
679 DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
680
681 i++;
682 CurrentEntry = CurrentEntry->Flink;
683 }
684
685 INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
686 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
687
688 return STATUS_SUCCESS;
689 }
690
691 NTSTATUS
692 NTAPI
693 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
694 {
695 KEVENT Event;
696 NTSTATUS Status;
697 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
698 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
699
700 KeInitializeEvent(&Event, NotificationEvent, FALSE);
701 IoCopyCurrentIrpStackLocationToNext(Irp);
702 IoSetCompletionRoutine(Irp,
703 IntVideoPortForwardIrpAndWaitCompletionRoutine,
704 &Event,
705 TRUE,
706 TRUE,
707 TRUE);
708
709 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
710 if (Status == STATUS_PENDING)
711 {
712 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
713 Status = Irp->IoStatus.Status;
714 }
715
716 return Status;
717 }
718
719 NTSTATUS
720 NTAPI
721 IntVideoPortDispatchFdoPnp(
722 IN PDEVICE_OBJECT DeviceObject,
723 IN PIRP Irp)
724 {
725 PIO_STACK_LOCATION IrpSp;
726 NTSTATUS Status;
727 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
728
729 IrpSp = IoGetCurrentIrpStackLocation(Irp);
730
731 switch (IrpSp->MinorFunction)
732 {
733 case IRP_MN_START_DEVICE:
734 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
735 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
736 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
737 Irp->IoStatus.Status = Status;
738 Irp->IoStatus.Information = 0;
739 IoCompleteRequest(Irp, IO_NO_INCREMENT);
740 break;
741
742 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
743 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
744 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
745 Status = IntVideoPortFilterResourceRequirements(DeviceObject, Irp);
746 Irp->IoStatus.Status = Status;
747 Irp->IoStatus.Information = 0;
748 IoCompleteRequest(Irp, IO_NO_INCREMENT);
749 break;
750
751 case IRP_MN_QUERY_DEVICE_RELATIONS:
752 if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
753 {
754 IoSkipCurrentIrpStackLocation(Irp);
755 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
756 }
757 else
758 {
759 Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
760 Irp->IoStatus.Status = Status;
761 IoCompleteRequest(Irp, IO_NO_INCREMENT);
762 }
763 break;
764
765 case IRP_MN_REMOVE_DEVICE:
766 case IRP_MN_QUERY_REMOVE_DEVICE:
767 case IRP_MN_CANCEL_REMOVE_DEVICE:
768 case IRP_MN_SURPRISE_REMOVAL:
769
770 case IRP_MN_STOP_DEVICE:
771 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
772 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
773 Status = STATUS_SUCCESS;
774 Irp->IoStatus.Status = Status;
775 Irp->IoStatus.Information = 0;
776 IoCompleteRequest(Irp, IO_NO_INCREMENT);
777 break;
778
779 case IRP_MN_QUERY_STOP_DEVICE:
780 case IRP_MN_CANCEL_STOP_DEVICE:
781 Status = STATUS_SUCCESS;
782 Irp->IoStatus.Status = STATUS_SUCCESS;
783 Irp->IoStatus.Information = 0;
784 IoCompleteRequest(Irp, IO_NO_INCREMENT);
785 break;
786
787 default:
788 Status = Irp->IoStatus.Status;
789 IoCompleteRequest(Irp, IO_NO_INCREMENT);
790 break;
791 }
792
793 return Status;
794 }
795
796 NTSTATUS
797 NTAPI
798 IntVideoPortDispatchPnp(
799 IN PDEVICE_OBJECT DeviceObject,
800 IN PIRP Irp)
801 {
802 PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
803
804 if (CommonExtension->Fdo)
805 return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
806 else
807 return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
808 }
809
810 NTSTATUS
811 NTAPI
812 IntVideoPortDispatchCleanup(
813 IN PDEVICE_OBJECT DeviceObject,
814 IN PIRP Irp)
815 {
816 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
817
818 DeviceExtension = DeviceObject->DeviceExtension;
819 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
820
821 Irp->IoStatus.Status = STATUS_SUCCESS;
822 Irp->IoStatus.Information = 0;
823 IoCompleteRequest(Irp, IO_NO_INCREMENT);
824
825 return STATUS_SUCCESS;
826 }
827
828 NTSTATUS
829 NTAPI
830 IntVideoPortDispatchPower(
831 IN PDEVICE_OBJECT DeviceObject,
832 IN PIRP Irp)
833 {
834 PIO_STACK_LOCATION IrpSp;
835 NTSTATUS Status = Irp->IoStatus.Status;
836 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
837
838 IrpSp = IoGetCurrentIrpStackLocation(Irp);
839
840 if (DeviceExtension->Common.Fdo)
841 {
842 PoStartNextPowerIrp(Irp);
843 IoSkipCurrentIrpStackLocation(Irp);
844 return PoCallDriver(DeviceExtension->NextDeviceObject, Irp);
845 }
846 else
847 {
848 switch (IrpSp->MinorFunction)
849 {
850 case IRP_MN_QUERY_POWER:
851 case IRP_MN_SET_POWER:
852 Status = STATUS_SUCCESS;
853 break;
854 }
855 PoStartNextPowerIrp(Irp);
856 Irp->IoStatus.Status = Status;
857 IoCompleteRequest(Irp, IO_NO_INCREMENT);
858 return Status;
859 }
860 }
861
862 NTSTATUS
863 NTAPI
864 IntVideoPortDispatchSystemControl(
865 IN PDEVICE_OBJECT DeviceObject,
866 IN PIRP Irp)
867 {
868 NTSTATUS Status;
869 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
870
871 if (DeviceExtension->Common.Fdo)
872 {
873 IoSkipCurrentIrpStackLocation(Irp);
874 return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
875 }
876 else
877 {
878 Status = Irp->IoStatus.Status;
879 IoCompleteRequest(Irp, IO_NO_INCREMENT);
880 return Status;
881 }
882 }
883
884 VOID
885 NTAPI
886 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
887 {
888 }