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