📄 pnputils.c
字号:
/*++dvdf
Routine Description:
This routine releases the specified parallel port back to the the parallel
port arbiter ParPort via an IOCTL_INTERNAL_PARALLEL_PORT_FREE.
Arguments:
PortDeviceObject - points to the ParPort device to be released
Return Value:
STATUS_SUCCESS - if the port was successfully released
!STATUS_SUCCESS - otherwise
--*/
{
return ParBuildSendInternalIoctl(IOCTL_INTERNAL_PARALLEL_PORT_FREE,
PortDeviceObject, NULL, 0, NULL, 0, NULL);
}
VOID
PptWriteMfgMdlToDevNode(
IN PDEVICE_OBJECT Pdo,
IN PCHAR Mfg,
IN PCHAR Mdl
)
{
PPDO_EXTENSION pdx = Pdo->DeviceExtension;
if( Mfg && Mdl ) {
NTSTATUS status;
HANDLE handle;
LONG mfgLen = strlen( Mfg );
LONG mdlLen = strlen( Mdl );
LONG maxLen = mfgLen > mdlLen ? mfgLen : mdlLen;
LONG bufLen = ( maxLen + sizeof(CHAR) ) * sizeof(WCHAR);
PWSTR buffer = ExAllocatePool( PagedPool | POOL_COLD_ALLOCATION, bufLen );
if( buffer ) {
status = IoOpenDeviceRegistryKey( Pdo, PLUGPLAY_REGKEY_DEVICE, KEY_ALL_ACCESS, &handle );
if( STATUS_SUCCESS == status ) {
UNICODE_STRING uniValueName;
LONG wcharCount;
//
// Write MFG to DevNode
//
RtlInitUnicodeString( &uniValueName, L"IEEE_1284_Manufacturer" );
wcharCount = _snwprintf( buffer, bufLen/sizeof(WCHAR), L"%S", Mfg );
if( (wcharCount > 0) && (wcharCount < (LONG)(bufLen/sizeof(WCHAR))) ){
// no buffer overflow - continue
status = ZwSetValueKey( handle, &uniValueName, 0, REG_SZ, buffer, (wcharCount+1)*sizeof(WCHAR) );
PptAssert( STATUS_SUCCESS == status );
} else {
// buffer overflow - skip writing this value to devnode
PptAssert(!"PptWriteMfgMdlToDevNode - buffer overflow on Mfg");
DD((PCE)pdx,DDW,"PptWriteMfgMdlToDevNode - buffer overflow on Mfg\n");
}
//
// Write MDL to DevNode
//
RtlInitUnicodeString( &uniValueName, L"IEEE_1284_Model" );
wcharCount = _snwprintf( buffer, bufLen/sizeof(WCHAR), L"%S", Mdl );
if( (wcharCount > 0) && (wcharCount < (LONG)(bufLen/sizeof(WCHAR))) ){
// no buffer overflow - continue
status = ZwSetValueKey( handle, &uniValueName, 0, REG_SZ, buffer, (wcharCount+1)*sizeof(WCHAR) );
PptAssert( STATUS_SUCCESS == status );
} else {
// buffer overflow - skip writing this value to devnode
PptAssert(!"PptWriteMfgMdlToDevNode - buffer overflow on Mdl");
DD((PCE)pdx,DDW,"PptWriteMfgMdlToDevNode - buffer overflow on Mdl\n");
}
ZwClose( handle );
} else {
DD((PCE)pdx,DDW,"PptWriteMfgMdlToDevNode - IoOpenDeviceRegistryKey FAILED - status = %x\n",status);
}
ExFreePool( buffer );
} // end if( buffer )
} else {
PptAssert(!"PptWriteMfgMdlToDevNode - Mfg or Mdl is NULL - calling function should catch this!");
DD((PCE)pdx,DDW,"PptWriteMfgMdlToDevNode - Mfg or Mdl is NULL - calling function should catch this!");
}
}
NTSTATUS
PptFdoHandleBusRelations(
IN PDEVICE_OBJECT Fdo,
IN PIRP Irp
)
{
PFDO_EXTENSION fdx = Fdo->DeviceExtension;
ULONG deviceCount = 0;
ULONG daisyChainDevCount;
PDEVICE_RELATIONS devRel;
ULONG devRelSize;
NTSTATUS status;
LARGE_INTEGER acquirePortTimeout;
BOOLEAN acquiredPort;
PUCHAR controller = fdx->PortInfo.Controller;
BOOLEAN changeDetected;
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - enter\n");
//
// acquire exclusive access to bus
//
// timeout is in 100 ns units
acquirePortTimeout.QuadPart = -(10 * 1000 * 1000 * 2); // 2 seconds
// RMT - is it valid to send this IOCTL to FDO from here?
status = PptAcquirePortViaIoctl( Fdo, &acquirePortTimeout );
if( STATUS_SUCCESS == status ) {
// we have the port
acquiredPort = TRUE;
} else {
// failed to aquire port
acquiredPort = FALSE;
// skip rescanning port - just report same thing we reported during previous scan
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - failed to acquire port for rescan\n");
goto target_failed_to_acquire_port;
}
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - Port Acquired\n");
//
// Rescan the bus, note changes, create new PDOs or mark existing
// PDOs for removal as required
//
//
// Handle Raw Port Legacy Interface LPTx device
//
if( !fdx->RawPortPdo ) {
// first time through this - create our LPTx legacy interface PDO
DD((PCE)fdx,DDT,"PptFdoHandleBusRelations - attempting to create RawPortPdo\n");
fdx->RawPortPdo = P4CreatePdo( Fdo, PdoTypeRawPort, 0, NULL );
}
//
// Handle End of Chain Device
//
// make sure all 1284.3 daisy chain devices are deselected
P5DeselectAllDaisyChainDevices( controller );
{
// A small delay here seems to improve reliablility of 1284 device ID queries below.
LARGE_INTEGER delay;
delay.QuadPart = -1;
KeDelayExecutionThread( KernelMode, FALSE, &delay );
}
if( fdx->EndOfChainPdo ) {
if( fdx->DisableEndOfChainBusRescan ) {
//
// Pretend that the LPTx.4 device from previous rescan is still present.
//
// This is needed to work around firmware state machines that can't handle a
// 1284 Device ID query while a print job is active.
//
; // do nothing
} else {
//
// we had an end of chain device - verify that it's still there
//
if( !P5IsDeviceStillThere( Fdo, fdx->EndOfChainPdo ) ) {
// End of chain device is gone - do some cleanup and mark the PDO for removal/deletion
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - EndOfChain device gone\n");
// note - P5MarkPdoAsHardwareGone sets fdx->EndOfChainPdo to NULL
P5MarkPdoAsHardwareGone( Fdo, PdoTypeEndOfChain, 0 );
}
}
}
if( NULL == fdx->EndOfChainPdo ) {
//
// we don't have an EndOfChain device - check for EndOfChain device arrival
//
PCHAR devId = P4ReadRawIeee1284DeviceId( controller );
if( devId ) {
// RawIeee1284 string includes 2 bytes of length data at beginning, omit these 2 bytes in call to P4CreatePdo
PDEVICE_OBJECT EndOfChainPdo = P4CreatePdo( Fdo, PdoTypeEndOfChain, 0, (devId+2) );
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - EndOfChain device detected <%s>\n",(devId+2));
if( EndOfChainPdo ) {
fdx->EndOfChainPdo = EndOfChainPdo;
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - created EndOfChainPdo\n");
} else {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - FAILED to create EndOfChainPdo\n");
}
ExFreePool( devId );
}
}
#ifdef _X86_ // Zip drives not supported on 64bit systems
//
// Handle Legacy Zip device
//
if( fdx->LegacyZipPdo ) {
//
// we had a Legacy Zip device - verify that it's still there
//
if( !P5IsDeviceStillThere( Fdo, fdx->LegacyZipPdo ) ) {
// Legacy Zip device is gone - do some cleanup and mark the PDO for removal/deletion
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - LegacyZip device gone\n");
// note - P5MarkPdoAsHardwareGone sets fdx->LegacyZipPdo to NULL
P5MarkPdoAsHardwareGone( Fdo, PdoTypeLegacyZip, 0 );
}
}
if( NULL == fdx->LegacyZipPdo ) {
//
// We don't have a LegacyZip - check for arrival
//
if( !ParEnableLegacyZip ) {
//
// Enumeration of LegacyZip drives was disabled, check the
// registry to see if user has enabled LegacyZip detection
//
// Check under \HKLM\SYSTEM\CCS\Services\Parport\Parameters
PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"ParEnableLegacyZip", &ParEnableLegacyZip );
if( !ParEnableLegacyZip ) {
// Check under \HKLM\SYSTEM\CCS\Services\Parallel\Parameters (upgrade case - under Win2k flag was here)
PptRegGetDword( RTL_REGISTRY_SERVICES, L"Parallel\\Parameters", L"ParEnableLegacyZip", &ParEnableLegacyZip );
if( ParEnableLegacyZip ) {
// we found the setting in the old location, save
// setting in new Parport location so that we find the
// flag on the first check in the future
PptRegSetDword( RTL_REGISTRY_SERVICES, L"Parport\\Parameters", L"ParEnableLegacyZip", &ParEnableLegacyZip );
}
}
}
if( ParEnableLegacyZip ) {
//
// Enumeration of LegacyZip drives is enabled - check for a LegacyZip arrival
//
if( P5LegacyZipDetected( controller ) ) {
// detected drive - create LegacyZip PDO
PDEVICE_OBJECT legacyZipPdo = P4CreatePdo( Fdo, PdoTypeLegacyZip, 0, NULL );
DD((PCE)fdx,DDE,"legacy Zip arrival detected\n");
if( legacyZipPdo ) {
fdx->LegacyZipPdo = legacyZipPdo;
DD((PCE)fdx,DDE,"PptFdoHandleBusRelations - created LegacyZipPdo\n");
} else {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - FAILED to create LegacyZipPdo\n");
}
} else {
// no legacy Zip detected - nothing more to do here
DD((PCE)fdx,DDE,"no legacy Zip detected\n");
}
} // if( ParEnableLegacyZip ) -- Detection of LegacyZips is enabled
} // if( fdx->LegacyZipPdo )
//
// Handle enumeration of IEEE 1284.3 Daisy Chain Devices
//
// did the 1284.3 daisy chain change since the last rescan?
daisyChainDevCount = PptInitiate1284_3( fdx );
DD((PCE)fdx,DDW,"daisyChainDevCount = %d\n",daisyChainDevCount);
changeDetected = FALSE;
{
ULONG id;
const ULONG maxId = 1;
ULONG count = 0;
for( id = 0 ; id <= maxId ; ++id ) {
if( fdx->DaisyChainPdo[id] ) {
++count;
}
}
if( count != daisyChainDevCount ) {
// number of devices changed from previous scan
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - number of DC devices changed - count=%d, daisyChainDevCount=%d\n",
count, daisyChainDevCount);
changeDetected = TRUE;
}
}
if( !changeDetected ) {
// number of devices stayed the same - are any of the devices different?
//
// number of daisy chain devices didn't change
// check if any of the devices changed
ULONG id;
const ULONG maxId = 1;
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - number of DC devices stayed same - check the devices\n");
for( id = 0 ; id <= maxId ; ++id ) {
if( fdx->DaisyChainPdo[id] && !P5IsDeviceStillThere( Fdo, fdx->DaisyChainPdo[id] ) ) {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - a DC device changed\n");
changeDetected = TRUE;
break;
}
}
}
if( changeDetected ) {
// we detected a change in the 1284.3 daisy chain devices - nuke all existing devices
ULONG id;
const ULONG maxId = 1;
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - changeDetected - nuking existing daisy chain PDOs\n");
for( id = 0 ; id <= maxId ; ++id ) {
if( fdx->DaisyChainPdo[id] ) {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - nuking daisy chain %d\n",id);
P5MarkPdoAsHardwareGone( Fdo, PdoTypeDaisyChain, id );
PptAssert( NULL == fdx->DaisyChainPdo[id] );
}
}
fdx->PnpInfo.Ieee1284_3DeviceCount = 0;
} else {
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - !changeDetected in daisy chain PDOs\n");
}
// reinit daisy chain and assign addresses
daisyChainDevCount = PptInitiate1284_3( fdx );
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - daisyChainDevCount = %d\n",daisyChainDevCount);
if( daisyChainDevCount > 2 ) {
// we only support 2 devices per port even though the spec supports up to 4 devices per port
DD((PCE)fdx,DDW,"PptFdoHandleBusRelations - DaisyChainDevCount > 2, set to 2\n");
daisyChainDevCount = 2;
}
if( changeDetected ) {
// we detected a change in the 1284.3 daisy chain devices - we
// previously nuked all old devices - now create a new PDO for
// each device detected
UCHAR id;
PptAssert( 0 == fdx->PnpInfo.Ieee1284_3DeviceCount );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -