Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

364 lines
9.4 KiB

//**************************************************************************
//
// HOTPLUG.C -- Xena Gaming Project
//
// Version 3.XX
//
// Copyright (c) 1997 Microsoft Corporation. All rights reserved.
//
// @doc
// @module HOTPLUG.C | Routines to support GameEnum hot-plugging
//**************************************************************************
#include "msgame.h"
//---------------------------------------------------------------------------
// Private Procedures
//---------------------------------------------------------------------------
static VOID MSGAME_CreateDeviceItem (PGAME_WORK_ITEM WorkItem);
static VOID MSGAME_RemoveDeviceItem (PGAME_WORK_ITEM WorkItem);
//---------------------------------------------------------------------------
// @func Calls GameEnum to add a new device to the chain
// @parm PGAME_WORK_ITEM | WorkItem | Pointer to add work item
// @rdesc None
// @comm Private function
//---------------------------------------------------------------------------
VOID MSGAME_CreateDeviceItem (PGAME_WORK_ITEM WorkItem)
{
PIRP pIrp;
KEVENT Event;
NTSTATUS ntStatus;
PDEVICEINFO DevInfo;
PDEVICE_EXTENSION DevExt;
IO_STATUS_BLOCK IoStatus;
GAMEENUM_EXPOSE_SIBLING ExposeSibling;
MsGamePrint ((DBG_INFORM, "%s: %s_ExposeSiblingItem Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the device extension.
//
DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (WorkItem->DeviceObject);
//
// Initialize expose sibling structure
//
memset (&ExposeSibling, 0, sizeof (ExposeSibling));
ExposeSibling.Size = sizeof (GAMEENUM_EXPOSE_SIBLING);
//
// Are we changing device or adding a sibling?
//
DevInfo = GET_DEVICE_DETECTED(&WorkItem->PortInfo);
if (!DevInfo)
DevInfo = GET_DEVICE_INFO(&WorkItem->PortInfo);
else ExposeSibling.HardwareIDs = DevInfo->HardwareId;
//
// Initialize the completion event
//
KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
//
// Allocate Internal I/O IRP
//
pIrp = IoBuildDeviceIoControlRequest (
IOCTL_GAMEENUM_EXPOSE_SIBLING,
DevExt->TopOfStack,
&ExposeSibling,
sizeof (GAMEENUM_EXPOSE_SIBLING),
&ExposeSibling,
sizeof (GAMEENUM_EXPOSE_SIBLING),
TRUE,
&Event,
&IoStatus);
//
// Call GameEnum synchronously
//
MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Expose Device at IRQL=%lu\n", MSGAME_NAME, KeGetCurrentIrql()));
ntStatus = IoCallDriver (DevExt->TopOfStack, pIrp);
if (ntStatus == STATUS_PENDING)
ntStatus = KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
if (!NT_SUCCESS (ntStatus))
MsGamePrint ((DBG_SEVERE, "%s: GameEnum Failed to Expose Device, Status = %X\n", MSGAME_NAME, ntStatus));
//
// Free work item memory
//
ExFreePool (WorkItem);
//
// Decrement IRP count holding driver in memory
//
if (!InterlockedDecrement (&DevExt->IrpCount))
KeSetEvent (&DevExt->RemoveEvent, 0, FALSE);
}
//---------------------------------------------------------------------------
// @func Calls GameEnum to remove a device from the chain
// @parm PGAME_WORK_ITEM | WorkItem | Pointer to add work item
// @rdesc None
// @comm Public function
//---------------------------------------------------------------------------
VOID MSGAME_RemoveDeviceItem (PGAME_WORK_ITEM WorkItem)
{
PIRP pIrp;
KEVENT Event;
NTSTATUS ntStatus;
PDEVICE_EXTENSION DevExt;
IO_STATUS_BLOCK IoStatus;
MsGamePrint ((DBG_INFORM, "%s: %s_RemoveDeviceItem Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get a pointer to the device extension.
//
DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (WorkItem->DeviceObject);
//
// Initialize the completion event
//
KeInitializeEvent (&Event, SynchronizationEvent, FALSE);
//
// Allocate Internal I/O IRP
//
pIrp = IoBuildDeviceIoControlRequest (
IOCTL_GAMEENUM_REMOVE_SELF,
DevExt->TopOfStack,
NULL,
0,
NULL,
0,
TRUE,
&Event,
&IoStatus);
//
// Call GameEnum synchronously
//
MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Remove Self at IRQL=%lu\n", MSGAME_NAME, KeGetCurrentIrql()));
ntStatus = IoCallDriver (DevExt->TopOfStack, pIrp);
if (ntStatus == STATUS_PENDING)
ntStatus = KeWaitForSingleObject (&Event, Suspended, KernelMode, FALSE, NULL);
if (!NT_SUCCESS (ntStatus))
MsGamePrint ((DBG_SEVERE, "%s: GameEnum Failed to Remove Self, Status = %X\n", MSGAME_NAME, ntStatus));
//
// Free work item memory
//
ExFreePool (WorkItem);
//
// Decrement IRP count holding driver in memory
//
if (!InterlockedDecrement (&DevExt->IrpCount))
KeSetEvent (&DevExt->RemoveEvent, 0, FALSE);
}
//---------------------------------------------------------------------------
// @func Calls GameEnum to add a new device to the chain
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_CreateDevice (PDEVICE_OBJECT DeviceObject)
{
PGAME_WORK_ITEM WorkItem;
PDEVICE_EXTENSION DevExt;
MsGamePrint ((DBG_INFORM, "%s: %s_ExposeSibling Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get pointer to device extension.
//
DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Allocate work item memory
//
WorkItem = ExAllocatePool (NonPagedPool, sizeof (GAME_WORK_ITEM));
if (!WorkItem)
{
MsGamePrint ((DBG_SEVERE, "%s: %s_ExposeSibling Failed to Allocate Work Item\n", MSGAME_NAME, MSGAME_NAME));
return (STATUS_INSUFFICIENT_RESOURCES);
}
//
// Increment IRP count to hold driver in memory
//
InterlockedIncrement (&DevExt->IrpCount);
//
// Initialize work item memory
//
ExInitializeWorkItem (&WorkItem->QueueItem, (PWORKER_THREAD_ROUTINE)MSGAME_CreateDeviceItem, WorkItem);
WorkItem->DeviceObject = DeviceObject;
WorkItem->PortInfo = DevExt->PortInfo;
//
// Queue the work item
//
MsGamePrint ((DBG_CONTROL, "%s: %s_ExposeSibling Queueing %s_ExposeSiblingItem\n", MSGAME_NAME, MSGAME_NAME, MSGAME_NAME));
ExQueueWorkItem (&WorkItem->QueueItem, DelayedWorkQueue);
//
// Return status
//
return (STATUS_SUCCESS);
}
//---------------------------------------------------------------------------
// @func Calls GameEnum to remove a device from the chain
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @parm PIRP | pIrp | Pointer to IO request packet
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_RemoveDevice (PDEVICE_OBJECT DeviceObject)
{
PDEVICEINFO DevInfo;
PGAME_WORK_ITEM WorkItem;
PDEVICE_EXTENSION DevExt;
MsGamePrint ((DBG_INFORM, "%s: %s_RemoveDevice Enter\n", MSGAME_NAME, MSGAME_NAME));
//
// Get pointer to device extension.
//
DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Get device information
//
DevInfo = GET_DEVICE_INFO(&DevExt->PortInfo);
//
// Skip if device already removed
//
if (DevExt->Removing || DevExt->Surprised || DevExt->Removed)
{
MsGamePrint ((DBG_SEVERE, "%s: %s_RemoveDevice attempted to destroy removed device\n", MSGAME_NAME, MSGAME_NAME));
InterlockedIncrement (&DevInfo->DevicePending);
return (STATUS_DELETE_PENDING);
}
//
// Allocate work item memory
//
WorkItem = ExAllocatePool (NonPagedPool, sizeof (GAME_WORK_ITEM));
if (!WorkItem)
{
MsGamePrint ((DBG_SEVERE, "%s: %s_RemoveDevice Failed to Allocate Work Item\n", MSGAME_NAME, MSGAME_NAME));
return (STATUS_INSUFFICIENT_RESOURCES);
}
//
// Increment IRP count to hold driver in memory
//
InterlockedIncrement (&DevExt->IrpCount);
//
// Mark device as being removed
//
DevExt->Removing = TRUE;
//
// Initialize work item memory
//
ExInitializeWorkItem (&WorkItem->QueueItem, (PWORKER_THREAD_ROUTINE)MSGAME_RemoveDeviceItem, WorkItem);
WorkItem->DeviceObject = DevExt->Self;
WorkItem->PortInfo = DevExt->PortInfo;
//
// Queue the work item
//
MsGamePrint ((DBG_CONTROL, "%s: %s_RemoveDevice Queueing %s_RemoveDeviceItem\n", MSGAME_NAME, MSGAME_NAME, MSGAME_NAME));
ExQueueWorkItem (&WorkItem->QueueItem, DelayedWorkQueue);
//
// Return status
//
return (STATUS_DEVICE_NOT_READY);
}
//---------------------------------------------------------------------------
// @func Calls GameEnum to add a new device to the chain
// @parm PDEVICE_OBJECT | DeviceObject | Pointer to device object
// @rdesc Returns NT status code
// @comm Public function
//---------------------------------------------------------------------------
NTSTATUS MSGAME_ChangeDevice (PDEVICE_OBJECT DeviceObject)
{
PDEVICE_EXTENSION DevExt;
MsGamePrint ((DBG_CONTROL, "%s: Calling GameEnum to Change Device\n", MSGAME_NAME));
//
// Get pointer to device extension.
//
DevExt = GET_MINIDRIVER_DEVICE_EXTENSION (DeviceObject);
//
// Increment IRP count to hold driver in memory
//
// InterlockedIncrement (&DevExt->IrpCount);
//
// Remove old device first
//
MSGAME_RemoveDevice (DeviceObject);
//
// Create new device second
//
MSGAME_CreateDevice (DeviceObject);
//
// Return status
//
return (STATUS_DEVICE_NOT_READY);
}