GENERICAPI NTSTATUS  InitializeGenericExtension(PGENERIC_EXTENSION pdx, PGENERIC_INIT_STRUCT isp)
    {                            // InitializeGenericExtension
    if(isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags)
        || !isp->DeviceObject
        || !isp->Ldo
        || !isp->Pdo
        || !isp->StartDevice
        || !isp->StopDevice
        || !isp->RemoveDevice
        || isp->DeviceQueue && !isp->StartIo)

        return STATUS_INVALID_PARAMETER;

    RtlZeroMemory(pdx, sizeof(GENERIC_EXTENSION));

    pdx->DeviceObject = isp->DeviceObject;
    pdx->LowerDeviceObject = isp->Ldo;
    pdx->Pdo = isp->Pdo;
    pdx->StartDevice = isp->StartDevice;
    pdx->StopDevice = isp->StopDevice;
    pdx->RemoveDevice = isp->RemoveDevice;

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, OkayToRemove) + sizeof(PQUERYFUNCTION))
        {                        // set OkayToStop & OkayToRemove pointers
        pdx->OkayToStop = isp->OkayToStop;
        pdx->OkayToRemove = isp->OkayToRemove;
        }                        // set OkayToStop & OkayToRemove pointers

    if((pdx->RemoveLock = isp->RemoveLock))
        IoInitializeRemoveLock(pdx->RemoveLock, 0, 0, 0);

    pdx->state = STOPPED;
    
    pdx->devpower = PowerDeviceD0;
    pdx->syspower = PowerSystemWorking;
    POWER_STATE state;
    state.DeviceState = PowerDeviceD0;
    PoSetPowerState(pdx->DeviceObject, DevicePowerState, state);

    // In version 1.3, I added support for multiple IRP queues

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, NumberOfQueues) + sizeof(ULONG)
        && isp->NumberOfQueues)
        {                        // multiple queues
        ULONG i;
        if(isp->DeviceQueue || isp->StartIo)
            return STATUS_INVALID_PARAMETER;    // can't mix new and old ways of identifying queues
        if(isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Queues) + isp->NumberOfQueues * 2 * sizeof(PVOID))
            return STATUS_INVALID_PARAMETER;    // init structure not big enough
        for (i = 0; i < isp->NumberOfQueues; ++i)
            if(!isp->Queues[i].DeviceQueue || !isp->Queues[i].StartIo)
                return STATUS_INVALID_PARAMETER;    // none of the entries can be NULL

        pdx->nqueues = isp->NumberOfQueues;
        pdx->queues = (PDEVQUEUE*) ExAllocatePoolWithTag(NonPagedPool, isp->NumberOfQueues * sizeof(PDEVQUEUE), SPOT_TAG);
        if(!pdx->queues)
            return STATUS_INSUFFICIENT_RESOURCES;

        for (i = 0; i < isp->NumberOfQueues; ++i)
            {                    // for each queue
            pdx->queues[i] = isp->Queues[i].DeviceQueue;
            InitializeQueue(pdx->queues[i], isp->Queues[i].StartIo);
            }                    // for each queue
        }                        // multiple queues

    else if(isp->DeviceQueue)
        {                        // single queue
        pdx->nqueues = 1;
        pdx->queues = (PDEVQUEUE*) ExAllocatePoolWithTag(NonPagedPool, sizeof(PDEVQUEUE), SPOT_TAG);
        if(!pdx->queues)
            return STATUS_INSUFFICIENT_RESOURCES;
        pdx->queues[0] = isp->DeviceQueue;
        InitializeQueue(pdx->queues[0], isp->StartIo);
        }                        // single queue

    // In version 1.9, I added support for FlushPendingIo.
    // In version 1.10, GetDevicePowerState

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Queues))
        {                        // additional reserved fields
        pdx->FlushPendingIo = isp->FlushPendingIo;
        pdx->GetDevicePowerState = isp->GetDevicePowerState;
        }                        // additional reserved fields

    // Capture the mini-driver name for messages. This needs to be in ANSI because
    // unicode conversions at or above DISPATCH_LEVEL are not allowed. In retrospect, I
    // should have made the field in the INIT struct be in ANSI to start with...

    if(!isp->DebugName.Length)
        strcpy(pdx->DebugName, "GENERIC");
    else
        {                        // convert debug name
        ANSI_STRING asname = {0, sizeof(pdx->DebugName) - 1, pdx->DebugName};
        RtlUnicodeStringToAnsiString(&asname, &isp->DebugName, FALSE);
        pdx->DebugName[asname.Length] = 0;
        }                        // convert debug name

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags) + sizeof(ULONG))
        pdx->Flags = isp->Flags & GENERIC_CLIENT_FLAGS;

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, RestoreDeviceContext) + sizeof(PCONTEXTFUNCTION))
        {                        // get power helper functions
        pdx->QueryPower = isp->QueryPower;
        pdx->SaveDeviceContext = isp->SaveDeviceContext;
        pdx->RestoreDeviceContext = isp->RestoreDeviceContext;
        }                        // get power helper functions

    if(isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, PerfBoundary) + sizeof(DEVICE_POWER_STATE))
        pdx->PerfBoundary = isp->PerfBoundary;
    else
        pdx->PerfBoundary = PowerDeviceUnspecified;

    if(pdx->PerfBoundary == PowerDeviceUnspecified)
        pdx->PerfBoundary = PowerDeviceMaximum; // inhibit POWER_SEQUENCE optimization

    // Initialize variables related to asynchrounous IOCTL management. In version 2.0, this
    // is now always done rather than depending on a flag in the init struct.

    InitializeListHead(&pdx->PendingIoctlList);
    pdx->IoctlAbortStatus = 0;
    KeInitializeSpinLock(&pdx->IoctlListLock);

    // Initialize to manage registered device interfaces

    KeInitializeEvent(&pdx->iflock, SynchronizationEvent, TRUE);
    InitializeListHead(&pdx->iflist);

    // Indicate we handle power IRPs at PASSIVE_LEVEL

    pdx->DeviceObject->Flags |= DO_POWER_PAGABLE;

    KdPrint(("GENERIC - Initializing for %s\n", pdx->DebugName));

    // If device honors paging-path notifications, initialize a synchronization
    // event in the signalled state to act as a simple mutex (SP-7)

    if(pdx->Flags & GENERIC_USAGE_PAGING)
        KeInitializeEvent(&pdx->evPagingPath, SynchronizationEvent, TRUE);

    // If requested to do so, register an AutoLaunch interface

    if(pdx->Flags & GENERIC_AUTOLAUNCH)
        GenericRegisterInterface(pdx, &GUID_AUTOLAUNCH_NOTIFY);

    // Register a power management interface

    GenericRegisterInterface(pdx, &GUID_GENERIC_POWER);

