extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
                                IN PUNICODE_STRING RegistryPath)
{
    KdPrint((DRIVERNAME " - Entering DriverEntry: DriverObject %8.8lX\n", DriverObject));

    // Insist that OS support at least the WDM level of the DDK we use

    if(!IoIsWdmVersionAvailable(1, 0))
    {
        KdPrint((DRIVERNAME " - Expected version of WDM (%d.%2.2d) not available\n", 1, 0));
        return STATUS_UNSUCCESSFUL;
    }

    // See if we're running under Win98 or NT:

    win98 = IsWin98();

    if(win98)
        KdPrint((DRIVERNAME " - Running under Windows 98\n"));
    else
        KdPrint((DRIVERNAME " - Running under NT\n"));

    // Initialize function pointers
    DriverObject->DriverUnload = DriverUnload;
    DriverObject->DriverExtension->AddDevice = AddDevice;

    DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    DriverObject->MajorFunction[IRP_MJ_READ] = DispatchReadWriteFlush;
    DriverObject->MajorFunction[IRP_MJ_WRITE] = DispatchReadWriteFlush;
    DriverObject->MajorFunction[IRP_MJ_FLUSH_BUFFERS] = DispatchReadWriteFlush;
    DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DispatchCleanup;
    DriverObject->MajorFunction[IRP_MJ_POWER] = DispatchPower;
    DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = DispatchInternalControl;
    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = DispatchWmi;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceIoControl;

    return STATUS_SUCCESS;
}
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
Example #3
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
Example #4
0
//------------------------------------------------------------------------
// GetDeviceStrings()
//
// dwDeviceNum:	Position of device entry in the Windows registry list.
// dev:			container class where device description strings will be stored.
//
// Copies device description from the registry for single device.
//------------------------------------------------------------------------
void CUsbIF::GetDeviceStrings(DWORD dwDeviceNum, CDeviceListEntry& dev)
{
	// Clear the device info
	dev.m_friendlyname	= "";
	dev.m_linkname		= "";
	dev.m_serialnumber	= "";

	// Retrieve device list for GUID that has been specified.
	HDEVINFO hDevInfoList = SetupDiGetClassDevs (&m_GUID, NULL, NULL, (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)); 

	if (hDevInfoList != NULL)
	{
		SP_DEVICE_INTERFACE_DATA deviceInfoData;

		// Clear data structure
		ZeroMemory(&deviceInfoData, sizeof(deviceInfoData));
		deviceInfoData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

		// retrieves a context structure for a device interface of a device information set.
		if (SetupDiEnumDeviceInterfaces (hDevInfoList, 0, &m_GUID, dwDeviceNum, &deviceInfoData)) 
		{
			// Must get the detailed information in two steps
			// First get the length of the detailed information and allocate the buffer
			// retrieves detailed information about a specified device interface.
			PSP_DEVICE_INTERFACE_DETAIL_DATA     functionClassDeviceData = NULL;
			ULONG  predictedLength, requiredLength;

			predictedLength = requiredLength = 0;
			SetupDiGetDeviceInterfaceDetail (	hDevInfoList,
												&deviceInfoData,
												NULL,			// Not yet allocated
												0,				// Set output buffer length to zero 
												&requiredLength,// Find out memory requirement
												NULL);			

			predictedLength = requiredLength;
			functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc (predictedLength);
			functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
			
			SP_DEVINFO_DATA did = {sizeof(SP_DEVINFO_DATA)};
	
			// Second, get the detailed information
			if ( SetupDiGetDeviceInterfaceDetail (	hDevInfoList,
													&deviceInfoData,
													functionClassDeviceData,
													predictedLength,
													&requiredLength,
													&did)) 
			{
				TCHAR fname[256];

				// Try by friendly name first.
				if (!SetupDiGetDeviceRegistryProperty(hDevInfoList, &did, SPDRP_FRIENDLYNAME, NULL, (PBYTE) fname, sizeof(fname), NULL))
				{	// Try by device description if friendly name fails.
					if (!SetupDiGetDeviceRegistryProperty(hDevInfoList, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) fname, sizeof(fname), NULL))
					{	// Use the raw path information for linkname and friendlyname
						strncpy(fname, functionClassDeviceData->DevicePath, 256);
					}
				}
					dev.m_friendlyname	= fname;
					dev.m_linkname		= functionClassDeviceData->DevicePath;
					// Now get the Serial Number this is OS dependent as the registry
				// has to be manually parsed under Win98
				if(!IsWin98())
				{
					GetSerialNumber(functionClassDeviceData->DevicePath, &(dev.m_serialnumber));
				}
				else
				{
					HKEY tempkey = NULL;
					LONG lRet;
					char szDeviceInstance[256];
					DWORD dwBufLen=256;

					//KeyPath is the known location of our device using SIBULK GUID {37538c66-9584-42d3-9632-ebad0a230d13} under Win98SE
					std::string KeyPath = "System\\CurrentControlSet\\Control\\DeviceClasses\\{37538c66-9584-42d3-9632-ebad0a230d13}\\";
					//SymLinkName is the dynamically allocated path of this particular instance of the Xpress USB device
					std::string SymLinkName = functionClassDeviceData->DevicePath;
					//You cannot use '/' symbols in a registry path name so replace them with "#
					SymLinkName = SymLinkName.replace(0,4,"##.#");
					//Add the dynamic SymLinkName to the known KeyPath string and you have the key path to this device instance
					KeyPath += SymLinkName;
					//Get the Key
					lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, KeyPath.c_str() , NULL, KEY_READ, &tempkey);
					if( lRet != ERROR_SUCCESS )
						tempkey = NULL;	//error retrieving key
					
					// Get the Device Instance string using the key
					lRet = RegQueryValueEx( tempkey, "DeviceInstance", NULL, NULL,
					(LPBYTE) szDeviceInstance, &dwBufLen);
					if( (lRet != ERROR_SUCCESS) || (dwBufLen > 80) )
						tempkey = NULL;	//error retrieving instance string
					std::string SerialNumber = szDeviceInstance;
					SerialNumber.erase(0,22);
					dev.m_serialnumber = SerialNumber;
					
				}
					
				free( functionClassDeviceData );
			}
		}
	}

	// SetupDiDestroyDeviceInfoList() destroys a device information set
	// and frees all associated memory.
	SetupDiDestroyDeviceInfoList (hDevInfoList);
}