[WIN32SS]
[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
28 /* PRIVATE FUNCTIONS **********************************************************/
29
30 /*
31 * Reset display to blue screen
32 */
33
34 BOOLEAN NTAPI
35 IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
36 {
37 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
38
39 if (ResetDisplayParametersDeviceExtension == NULL)
40 return FALSE;
41
42 DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
43
44 if (DriverExtension->InitializationData.HwResetHw != NULL)
45 {
46 if (DriverExtension->InitializationData.HwResetHw(
47 &ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
48 Columns, Rows))
49 {
50 ResetDisplayParametersDeviceExtension = NULL;
51 return TRUE;
52 }
53 }
54
55 ResetDisplayParametersDeviceExtension = NULL;
56 return FALSE;
57 }
58
59 NTSTATUS NTAPI
60 IntVideoPortAddDevice(
61 IN PDRIVER_OBJECT DriverObject,
62 IN PDEVICE_OBJECT PhysicalDeviceObject)
63 {
64 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
65 PDEVICE_OBJECT DeviceObject;
66 NTSTATUS Status;
67
68 /*
69 * Get the initialization data we saved in VideoPortInitialize.
70 */
71
72 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
73
74 /*
75 * Create adapter device object.
76 */
77
78 Status = IntVideoPortCreateAdapterDeviceObject(
79 DriverObject,
80 DriverExtension,
81 PhysicalDeviceObject,
82 &DeviceObject);
83 if (NT_SUCCESS(Status))
84 VideoPortDeviceNumber++;
85
86 return Status;
87 }
88
89 /*
90 * IntVideoPortDispatchOpen
91 *
92 * Answer requests for Open calls.
93 *
94 * Run Level
95 * PASSIVE_LEVEL
96 */
97
98 NTSTATUS NTAPI
99 IntVideoPortDispatchOpen(
100 IN PDEVICE_OBJECT DeviceObject,
101 IN PIRP Irp)
102 {
103 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
104 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
105
106 TRACE_(VIDEOPRT, "IntVideoPortDispatchOpen\n");
107
108 if (CsrssInitialized == FALSE)
109 {
110 /*
111 * We know the first open call will be from the CSRSS process
112 * to let us know its handle.
113 */
114
115 INFO_(VIDEOPRT, "Referencing CSRSS\n");
116 Csrss = (PKPROCESS)PsGetCurrentProcess();
117 INFO_(VIDEOPRT, "Csrss %p\n", Csrss);
118
119 CsrssInitialized = TRUE;
120
121 Irp->IoStatus.Information = FILE_OPENED;
122 IoCompleteRequest(Irp, IO_NO_INCREMENT);
123
124 return STATUS_SUCCESS;
125 }
126
127 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
128 DriverExtension = DeviceExtension->DriverExtension;
129
130 if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
131 {
132 Irp->IoStatus.Status = STATUS_SUCCESS;
133
134 InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
135 }
136 else
137 {
138 Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
139 }
140
141 Irp->IoStatus.Information = FILE_OPENED;
142 IoCompleteRequest(Irp, IO_NO_INCREMENT);
143
144 return STATUS_SUCCESS;
145 }
146
147 /*
148 * IntVideoPortDispatchClose
149 *
150 * Answer requests for Close calls.
151 *
152 * Run Level
153 * PASSIVE_LEVEL
154 */
155
156 NTSTATUS NTAPI
157 IntVideoPortDispatchClose(
158 IN PDEVICE_OBJECT DeviceObject,
159 IN PIRP Irp)
160 {
161 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
162
163 TRACE_(VIDEOPRT, "IntVideoPortDispatchClose\n");
164
165 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
166 if (DeviceExtension->DeviceOpened >= 1 &&
167 InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0)
168 {
169 ResetDisplayParametersDeviceExtension = NULL;
170 InbvNotifyDisplayOwnershipLost(NULL);
171 ResetDisplayParametersDeviceExtension = DeviceExtension;
172 IntVideoPortResetDisplayParameters(80, 50);
173 }
174
175 Irp->IoStatus.Status = STATUS_SUCCESS;
176 IoCompleteRequest(Irp, IO_NO_INCREMENT);
177
178 return STATUS_SUCCESS;
179 }
180
181 /*
182 * IntVideoPortDispatchDeviceControl
183 *
184 * Answer requests for device control calls.
185 *
186 * Run Level
187 * PASSIVE_LEVEL
188 */
189
190 NTSTATUS NTAPI
191 IntVideoPortDispatchDeviceControl(
192 IN PDEVICE_OBJECT DeviceObject,
193 IN PIRP Irp)
194 {
195 PIO_STACK_LOCATION IrpStack;
196 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
197 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
198 PVIDEO_REQUEST_PACKET vrp;
199 NTSTATUS Status;
200
201 TRACE_(VIDEOPRT, "IntVideoPortDispatchDeviceControl\n");
202
203 IrpStack = IoGetCurrentIrpStackLocation(Irp);
204 DeviceExtension = DeviceObject->DeviceExtension;
205 DriverExtension = DeviceExtension->DriverExtension;
206
207 /* Translate the IRP to a VRP */
208 vrp = ExAllocatePool(NonPagedPool, sizeof(VIDEO_REQUEST_PACKET));
209 if (NULL == vrp)
210 {
211 return STATUS_NO_MEMORY;
212 }
213
214 vrp->StatusBlock = (PSTATUS_BLOCK)&(Irp->IoStatus);
215 vrp->IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
216
217 INFO_(VIDEOPRT, "- IoControlCode: %x\n", vrp->IoControlCode);
218
219 /* We're assuming METHOD_BUFFERED */
220 vrp->InputBuffer = Irp->AssociatedIrp.SystemBuffer;
221 vrp->InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
222 vrp->OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
223 vrp->OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
224
225 /* Call the Miniport Driver with the VRP */
226 DriverExtension->InitializationData.HwStartIO(
227 &DeviceExtension->MiniPortDeviceExtension,
228 vrp);
229
230 /* Free the VRP */
231 ExFreePool(vrp);
232
233 INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
234
235 if (Irp->IoStatus.Status != STATUS_SUCCESS)
236 {
237 /* Map from win32 error codes to NT status values. */
238 switch (Irp->IoStatus.Status)
239 {
240 case ERROR_NOT_ENOUGH_MEMORY: Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; break;
241 case ERROR_MORE_DATA: Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; break;
242 case ERROR_INVALID_FUNCTION: Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; break;
243 case ERROR_INVALID_PARAMETER: Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break;
244 case ERROR_INSUFFICIENT_BUFFER: Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL; break;
245 case ERROR_DEV_NOT_EXIST: Irp->IoStatus.Status = STATUS_DEVICE_DOES_NOT_EXIST; break;
246 case ERROR_IO_PENDING: Irp->IoStatus.Status = STATUS_PENDING; break;
247 }
248 }
249
250 Status = Irp->IoStatus.Status;
251 IoCompleteRequest(Irp, IO_NO_INCREMENT);
252
253 return Status;
254 }
255
256 /*
257 * IntVideoPortWrite
258 *
259 * This is a bit of a hack. We want to take ownership of the display as late
260 * as possible, just before the switch to graphics mode. Win32k knows when
261 * this happens, we don't. So we need Win32k to inform us. This could be done
262 * using an IOCTL, but there's no way of knowing which IOCTL codes are unused
263 * in the communication between GDI driver and miniport driver. So we use
264 * IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
265 * since we know for certain that there is no read/write activity going on
266 * between GDI and miniport drivers.
267 * We don't actually need the data that is passed, we just trigger on the fact
268 * that an IRP_MJ_WRITE was sent.
269 *
270 * Run Level
271 * PASSIVE_LEVEL
272 */
273
274 NTSTATUS NTAPI
275 IntVideoPortDispatchWrite(
276 IN PDEVICE_OBJECT DeviceObject,
277 IN PIRP Irp)
278 {
279 PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
280 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
281 NTSTATUS nErrCode;
282
283 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
284
285 /*
286 * Storing the device extension pointer in a static variable is an
287 * ugly hack. Unfortunately, we need it in IntVideoPortResetDisplayParameters
288 * and InbvNotifyDisplayOwnershipLost doesn't allow us to pass a userdata
289 * parameter. On the bright side, the DISPLAY device is opened
290 * exclusively, so there can be only one device extension active at
291 * any point in time.
292 *
293 * FIXME: We should process all opened display devices in
294 * IntVideoPortResetDisplayParameters.
295 */
296
297 ResetDisplayParametersDeviceExtension = DeviceExtension;
298 InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
299
300 nErrCode = STATUS_SUCCESS;
301 Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
302 Irp->IoStatus.Status = nErrCode;
303 IoCompleteRequest(Irp, IO_NO_INCREMENT);
304
305 return nErrCode;
306 }
307
308 NTSTATUS NTAPI
309 IntVideoPortPnPStartDevice(
310 IN PDEVICE_OBJECT DeviceObject,
311 IN PIRP Irp)
312 {
313 PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
314 PDRIVER_OBJECT DriverObject;
315 PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
316 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
317 PCM_RESOURCE_LIST AllocatedResources;
318
319 /*
320 * Get the initialization data we saved in VideoPortInitialize.
321 */
322
323 DriverObject = DeviceObject->DriverObject;
324 DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
325 DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
326
327 /*
328 * Store some resources in the DeviceExtension.
329 */
330
331 AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
332 if (AllocatedResources != NULL)
333 {
334 CM_FULL_RESOURCE_DESCRIPTOR *FullList;
335 CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
336 ULONG ResourceCount;
337 ULONG ResourceListSize;
338
339 /* Save the resource list */
340 ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
341 ResourceListSize =
342 FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
343 PartialDescriptors[ResourceCount]);
344 DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
345 if (DeviceExtension->AllocatedResources == NULL)
346 {
347 return STATUS_INSUFFICIENT_RESOURCES;
348 }
349
350 RtlCopyMemory(DeviceExtension->AllocatedResources,
351 AllocatedResources,
352 ResourceListSize);
353
354 /* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
355 for (FullList = AllocatedResources->List;
356 FullList < AllocatedResources->List + AllocatedResources->Count;
357 FullList++)
358 {
359 INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
360 FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
361
362 /* FIXME: Is this ASSERT ok for resources from the PNP manager? */
363 ASSERT(FullList->InterfaceType == PCIBus);
364 ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
365 ASSERT(1 == FullList->PartialResourceList.Version);
366 ASSERT(1 == FullList->PartialResourceList.Revision);
367 for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
368 Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
369 Descriptor++)
370 {
371 if (Descriptor->Type == CmResourceTypeInterrupt)
372 {
373 DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
374 DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
375 if (Descriptor->ShareDisposition == CmResourceShareShared)
376 DeviceExtension->InterruptShared = TRUE;
377 else
378 DeviceExtension->InterruptShared = FALSE;
379 }
380 }
381 }
382 }
383 INFO_(VIDEOPRT, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
384 DeviceExtension->InterruptLevel,
385 DeviceExtension->InterruptVector);
386
387 /*
388 * Create adapter device object.
389 */
390
391 return IntVideoPortFindAdapter(
392 DriverObject,
393 DriverExtension,
394 DeviceObject);
395 }
396
397
398 NTSTATUS
399 NTAPI
400 IntVideoPortForwardIrpAndWaitCompletionRoutine(
401 PDEVICE_OBJECT Fdo,
402 PIRP Irp,
403 PVOID Context)
404 {
405 PKEVENT Event = Context;
406
407 if (Irp->PendingReturned)
408 KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
409
410 return STATUS_MORE_PROCESSING_REQUIRED;
411 }
412
413 NTSTATUS
414 NTAPI
415 IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
416 {
417 PDEVICE_RELATIONS DeviceRelations;
418 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
419 PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
420 ULONG i;
421 PLIST_ENTRY CurrentEntry;
422
423 /* Count the children */
424 i = 0;
425 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
426 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
427 {
428 i++;
429 CurrentEntry = CurrentEntry->Flink;
430 }
431
432 if (i == 0)
433 return Irp->IoStatus.Status;
434
435 DeviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
436 if (!DeviceRelations) return STATUS_NO_MEMORY;
437
438 DeviceRelations->Count = i;
439
440 /* Add the children */
441 i = 0;
442 CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
443 while (CurrentEntry != &DeviceExtension->ChildDeviceList)
444 {
445 ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
446
447 ObReferenceObject(ChildExtension->PhysicalDeviceObject);
448 DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
449
450 i++;
451 CurrentEntry = CurrentEntry->Flink;
452 }
453
454 INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
455 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
456
457 return STATUS_SUCCESS;
458 }
459
460 NTSTATUS
461 NTAPI
462 IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
463 {
464 KEVENT Event;
465 NTSTATUS Status;
466 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
467 (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
468
469 KeInitializeEvent(&Event, NotificationEvent, FALSE);
470 IoCopyCurrentIrpStackLocationToNext(Irp);
471 IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine,
472 &Event, TRUE, TRUE, TRUE);
473 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
474 if (Status == STATUS_PENDING)
475 {
476 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
477 Status = Irp->IoStatus.Status;
478 }
479 return Status;
480 }
481
482 NTSTATUS NTAPI
483 IntVideoPortDispatchFdoPnp(
484 IN PDEVICE_OBJECT DeviceObject,
485 IN PIRP Irp)
486 {
487 PIO_STACK_LOCATION IrpSp;
488 NTSTATUS Status;
489 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
490
491 IrpSp = IoGetCurrentIrpStackLocation(Irp);
492
493 switch (IrpSp->MinorFunction)
494 {
495 case IRP_MN_START_DEVICE:
496 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
497 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
498 Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
499 Irp->IoStatus.Status = Status;
500 Irp->IoStatus.Information = 0;
501 IoCompleteRequest(Irp, IO_NO_INCREMENT);
502 break;
503
504 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
505 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
506 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
507 Status = IntVideoPortFilterResourceRequirements(DeviceObject, Irp);
508 Irp->IoStatus.Status = Status;
509 Irp->IoStatus.Information = 0;
510 IoCompleteRequest(Irp, IO_NO_INCREMENT);
511 break;
512
513 case IRP_MN_QUERY_DEVICE_RELATIONS:
514 if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
515 {
516 IoSkipCurrentIrpStackLocation(Irp);
517 Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
518 }
519 else
520 {
521 Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
522 Irp->IoStatus.Status = Status;
523 IoCompleteRequest(Irp, IO_NO_INCREMENT);
524 }
525 break;
526
527 case IRP_MN_REMOVE_DEVICE:
528 case IRP_MN_QUERY_REMOVE_DEVICE:
529 case IRP_MN_CANCEL_REMOVE_DEVICE:
530 case IRP_MN_SURPRISE_REMOVAL:
531
532 case IRP_MN_STOP_DEVICE:
533 Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
534 if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
535 Status = STATUS_SUCCESS;
536 Irp->IoStatus.Status = Status;
537 Irp->IoStatus.Information = 0;
538 IoCompleteRequest(Irp, IO_NO_INCREMENT);
539 break;
540
541 case IRP_MN_QUERY_STOP_DEVICE:
542 case IRP_MN_CANCEL_STOP_DEVICE:
543 Status = STATUS_SUCCESS;
544 Irp->IoStatus.Status = STATUS_SUCCESS;
545 Irp->IoStatus.Information = 0;
546 IoCompleteRequest(Irp, IO_NO_INCREMENT);
547 break;
548
549 default:
550 Status = Irp->IoStatus.Status;
551 IoCompleteRequest(Irp, IO_NO_INCREMENT);
552 break;
553 }
554
555 return Status;
556 }
557
558 NTSTATUS NTAPI
559 IntVideoPortDispatchPnp(
560 IN PDEVICE_OBJECT DeviceObject,
561 IN PIRP Irp)
562 {
563 PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
564
565 if (CommonExtension->Fdo)
566 return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
567 else
568 return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
569 }
570
571 NTSTATUS NTAPI
572 IntVideoPortDispatchCleanup(
573 IN PDEVICE_OBJECT DeviceObject,
574 IN PIRP Irp)
575 {
576 PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
577
578 DeviceExtension = DeviceObject->DeviceExtension;
579 RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
580
581 Irp->IoStatus.Status = STATUS_SUCCESS;
582 Irp->IoStatus.Information = 0;
583 IoCompleteRequest(Irp, IO_NO_INCREMENT);
584
585 return STATUS_SUCCESS;
586 }
587
588 NTSTATUS NTAPI
589 IntVideoPortDispatchPower(
590 IN PDEVICE_OBJECT DeviceObject,
591 IN PIRP Irp)
592 {
593 return STATUS_NOT_IMPLEMENTED;
594 }
595
596 NTSTATUS NTAPI
597 IntVideoPortDispatchSystemControl(
598 IN PDEVICE_OBJECT DeviceObject,
599 IN PIRP Irp)
600 {
601 return STATUS_NOT_IMPLEMENTED;
602 }
603
604 VOID NTAPI
605 IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
606 {
607 }