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