Something went wrong. Try again.
Reactos
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291/* * VideoPort driver * * Copyright (C) 2002, 2003, 2004 ReactOS Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */
#include "videoprt.h"
#include <ndk/inbvfuncs.h>#include <ndk/obfuncs.h>#include <ndk/psfuncs.h>
#define NDEBUG#include <debug.h>
/* GLOBAL VARIABLES ***********************************************************/
static PVIDEO_WIN32K_CALLOUT Win32kCallout = NULL;static HANDLE InbvThreadHandle = NULL;static BOOLEAN InbvMonitoring = FALSE;
/* PRIVATE FUNCTIONS **********************************************************/
static VOIDVideoPortWin32kCallout( _In_ PVIDEO_WIN32K_CALLBACKS_PARAMS CallbackParams){ if (!Win32kCallout) return;
/* Perform the call in the CSRSS context */ if (!CsrProcess) return;
KeAttachProcess(CsrProcess); Win32kCallout(CallbackParams); KeDetachProcess();}
/* * Reinitialize the display to base VGA mode. * * Returns TRUE if it completely resets the adapter to the given character mode. * Returns FALSE otherwise, indicating that the HAL should perform the VGA mode * reset itself after HwVidResetHw() returns control. * * This callback has been registered with InbvNotifyDisplayOwnershipLost() * and is called by InbvAcquireDisplayOwnership(), typically when the bugcheck * code regains display access. Therefore this routine can be called at any * IRQL, and in particular at IRQL = HIGH_LEVEL. This routine must also reside * completely in non-paged pool, and cannot perform the following actions: * Allocate memory, access pageable memory, use any synchronization mechanisms * or call any routine that must execute at IRQL = DISPATCH_LEVEL or below. */static BOOLEANNTAPIIntVideoPortResetDisplayParametersEx( _In_ ULONG Columns, _In_ ULONG Rows, _In_ BOOLEAN CalledByInbv){ BOOLEAN Success = TRUE; // Suppose we don't need to perform a full reset. KIRQL OldIrql; PLIST_ENTRY PrevEntry, Entry; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
/* Check if we are at dispatch level or lower, and acquire the lock */ OldIrql = KeGetCurrentIrql(); if (OldIrql <= DISPATCH_LEVEL) { /* Loop until the lock is free, then raise IRQL to dispatch level */ while (!KeTestSpinLock(&HwResetAdaptersLock)); KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); } KeAcquireSpinLockAtDpcLevel(&HwResetAdaptersLock);
/* Bail out early if we don't have any resettable adapter */ if (IsListEmpty(&HwResetAdaptersList)) { Success = FALSE; // No adapter found: request HAL to perform a full reset. goto Quit; }
/* * If we have been unexpectedly called via a callback from * InbvAcquireDisplayOwnership(), start monitoring INBV. */ if (CalledByInbv) InbvMonitoring = TRUE;
for (PrevEntry = &HwResetAdaptersList, Entry = PrevEntry->Flink; Entry != &HwResetAdaptersList; PrevEntry = Entry, Entry = Entry->Flink) { /* * Check whether the entry address is properly aligned, * the device and driver extensions must be readable and * the device extension properly back-linked to the last entry. */// #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0) if (((ULONG_PTR)Entry & (sizeof(ULONG_PTR) - 1)) != 0) { Success = FALSE; // We failed: request HAL to perform a full reset. goto Quit; }
DeviceExtension = CONTAINING_RECORD(Entry, VIDEO_PORT_DEVICE_EXTENSION, HwResetListEntry); /* * As this function can be called as part of the INBV initialization * by the bugcheck code, avoid any problems and protect all accesses * within SEH. */ _SEH2_TRY { DriverExtension = DeviceExtension->DriverExtension; ASSERT(DriverExtension);
if (DeviceExtension->HwResetListEntry.Blink != PrevEntry) { Success = FALSE; // We failed: request HAL to perform a full reset. _SEH2_YIELD(goto Quit); }
if ((DeviceExtension->DeviceOpened >= 1) && (DriverExtension->InitializationData.HwResetHw != NULL)) { Success &= DriverExtension->InitializationData.HwResetHw( &DeviceExtension->MiniPortDeviceExtension, Columns, Rows); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { } _SEH2_END; }
Quit: /* Release the lock and restore the old IRQL if we were at dispatch level or lower */ KeReleaseSpinLockFromDpcLevel(&HwResetAdaptersLock); if (OldIrql <= DISPATCH_LEVEL) KeLowerIrql(OldIrql);
return Success;}
/* This callback is registered with InbvNotifyDisplayOwnershipLost() */static BOOLEANNTAPIIntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows){ /* Call the extended function, specifying we were called by INBV */ return IntVideoPortResetDisplayParametersEx(Columns, Rows, TRUE);}
/* * (Adapted for ReactOS/Win2k3 from an original comment * by Gé van Geldorp, June 2003, r4937) * * DISPLAY OWNERSHIP * * So, who owns the physical display and is allowed to write to it? * * In NT 5.x (Win2k/Win2k3), upon boot INBV/BootVid owns the display, unless * /NOGUIBOOT has been specified in the boot command line. Later in the boot * sequence, WIN32K.SYS opens the DISPLAY device. This open call ends up in * VIDEOPRT.SYS. This component takes ownership of the display by calling * InbvNotifyDisplayOwnershipLost() -- effectively telling INBV to release * ownership of the display it previously had. From that moment on, the display * is owned by that component and can be switched to graphics mode. The display * is not supposed to return to text mode, except in case of a bugcheck. * The bugcheck code calls InbvAcquireDisplayOwnership() so as to make INBV * re-take display ownership, and calls back the function previously registered * by VIDEOPRT.SYS with InbvNotifyDisplayOwnershipLost(). After the bugcheck, * execution is halted. So, under NT, the only possible sequence of display * modes is text mode -> graphics mode -> text mode (the latter hopefully * happening very infrequently). * * In ReactOS things are a little bit different. We want to have a functional * interactive text mode. We should be able to switch back and forth from * text mode to graphics mode when a GUI app is started and then finished. * Also, when the system bugchecks in graphics mode we want to switch back to * text mode and show the bugcheck information. Last but not least, when using * KDBG in /DEBUGPORT=SCREEN mode, breaking into the debugger would trigger a * switch to text mode, and the user would expect that by continuing execution * a switch back to graphics mode is done. */static VOIDNTAPIInbvMonitorThread( _In_ PVOID Context){ VIDEO_WIN32K_CALLBACKS_PARAMS CallbackParams; LARGE_INTEGER Delay; USHORT i;
KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
while (TRUE) { /* * During one second, check the INBV status each 100 milliseconds, * then revert to 1 second delay. */ i = 10; Delay.QuadPart = (LONGLONG)-100*1000*10; // 100 millisecond delay while (!InbvMonitoring) { KeDelayExecutionThread(KernelMode, FALSE, &Delay);
if ((i > 0) && (--i == 0)) Delay.QuadPart = (LONGLONG)-1*1000*1000*10; // 1 second delay }
/* * Loop while the display is owned by INBV. We cannot do anything else * than polling since INBV does not offer a proper notification system. * * During one second, check the INBV status each 100 milliseconds, * then revert to 1 second delay. */ i = 10; Delay.QuadPart = (LONGLONG)-100*1000*10; // 100 millisecond delay while (InbvCheckDisplayOwnership()) { KeDelayExecutionThread(KernelMode, FALSE, &Delay);
if ((i > 0) && (--i == 0)) Delay.QuadPart = (LONGLONG)-1*1000*1000*10; // 1 second delay }
/* Reset the monitoring */ InbvMonitoring = FALSE;
/* * Somebody released INBV display ownership, usually by invoking * InbvNotifyDisplayOwnershipLost(). However the caller of this * function certainly specified a different callback than ours. * As we are going to be the only owner of the active display, * we need to re-register our own display reset callback. */ InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
/* Tell Win32k to reset the display */ CallbackParams.CalloutType = VideoFindAdapterCallout; // CallbackParams.PhysDisp = NULL; CallbackParams.Param = (ULONG_PTR)TRUE; // TRUE: Re-enable display; FALSE: Disable display. VideoPortWin32kCallout(&CallbackParams); }
// FIXME: See IntVideoPortInbvCleanup(). // PsTerminateSystemThread(STATUS_SUCCESS);}
static NTSTATUSIntVideoPortInbvInitialize(VOID){ /* Create the INBV monitoring thread if needed */ if (!InbvThreadHandle) { NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes = RTL_CONSTANT_OBJECT_ATTRIBUTES(NULL, OBJ_KERNEL_HANDLE);
Status = PsCreateSystemThread(&InbvThreadHandle, 0, &ObjectAttributes, NULL, NULL, InbvMonitorThread, NULL); if (!NT_SUCCESS(Status)) InbvThreadHandle = NULL; }
/* Re-register the display reset callback with INBV */ InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
return STATUS_SUCCESS;}
static NTSTATUSIntVideoPortInbvCleanup( IN PDEVICE_OBJECT DeviceObject){ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; // HANDLE ThreadHandle;
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if ((DeviceExtension->DeviceOpened >= 1) && (InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0)) { // RemoveEntryList(&DeviceExtension->HwResetListEntry); InbvNotifyDisplayOwnershipLost(NULL); IntVideoPortResetDisplayParametersEx(80, 50, FALSE); // or InbvAcquireDisplayOwnership(); ? }
#if 0 // TODO: Find the best way to communicate the request. /* Signal the INBV monitoring thread and wait for it to terminate */ ThreadHandle = InterlockedExchangePointer((PVOID*)&InbvThreadHandle, NULL); if (ThreadHandle) { KeWaitForSingleObject(&ThreadHandle, Executive, KernelMode, FALSE, NULL); /* Close its handle */ ObCloseHandle(ThreadHandle, KernelMode); }#endif
return STATUS_SUCCESS;}
NTSTATUSNTAPIIntVideoPortAddDevice( IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject){ PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; PDEVICE_OBJECT DeviceObject; NTSTATUS Status;
/* Get the initialization data we saved in VideoPortInitialize. */ DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
/* Create adapter device object. */ Status = IntVideoPortCreateAdapterDeviceObject(DriverObject, DriverExtension, PhysicalDeviceObject, DriverExtension->InitializationData.StartingDeviceNumber, 0, &DeviceObject); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "IntVideoPortCreateAdapterDeviceObject() failed with status 0x%lx\n", Status); } return Status;}
/* * IntVideoPortDispatchOpen * * Answer requests for Open calls. * * Run Level * PASSIVE_LEVEL */NTSTATUSNTAPIIntVideoPortDispatchOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ NTSTATUS Status; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
TRACE_(VIDEOPRT, "IntVideoPortDispatchOpen\n");
if (!CsrProcess) { /* We know the first open call is from the CSRSS process. * Get a reference to it for Int10 support. */ INFO_(VIDEOPRT, "Referencing CSRSS\n"); CsrProcess = (PKPROCESS)PsGetCurrentProcess(); ObReferenceObject(CsrProcess); INFO_(VIDEOPRT, "CsrProcess 0x%p\n", CsrProcess);
Status = IntInitializeInt10(); if (!NT_SUCCESS(Status)) { ERR_(VIDEOPRT, "IntInitializeInt10() failed: 0x%lx\n", Status); ObDereferenceObject(CsrProcess); CsrProcess = NULL; return Status; } }
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension; DriverExtension = DeviceExtension->DriverExtension;
// FIXME: (Re-)initialize INBV only if DeviceObject doesn't belong to a mirror driver. IntVideoPortInbvInitialize();
if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension)) { Status = STATUS_SUCCESS; InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
/* Query children, now that device is opened */ VideoPortEnumerateChildren(DeviceExtension->MiniPortDeviceExtension, NULL); } else { Status = STATUS_UNSUCCESSFUL; }
Irp->IoStatus.Status = Status; Irp->IoStatus.Information = FILE_OPENED; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;}
/* * IntVideoPortDispatchClose * * Answer requests for Close calls. * * Run Level * PASSIVE_LEVEL */NTSTATUSNTAPIIntVideoPortDispatchClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ TRACE_(VIDEOPRT, "IntVideoPortDispatchClose\n");
IntVideoPortInbvCleanup(DeviceObject);
Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS;}
PSTRIoctlName(ULONG Ioctl){ switch (Ioctl) { case IOCTL_VIDEO_ENABLE_VDM: return "IOCTL_VIDEO_ENABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_DISABLE_VDM: return "IOCTL_VIDEO_DISABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_REGISTER_VDM: return "IOCTL_VIDEO_REGISTER_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE: return "IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE: return "IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_MONITOR_DEVICE: return "IOCTL_VIDEO_MONITOR_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_ENUM_MONITOR_PDO: return "IOCTL_VIDEO_ENUM_MONITOR_PDO"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS: return "IOCTL_VIDEO_INIT_WIN32K_CALLBACKS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS: return "IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_IS_VGA_DEVICE: return "IOCTL_VIDEO_IS_VGA_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_USE_DEVICE_IN_SESSION: return "IOCTL_VIDEO_USE_DEVICE_IN_SESSION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0a, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_PREPARE_FOR_EARECOVERY: return "IOCTL_VIDEO_PREPARE_FOR_EARECOVERY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0b, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SAVE_HARDWARE_STATE: return "IOCTL_VIDEO_SAVE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x80, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_RESTORE_HARDWARE_STATE: return "IOCTL_VIDEO_RESTORE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x81, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_AVAIL_MODES: return "IOCTL_VIDEO_QUERY_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x100, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES: return "IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x101, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_CURRENT_MODE: return "IOCTL_VIDEO_QUERY_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x102, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_CURRENT_MODE: return "IOCTL_VIDEO_SET_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x103, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_RESET_DEVICE: return "IOCTL_VIDEO_RESET_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x104, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_LOAD_AND_SET_FONT: return "IOCTL_VIDEO_LOAD_AND_SET_FONT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x105, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_PALETTE_REGISTERS: return "IOCTL_VIDEO_SET_PALETTE_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x106, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_COLOR_REGISTERS: return "IOCTL_VIDEO_SET_COLOR_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x107, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_ENABLE_CURSOR: return "IOCTL_VIDEO_ENABLE_CURSOR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x108, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_DISABLE_CURSOR: return "IOCTL_VIDEO_DISABLE_CURSOR"; // CTL_CODE (FILE_DEVICE_VIDEO, 0x109, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_CURSOR_ATTR: return "IOCTL_VIDEO_SET_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10a, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_CURSOR_ATTR: return "IOCTL_VIDEO_QUERY_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10b, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_CURSOR_POSITION: return "IOCTL_VIDEO_SET_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10c, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_CURSOR_POSITION: return "IOCTL_VIDEO_QUERY_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10d, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_ENABLE_POINTER: return "IOCTL_VIDEO_ENABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10e, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_DISABLE_POINTER: return "IOCTL_VIDEO_DISABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10f, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_POINTER_ATTR: return "IOCTL_VIDEO_SET_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x110, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_POINTER_ATTR: return "IOCTL_VIDEO_QUERY_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x111, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_POINTER_POSITION: return "IOCTL_VIDEO_SET_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x112, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_POINTER_POSITION: return "IOCTL_VIDEO_QUERY_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x113, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES: return "IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x114, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_GET_BANK_SELECT_CODE: return "IOCTL_VIDEO_GET_BANK_SELECT_CODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x115, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_MAP_VIDEO_MEMORY: return "IOCTL_VIDEO_MAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x116, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: return "IOCTL_VIDEO_UNMAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x117, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES: return "IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x118, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES: return "IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x119, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES: return "IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11a, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_POWER_MANAGEMENT: return "IOCTL_VIDEO_SET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11b, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_GET_POWER_MANAGEMENT: return "IOCTL_VIDEO_GET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11c, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SHARE_VIDEO_MEMORY: return "IOCTL_VIDEO_SHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11d, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY: return "IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11e, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_COLOR_LUT_DATA: return "IOCTL_VIDEO_SET_COLOR_LUT_DATA"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11f, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_GET_CHILD_STATE: return "IOCTL_VIDEO_GET_CHILD_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x120, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION: return "IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x121, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION: return "IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x122, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SWITCH_DUALVIEW: return "IOCTL_VIDEO_SWITCH_DUALVIEW"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x123, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_BANK_POSITION: return "IOCTL_VIDEO_SET_BANK_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x124, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS: return "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS: return "IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS) case IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS: return "IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS) }
return "<unknown ioctl code>";}
staticNTSTATUSVideoPortUseDeviceInSession( _Inout_ PDEVICE_OBJECT DeviceObject, _Inout_ PVIDEO_DEVICE_SESSION_STATUS SessionState, _In_ ULONG BufferLength, _Out_ PULONG_PTR Information){ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
/* Check buffer size */ *Information = sizeof(VIDEO_DEVICE_SESSION_STATUS); if (BufferLength < sizeof(VIDEO_DEVICE_SESSION_STATUS)) { ERR_(VIDEOPRT, "Buffer too small for VIDEO_DEVICE_SESSION_STATUS: %lx\n", BufferLength); return STATUS_BUFFER_TOO_SMALL; }
/* Get the device extension */ DeviceExtension = DeviceObject->DeviceExtension;
/* Shall we enable the session? */ if (SessionState->bEnable) { /* Check if we have no session yet */ if (DeviceExtension->SessionId == -1) { /* Use this session and return success */ DeviceExtension->SessionId = PsGetCurrentProcessSessionId(); SessionState->bSuccess = TRUE; } else { ERR_(VIDEOPRT, "Requested to set session, but session is already set to: 0x%lx\n", DeviceExtension->SessionId); SessionState->bSuccess = FALSE; } } else { /* Check if we belong to the current session */ if (DeviceExtension->SessionId == PsGetCurrentProcessSessionId()) { /* Reset the session and return success */ DeviceExtension->SessionId = -1; SessionState->bSuccess = TRUE; } else { ERR_(VIDEOPRT, "Requested to reset session, but session is not set\n"); SessionState->bSuccess = FALSE; } }
return STATUS_SUCCESS;}
staticNTSTATUSVideoPortEnumMonitorPdo( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PVIDEO_MONITOR_DEVICE *ppMonitorDevices, _Out_ PULONG_PTR Information){ PVIDEO_MONITOR_DEVICE pMonitorDevices; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PVIDEO_PORT_CHILD_EXTENSION ChildExtension; ULONG i; PLIST_ENTRY CurrentEntry;
/* Count the children */ i = 0; CurrentEntry = DeviceExtension->ChildDeviceList.Flink; while (CurrentEntry != &DeviceExtension->ChildDeviceList) { i++; CurrentEntry = CurrentEntry->Flink; }
pMonitorDevices = ExAllocatePoolZero(PagedPool, sizeof(VIDEO_MONITOR_DEVICE) * (i + 1), TAG_VIDEO_PORT); if (!pMonitorDevices) return STATUS_INSUFFICIENT_RESOURCES;
/* Add the children */ i = 0; CurrentEntry = DeviceExtension->ChildDeviceList.Flink; while (CurrentEntry != &DeviceExtension->ChildDeviceList) { ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
ObReferenceObject(ChildExtension->PhysicalDeviceObject); pMonitorDevices[i++].pdo = ChildExtension->PhysicalDeviceObject; CurrentEntry = CurrentEntry->Flink; }
*ppMonitorDevices = pMonitorDevices; *Information = sizeof(pMonitorDevices); return STATUS_SUCCESS;}
staticNTSTATUSVideoPortInitWin32kCallbacks( _In_ PDEVICE_OBJECT DeviceObject, _Inout_ PVIDEO_WIN32K_CALLBACKS Win32kCallbacks, _In_ ULONG BufferLength, _Out_ PULONG_PTR Information){ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
*Information = sizeof(VIDEO_WIN32K_CALLBACKS); if (BufferLength < sizeof(VIDEO_WIN32K_CALLBACKS)) { ERR_(VIDEOPRT, "Buffer too small for VIDEO_WIN32K_CALLBACKS: %lx\n", BufferLength); return STATUS_BUFFER_TOO_SMALL; }
/* Save the callout function globally */ Win32kCallout = Win32kCallbacks->Callout;
/* Return reasonable values to Win32k */ Win32kCallbacks->bACPI = FALSE; Win32kCallbacks->pPhysDeviceObject = DeviceExtension->PhysicalDeviceObject; Win32kCallbacks->DualviewFlags = 0;
return STATUS_SUCCESS;}
staticNTSTATUSVideoPortForwardDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION IrpStack; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; VIDEO_REQUEST_PACKET vrp;
TRACE_(VIDEOPRT, "VideoPortForwardDeviceControl\n");
IrpStack = IoGetCurrentIrpStackLocation(Irp); DeviceExtension = DeviceObject->DeviceExtension; DriverExtension = DeviceExtension->DriverExtension;
/* Translate the IRP to a VRP */ vrp.StatusBlock = (PSTATUS_BLOCK)&Irp->IoStatus; vrp.IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
INFO_(VIDEOPRT, "- IoControlCode: %x\n", vrp.IoControlCode);
/* We're assuming METHOD_BUFFERED */ vrp.InputBuffer = Irp->AssociatedIrp.SystemBuffer; vrp.InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; vrp.OutputBuffer = Irp->AssociatedIrp.SystemBuffer; vrp.OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
/* Call the Miniport Driver with the VRP */ DriverExtension->InitializationData.HwStartIO(&DeviceExtension->MiniPortDeviceExtension, &vrp);
INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
/* Map from win32 error codes to NT status values. */ switch (Irp->IoStatus.Status) { case NO_ERROR: return STATUS_SUCCESS; case ERROR_NOT_ENOUGH_MEMORY: return STATUS_INSUFFICIENT_RESOURCES; case ERROR_MORE_DATA: return STATUS_BUFFER_OVERFLOW; case ERROR_INVALID_FUNCTION: return STATUS_NOT_IMPLEMENTED; case ERROR_INVALID_PARAMETER: return STATUS_INVALID_PARAMETER; case ERROR_INSUFFICIENT_BUFFER: return STATUS_BUFFER_TOO_SMALL; case ERROR_DEV_NOT_EXIST: return STATUS_DEVICE_DOES_NOT_EXIST; case ERROR_IO_PENDING: return STATUS_PENDING; default: return STATUS_UNSUCCESSFUL; }}
/* * IntVideoPortDispatchDeviceControl * * Answer requests for device control calls. * * Run Level * PASSIVE_LEVEL */NTSTATUSNTAPIIntVideoPortDispatchDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION IrpStack; NTSTATUS Status; ULONG IoControlCode;
TRACE_(VIDEOPRT, "IntVideoPortDispatchDeviceControl\n");
IrpStack = IoGetCurrentIrpStackLocation(Irp);
switch (IrpStack->MajorFunction) { case IRP_MJ_DEVICE_CONTROL: /* This is the main part of this function and is handled below */ break;
case IRP_MJ_SHUTDOWN: { /* Dereference CSRSS */ PKPROCESS OldCsrProcess; OldCsrProcess = InterlockedExchangePointer((PVOID*)&CsrProcess, NULL); if (OldCsrProcess) ObDereferenceObject(OldCsrProcess);
Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
default: ERR_(VIDEOPRT, "- Unknown MajorFunction 0x%x\n", IrpStack->MajorFunction); Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_SUCCESS; }
IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
INFO_(VIDEOPRT, "- IoControlCode: 0x%x: %s\n", IoControlCode, IoctlName(IoControlCode));
switch (IoControlCode) { case IOCTL_VIDEO_ENABLE_VDM: case IOCTL_VIDEO_DISABLE_VDM: case IOCTL_VIDEO_REGISTER_VDM: WARN_(VIDEOPRT, "- IOCTL_VIDEO_*_VDM are UNIMPLEMENTED!\n"); Status = STATUS_NOT_IMPLEMENTED; break;
case IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE: case IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE: WARN_(VIDEOPRT, "- IOCTL_VIDEO_GET/SET_OUTPUT_DEVICE_POWER_STATE are UNIMPLEMENTED!\n"); Status = STATUS_NOT_IMPLEMENTED; break;
case IOCTL_VIDEO_SET_POWER_MANAGEMENT: case IOCTL_VIDEO_GET_POWER_MANAGEMENT: WARN_(VIDEOPRT, "- IOCTL_VIDEO_GET/SET_POWER_MANAGEMENT are UNIMPLEMENTED!\n"); Status = STATUS_NOT_IMPLEMENTED; break;
case IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS: case IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS: case IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS: WARN_(VIDEOPRT, "- IOCTL_VIDEO_*_BRIGHTNESS are UNIMPLEMENTED!\n"); Status = STATUS_NOT_IMPLEMENTED; break;
case IOCTL_VIDEO_ENUM_MONITOR_PDO: INFO_(VIDEOPRT, "- IOCTL_VIDEO_ENUM_MONITOR_PDO\n"); Status = VideoPortEnumMonitorPdo(DeviceObject, Irp->AssociatedIrp.SystemBuffer, &Irp->IoStatus.Information); break;
case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS: INFO_(VIDEOPRT, "- IOCTL_VIDEO_INIT_WIN32K_CALLBACKS\n"); Status = VideoPortInitWin32kCallbacks(DeviceObject, Irp->AssociatedIrp.SystemBuffer, IrpStack->Parameters.DeviceIoControl.InputBufferLength, &Irp->IoStatus.Information); break;
case IOCTL_VIDEO_IS_VGA_DEVICE: WARN_(VIDEOPRT, "- IOCTL_VIDEO_IS_VGA_DEVICE is UNIMPLEMENTED!\n"); Status = STATUS_NOT_IMPLEMENTED; break;
case IOCTL_VIDEO_USE_DEVICE_IN_SESSION: INFO_(VIDEOPRT, "- IOCTL_VIDEO_USE_DEVICE_IN_SESSION\n"); Status = VideoPortUseDeviceInSession(DeviceObject, Irp->AssociatedIrp.SystemBuffer, IrpStack->Parameters.DeviceIoControl.InputBufferLength, &Irp->IoStatus.Information); break;
case IOCTL_VIDEO_PREPARE_FOR_EARECOVERY: INFO_(VIDEOPRT, "- IOCTL_VIDEO_PREPARE_FOR_EARECOVERY\n"); /* * The Win32k Watchdog Timer detected that a thread spent more time * in a display driver than the allotted time its threshold specified, * and thus is going to attempt to recover by switching to VGA mode. * If this attempt fails, the watchdog generates bugcheck 0xEA * "THREAD_STUCK_IN_DEVICE_DRIVER". * * Prepare the recovery by resetting the display adapters to * standard VGA 80x25 text mode. */ IntVideoPortResetDisplayParametersEx(80, 25, FALSE); Status = STATUS_SUCCESS; break;
default: /* Forward to the Miniport Driver */ Status = VideoPortForwardDeviceControl(DeviceObject, Irp); break; }
INFO_(VIDEOPRT, "- Returned status: 0x%x\n", Status);
Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_VIDEO_INCREMENT); return Status;}
NTSTATUSNTAPIIntVideoPortPnPStartDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp); PDRIVER_OBJECT DriverObject; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; PCM_RESOURCE_LIST AllocatedResources;
/* Get the initialization data we saved in VideoPortInitialize.*/ DriverObject = DeviceObject->DriverObject; DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject); DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/* Store some resources in the DeviceExtension. */ AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources; if (AllocatedResources != NULL) { CM_FULL_RESOURCE_DESCRIPTOR *FullList; CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor; ULONG ResourceCount; ULONG ResourceListSize;
/* Save the resource list */ ResourceCount = AllocatedResources->List[0].PartialResourceList.Count; ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList. PartialDescriptors[ResourceCount]); DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize); if (DeviceExtension->AllocatedResources == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }
RtlCopyMemory(DeviceExtension->AllocatedResources, AllocatedResources, ResourceListSize);
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */ FullList = AllocatedResources->List; ASSERT(AllocatedResources->Count == 1); INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n", FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */ ASSERT(FullList->InterfaceType == PCIBus); ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber); ASSERT(1 == FullList->PartialResourceList.Version); ASSERT(1 == FullList->PartialResourceList.Revision); for (Descriptor = FullList->PartialResourceList.PartialDescriptors; Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count; Descriptor++) { if (Descriptor->Type == CmResourceTypeInterrupt) { DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level; DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector; if (Descriptor->ShareDisposition == CmResourceShareShared) DeviceExtension->InterruptShared = TRUE; else DeviceExtension->InterruptShared = FALSE; } } }
INFO_(VIDEOPRT, "Interrupt level: 0x%x Interrupt Vector: 0x%x\n", DeviceExtension->InterruptLevel, DeviceExtension->InterruptVector);
/* Create adapter device object. */ return IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);}
NTSTATUSNTAPIIntVideoPortForwardIrpAndWaitCompletionRoutine( PDEVICE_OBJECT Fdo, PIRP Irp, PVOID Context){ PKEVENT Event = Context;
if (Irp->PendingReturned) KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;}
NTSTATUSNTAPIIntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp){ PDEVICE_RELATIONS DeviceRelations; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; PVIDEO_PORT_CHILD_EXTENSION ChildExtension; ULONG i; PLIST_ENTRY CurrentEntry; NTSTATUS Status;
if (InterlockedCompareExchange((PLONG)&DeviceExtension->DeviceOpened, 0, 0) == 0) { /* Device not opened. Don't enumerate children yet */ WARN_(VIDEOPRT, "Skipping child enumeration because device is not opened"); return STATUS_INSUFFICIENT_RESOURCES; } /* Query children of the device. */ Status = IntVideoPortEnumerateChildren(DeviceObject, Irp); if (!NT_SUCCESS(Status)) return Status;
/* Count the children */ i = 0; CurrentEntry = DeviceExtension->ChildDeviceList.Flink; while (CurrentEntry != &DeviceExtension->ChildDeviceList) { i++; CurrentEntry = CurrentEntry->Flink; }
if (i == 0) return Irp->IoStatus.Status;
DeviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID))); if (!DeviceRelations) return STATUS_NO_MEMORY;
DeviceRelations->Count = i;
/* Add the children */ i = 0; CurrentEntry = DeviceExtension->ChildDeviceList.Flink; while (CurrentEntry != &DeviceExtension->ChildDeviceList) { ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
ObReferenceObject(ChildExtension->PhysicalDeviceObject); DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
i++; CurrentEntry = CurrentEntry->Flink; }
INFO_(VIDEOPRT, "Reported %d PDOs\n", i); Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;}
NTSTATUSNTAPIIntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp){ KEVENT Event; NTSTATUS Status; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
KeInitializeEvent(&Event, NotificationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine, &Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; }
return Status;}
NTSTATUSNTAPIIntVideoPortDispatchFdoPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION IrpSp; NTSTATUS Status; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction) { case IRP_MN_START_DEVICE: Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp); if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) Status = IntVideoPortPnPStartDevice(DeviceObject, Irp); Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* Call lower drivers, and ignore result (that's probably STATUS_NOT_SUPPORTED) */ (VOID)IntVideoPortForwardIrpAndWait(DeviceObject, Irp); /* Now, fill resource requirements list */ Status = IntVideoPortFilterResourceRequirements(DeviceObject, IrpSp, Irp); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;
case IRP_MN_QUERY_DEVICE_RELATIONS: { DEVICE_RELATION_TYPE RelationType = IrpSp->Parameters.QueryDeviceRelations.Type;
switch (RelationType) { case TargetDeviceRelation: { PDEVICE_RELATIONS TargetList;
TargetList = ExAllocatePoolZero(PagedPool, sizeof(*TargetList), TAG_VIDEO_PORT); if (TargetList == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; Irp->IoStatus.Information = 0; } else { TargetList->Count++; TargetList->Objects[0] = DeviceObject; ObReferenceObject(DeviceObject); Irp->IoStatus.Information = (ULONG_PTR)TargetList; Status = STATUS_SUCCESS; }
Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); break; }
case BusRelations: Status = IntVideoPortQueryBusRelations(DeviceObject, Irp); Irp->IoStatus.Status = Status; if (!NT_SUCCESS(Status)) { IoCompleteRequest(Irp, IO_NO_INCREMENT); } else if (DeviceExtension->NextDeviceObject != NULL) { IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); } break;
default: if (DeviceExtension->NextDeviceObject != NULL) { IoSkipCurrentIrpStackLocation(Irp); Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp); } else { Status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } break; } break; }
case IRP_MN_REMOVE_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_CANCEL_REMOVE_DEVICE: case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_STOP_DEVICE: Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp); if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status)) Status = STATUS_SUCCESS; Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;
case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_CANCEL_STOP_DEVICE: Status = STATUS_SUCCESS; Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); break;
default: Status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); break; }
return Status;}
NTSTATUSNTAPIIntVideoPortDispatchPnp( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
if (CommonExtension->Fdo) return IntVideoPortDispatchFdoPnp(DeviceObject, Irp); else return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);}
NTSTATUSNTAPIIntVideoPortDispatchCleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = DeviceObject->DeviceExtension; RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;}
NTSTATUSNTAPIIntVideoPortDispatchPower( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ PIO_STACK_LOCATION IrpSp; NTSTATUS Status = Irp->IoStatus.Status; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (DeviceExtension->Common.Fdo) { PoStartNextPowerIrp(Irp); IoSkipCurrentIrpStackLocation(Irp); return PoCallDriver(DeviceExtension->NextDeviceObject, Irp); } else { switch (IrpSp->MinorFunction) { case IRP_MN_QUERY_POWER: case IRP_MN_SET_POWER: Status = STATUS_SUCCESS; break; } PoStartNextPowerIrp(Irp); Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }}
NTSTATUSNTAPIIntVideoPortDispatchSystemControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){ NTSTATUS Status; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
if (DeviceExtension->Common.Fdo) { IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(DeviceExtension->NextDeviceObject, Irp); } else { Status = Irp->IoStatus.Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); return Status; }}
VOIDNTAPIIntVideoPortUnload(PDRIVER_OBJECT DriverObject){}