[VIDEOPRT] Implement support for INT10 on x64 using the newly implemented HAL functions.
[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 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 }