#ifdef _X86_
    win98 = IsWin98();
#endif

    return STATUS_SUCCESS;
    }                            // InitializeGenericExtension
Beispiel #2
0
GENERICAPI NTSTATUS GENERIC_EXPORT InitializeGenericExtension(PGENERIC_EXTENSION pdx, PGENERIC_INIT_STRUCT isp)
	{							// InitializeGenericExtension
	if (isp->Size < FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags)
		|| !isp->DeviceObject
		|| !isp->Ldo
		|| !isp->Pdo
		|| !isp->StartDevice
		|| !isp->StopDevice
		|| !isp->RemoveDevice
		|| isp->DeviceQueue && !isp->StartIo)

		return STATUS_INVALID_PARAMETER;

	RtlZeroMemory(pdx, sizeof(GENERIC_EXTENSION));

	pdx->DeviceObject = isp->DeviceObject;
	pdx->LowerDeviceObject = isp->Ldo;
	pdx->Pdo = isp->Pdo;
	pdx->StartDevice = isp->StartDevice;
	pdx->StopDevice = isp->StopDevice;
	pdx->RemoveDevice = isp->RemoveDevice;

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, OkayToRemove) + sizeof(PQUERYFUNCTION))
		{						// set OkayToStop & OkayToRemove pointers
		pdx->OkayToStop = isp->OkayToStop;
		pdx->OkayToRemove = isp->OkayToRemove;
		}						// set OkayToStop & OkayToRemove pointers

	if ((pdx->dqReadWrite = isp->DeviceQueue))
		{						// queue reads & writes
		if (!isp->StartIo)
			return STATUS_INVALID_PARAMETER;
		InitializeQueue(pdx->dqReadWrite, isp->StartIo);
		}						// queue reads & writes

	if ((pdx->RemoveLock = isp->RemoveLock))
		IoInitializeRemoveLock(pdx->RemoveLock, 0, 0, 0);

	pdx->state = STOPPED;
	
	pdx->devpower = PowerDeviceD0;
	pdx->syspower = PowerSystemWorking;
	POWER_STATE state;
	state.DeviceState = PowerDeviceD0;
	PoSetPowerState(pdx->DeviceObject, DevicePowerState, state);

	// Capture the mini-driver name for messages. This needs to be in ANSI because
	// unicode conversions at or above DISPATCH_LEVEL are not allowed

	if (!isp->DebugName.Length)
		strcpy(pdx->DebugName, "GENERIC");
	else
		{						// convert debug name
		ANSI_STRING asname = {0, sizeof(pdx->DebugName) - 1, pdx->DebugName};
		RtlUnicodeStringToAnsiString(&asname, &isp->DebugName, FALSE);
		pdx->DebugName[asname.Length] = 0;
		}						// convert debug name

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, Flags) + sizeof(ULONG))
		pdx->Flags = isp->Flags & GENERIC_CLIENT_FLAGS;

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, RestoreDeviceContext) + sizeof(PCONTEXTFUNCTION))
		{						// get power helper functions
		pdx->QueryPower = isp->QueryPower;
		pdx->SaveDeviceContext = isp->SaveDeviceContext;
		pdx->RestoreDeviceContext = isp->RestoreDeviceContext;
		}						// get power helper functions

	if (isp->Size >= FIELD_OFFSET(GENERIC_INIT_STRUCT, PerfBoundary) + sizeof(DEVICE_POWER_STATE))
		pdx->PerfBoundary = isp->PerfBoundary;
	else
		pdx->PerfBoundary = PowerDeviceUnspecified;

	if (pdx->PerfBoundary == PowerDeviceUnspecified)
		pdx->PerfBoundary = PowerDeviceMaximum; // inhibit POWER_SEQUENCE optimization

	// Initialize variables related to asynchrounous IOCTL management.

	if (pdx->Flags & GENERIC_PENDING_IOCTLS)
		{						// driver may cache asyncronous IOCTLs
		InitializeListHead(&pdx->PendingIoctlList);
		pdx->IoctlAbortStatus = 0;

		// We need to initialize our IOCTL spin lock sometime, but just once.
		// Acquiring the cancel spin lock to guard this operation is a bit of
		// a hack, I suppose, but note that a class driver like this one never
		// gets an actual chance to initialize, so it's not my fault...

		KIRQL oldirql;
		IoAcquireCancelSpinLock(&oldirql);	// any global spin lock would do
		if (!IoctlListLockInitialized)
			{					// initialize global lock
			IoctlListLockInitialized = TRUE;
			KeInitializeSpinLock(&IoctlListLock);
			}					// initialize global lock
		IoReleaseCancelSpinLock(oldirql);
		}						// driver may cache asynchronous IOCTLs

	// Initialize to manage registered device interfaces

	ExInitializeFastMutex(&pdx->iflock);
	InitializeListHead(&pdx->iflist);

	// Indicate we handle power IRPs at PASSIVE_LEVEL

	pdx->DeviceObject->Flags |= DO_POWER_PAGABLE;

	KdPrint(("GENERIC - Initializing for %s\n", pdx->DebugName));

	// If requested to do so, register an AutoLaunch interface

	if (pdx->Flags & GENERIC_AUTOLAUNCH)
		GenericRegisterInterface(pdx, &GUID_AUTOLAUNCH_NOTIFY);

	// Register a power management interface

	GenericRegisterInterface(pdx, &GUID_GENERIC_POWER);

#ifdef _X86_
	win98 = IsWin98();
#endif

	return STATUS_SUCCESS;
	}							// InitializeGenericExtension