windows-nt/Source/XPSP1/NT/drivers/parallel/parclass/ppa3x.c
2020-09-26 16:20:57 +08:00

617 lines
21 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1999 - 1999
//
// File: ppa3x.c
//
//--------------------------------------------------------------------------
#include "pch.h"
VOID
ParCheckEnableLegacyZipFlag()
/*++
Routine Description:
Initialize debugging variables from registry; set to default values
if anything fails.
Arguments:
RegistryPath - Root path in registry where we should look
Return Value:
None
--*/
{
NTSTATUS Status;
RTL_QUERY_REGISTRY_TABLE paramTable[2];
ULONG defaultZipEnabled = 0;
PWSTR suffix = L"\\Parameters";
UNICODE_STRING path = {0,0,0};
ULONG length;
//
// set up table entries for call to RtlQueryRegistryValues
//
RtlZeroMemory( paramTable, sizeof(paramTable));
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = (PWSTR)L"ParEnableLegacyZip";
paramTable[0].EntryContext = &ParEnableLegacyZip;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &defaultZipEnabled;
paramTable[0].DefaultLength = sizeof(ULONG);
//
// leave paramTable[2] as all zeros - this terminates the table
//
Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
RegistryPath.Buffer,
&paramTable[0],
NULL,
NULL);
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - status from RtlQueryRegistryValues = %x\n", Status) );
if( !NT_SUCCESS( Status ) ) {
// registry read failed, use defaults
ParEnableLegacyZip = defaultZipEnabled;
return;
}
if( ParEnableLegacyZip ) {
// we found a non-zero value - enable PnP for old parallel port Zip
ParDump2(PARPNP1, ("ppa3x::ParCheckEnableLegacyZipFlag - FOUND - ParEnableLegacyZip Flag = %08x\n", ParEnableLegacyZip) );
return;
}
//
// We didn't find the registry flag, maybe it's under the Parameters subkey
//
// compute the size of the path including the "parameters" suffix
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - RegPath length = %d\n", RegistryPath.Length) );
length = ( sizeof(WCHAR) * wcslen( suffix ) ) + sizeof(UNICODE_NULL);
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - suffix length = %d\n", length) );
length += RegistryPath.Length;
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - total dest length = %d\n", length) );
// build the path
path.Buffer = ExAllocatePool( PagedPool, length );
if( NULL == path.Buffer ) {
// out of pool, use defaults
ParEnableLegacyZip = defaultZipEnabled;
return;
}
RtlZeroMemory( path.Buffer, length );
path.MaximumLength = (USHORT)length;
RtlCopyUnicodeString( &path, &RegistryPath );
RtlAppendUnicodeToString( &path, suffix );
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - path = <%wZ>\n", &path) );
// query at new location in registry
Status = RtlQueryRegistryValues( RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
path.Buffer,
&paramTable[0],
NULL,
NULL);
RtlFreeUnicodeString( &path );
ParDump2(PARPNP4, ("ppa3x::ParCheckEnableLegacyZipFlag - status from RtlQueryRegistryValues on SubKey = %x\n", Status) );
if( !NT_SUCCESS( Status ) ) {
// registry read failed, use defaults
ParEnableLegacyZip = defaultZipEnabled;
return;
}
ParDump2(PARPNP1, ("ppa3x::ParCheckEnableLegacyZipFlag - FOUND SubKey ParEnableLegacyZip Flag = %08x\n", ParEnableLegacyZip) );
}
BOOLEAN
ParLegacyZipCheckDevice(
PUCHAR Controller
)
{
WRITE_PORT_UCHAR( Controller+DCR_OFFSET, (UCHAR)(DCR_NOT_INIT | DCR_AUTOFEED) );
if ( (READ_PORT_UCHAR( Controller+DSR_OFFSET ) & DSR_NOT_FAULT) == DSR_NOT_FAULT ) {
WRITE_PORT_UCHAR( Controller+DCR_OFFSET, (UCHAR)DCR_NOT_INIT );
if ( (READ_PORT_UCHAR( Controller+DSR_OFFSET ) & DSR_NOT_FAULT) != DSR_NOT_FAULT ) {
// A device was found
return TRUE;
}
}
// No device is there
return FALSE;
} // end PptLegacyZipCheckDevice()
PCHAR ParBuildLegacyZipDeviceId()
{
ULONG size = sizeof(PAR_LGZIP_PSEUDO_1284_ID_STRING) + sizeof(NULL);
PCHAR id = ExAllocatePool(PagedPool, size);
if( id ) {
RtlZeroMemory( id, size );
RtlCopyMemory( id, ParLegacyZipPseudoId, size - sizeof(NULL) );
return id;
} else {
return NULL;
}
}
PCHAR
Par3QueryLegacyZipDeviceId(
IN PDEVICE_EXTENSION Extension,
OUT PCHAR CallerDeviceIdBuffer, OPTIONAL
IN ULONG CallerBufferSize,
OUT PULONG DeviceIdSize,
IN BOOLEAN bReturnRawString // TRUE == include the 2 size bytes in the returned string
// FALSE == discard the 2 size bytes
)
{
USHORT deviceIdSize;
PCHAR deviceIdBuffer;
UNREFERENCED_PARAMETER( Extension );
// initialize returned size in case we have an error
*DeviceIdSize = 0;
deviceIdBuffer = ParBuildLegacyZipDeviceId();
if( !deviceIdBuffer ) {
// error, likely out of resources
return NULL;
}
deviceIdSize = (USHORT) strlen(deviceIdBuffer);
*DeviceIdSize = deviceIdSize;
if( (NULL != CallerDeviceIdBuffer) && (CallerBufferSize >= deviceIdSize) ) {
// caller supplied buffer is large enough, use it
RtlZeroMemory( CallerDeviceIdBuffer, CallerBufferSize );
RtlCopyMemory( CallerDeviceIdBuffer, deviceIdBuffer, deviceIdSize );
ExFreePool( deviceIdBuffer );
return CallerDeviceIdBuffer;
} else {
// caller buffer too small, return pointer to our buffer
return deviceIdBuffer;
}
}
PDEVICE_OBJECT
ParCreateLegacyZipPdo(
IN PDEVICE_OBJECT LegacyPodo,
UCHAR Dot3Id
)
/*++
Routine Description:
Create PDO for legacy Zip Drive
LegacyPodo - points to the Legacy PODO for the port
Return Value:
PDEVICE_OBJECT - on success, points to the PDO we create
NULL - otherwise
--*/
{
PDEVICE_EXTENSION legacyExt = LegacyPodo->DeviceExtension;
PDRIVER_OBJECT driverObject = LegacyPodo->DriverObject;
PDEVICE_OBJECT fdo = legacyExt->ParClassFdo;
UNICODE_STRING className = {0,0,NULL};
NTSTATUS status;
PCHAR deviceIdString = NULL;
ULONG deviceIdLength = 0;
PDEVICE_OBJECT newDevObj = NULL;
PDEVICE_EXTENSION newDevExt;
ULONG idTry = 1;
ULONG maxIdTries = 3;
BOOLEAN useModifiedClassName = FALSE;
UNICODE_STRING modifiedClassName;
UNICODE_STRING suffix;
UNICODE_STRING dash;
WCHAR suffixBuffer[10];
ULONG number = 0;
ULONG maxNumber = 256;
ULONG newLength;
PAGED_CODE();
//
// Query for PnP device
//
while( (NULL == deviceIdString) && (idTry <= maxIdTries) ) {
if( Dot3Id == DOT3_LEGACY_ZIP_ID) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - calling ParBuildLegacyZipDeviceId()\n"));
deviceIdString = ParBuildLegacyZipDeviceId();
if(deviceIdString)
{
deviceIdLength = strlen( deviceIdString );
}
} else{
ASSERT(FALSE); // should never get here
deviceIdString = Par3QueryDeviceId(legacyExt, NULL, 0, &deviceIdLength, FALSE, FALSE);
}
if( NULL == deviceIdString ) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - no 1284 ID on try %d\n", idTry) );
KeStallExecutionProcessor(1);
++idTry;
} else {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - devIdString=<%s> on try %d\n", deviceIdString, idTry) );
}
}
if( !deviceIdString ) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - no 1284 ID, bail out\n") );
return NULL;
}
//
// Found PnP Device, create a PDO to represent the device
// - create classname
// - create device object
// - initialize device object and extension
// - create symbolic link
// - register for PnP TargetDeviceChange notification
//
//
// Create a class name of the form \Device\ParallelN,
//
ParMakeDotClassNameFromBaseClassName(&legacyExt->ClassName, Dot3Id, &className);
if( !className.Buffer ) {
// unable to construct ClassName
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - unable to construct ClassName for device\n") );
ExFreePool(deviceIdString);
return NULL;
}
//
// create device object
//
status = ParCreateDevice(driverObject, sizeof(DEVICE_EXTENSION), &className,
FILE_DEVICE_PARALLEL_PORT, 0, TRUE, &newDevObj);
///
if( status == STATUS_OBJECT_NAME_COLLISION ) {
//
// old name is still in use, appending a suffix and try again
//
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - ParCreateDevice FAILED due to name Collision on <%wZ> - retry\n", &className));
useModifiedClassName = TRUE;
suffix.Length = 0;
suffix.MaximumLength = sizeof(suffixBuffer);
suffix.Buffer = suffixBuffer;
RtlInitUnicodeString( &dash, (PWSTR)L"-" );
newLength = className.MaximumLength + 5*sizeof(WCHAR); // L"-XXX" suffix
modifiedClassName.Length = 0;
modifiedClassName.MaximumLength = (USHORT)newLength;
modifiedClassName.Buffer = ExAllocatePool(PagedPool, newLength);
if( NULL == modifiedClassName.Buffer ) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - ParCreateDevice FAILED - no PagedPool avail\n"));
ExFreePool(deviceIdString);
RtlFreeUnicodeString( &className );
return NULL;
}
while( ( status == STATUS_OBJECT_NAME_COLLISION ) && ( number <= maxNumber ) ) {
status = RtlIntegerToUnicodeString(number, 10, &suffix);
if ( !NT_SUCCESS(status) ) {
ExFreePool(deviceIdString);
RtlFreeUnicodeString( &className );
RtlFreeUnicodeString( &modifiedClassName );
return NULL;
}
RtlCopyUnicodeString( &modifiedClassName, &className );
RtlAppendUnicodeStringToString( &modifiedClassName, &dash );
RtlAppendUnicodeStringToString( &modifiedClassName, &suffix );
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - trying ParCreateDevice with className <%wZ>\n", &modifiedClassName));
status = ParCreateDevice(driverObject, sizeof(DEVICE_EXTENSION), &modifiedClassName,
FILE_DEVICE_PARALLEL_PORT, 0, TRUE, &newDevObj);
if( NT_SUCCESS( status ) ) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - ParCreateDevice returned SUCCESS with className <%wZ>\n", &modifiedClassName));
} else {
++number;
}
}
}
///
if( useModifiedClassName ) {
// copy modifiedClassName to className
RtlFreeUnicodeString( &className );
className = modifiedClassName;
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - copy useModifiedClassName to className - className=<%wZ>\n", &className));
}
if( !NT_SUCCESS(status) ) {
// unable to create device object, bail out
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - unable to create device object "
"className=<%wZ>, bail out - status=%x\n", &className, status) );
ExFreePool(deviceIdString);
RtlFreeUnicodeString(&className);
ParLogError(fdo->DriverObject, NULL, PhysicalZero, PhysicalZero,
0, 0, 0, 9, STATUS_SUCCESS, PAR_INSUFFICIENT_RESOURCES);
return NULL;
} else {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - device created <%wZ>\n", &className));
}
//
// device object created
//
newDevExt = newDevObj->DeviceExtension;
//
// initialize device object and extension
//
ParInitCommonDOPre(newDevObj, fdo, &className);
status = ParInitPdo(newDevObj, (PUCHAR)deviceIdString, deviceIdLength, LegacyPodo, Dot3Id);
if( !NT_SUCCESS( status ) ) {
// initialization failed, clean up and bail out
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - call to ParInitPdo failed, bail out\n") );
ParAcquireListMutexAndKillDeviceObject(fdo, newDevObj);
return NULL;
}
ParInitCommonDOPost(newDevObj);
//
// create symbolic link
//
if( newDevExt->SymbolicLinkName.Buffer ) {
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - ready to create symlink - SymbolicLinkName <%wZ>, ClassName <%wZ>\n",
&newDevExt->SymbolicLinkName, &newDevExt->ClassName) );
ParDump2(PARPNP1, (" - Length=%hd, MaximumLength=%hd\n", newDevExt->ClassName.Length, newDevExt->ClassName.MaximumLength) );
ASSERT(newDevExt->ClassName.Length < 100);
PAGED_CODE();
status = IoCreateUnprotectedSymbolicLink(&newDevExt->SymbolicLinkName, &newDevExt->ClassName);
if ( NT_SUCCESS(status) ) {
// note this in our extension for later cleanup
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - SymbolicLinkName -> ClassName = <%wZ> -> <%wZ>\n",
&newDevExt->SymbolicLinkName, &newDevExt->ClassName) );
newDevExt->CreatedSymbolicLink = TRUE;
// Write symbolic link map info to the registry.
status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
(PWSTR)L"PARALLEL PORTS",
newDevExt->ClassName.Buffer,
REG_SZ,
newDevExt->SymbolicLinkName.Buffer,
newDevExt->SymbolicLinkName.Length +
sizeof(WCHAR));
if (!NT_SUCCESS(status)) {
// unable to write map info to registry - continue anyway
ParLogError(newDevObj->DriverObject, newDevObj,
newDevExt->OriginalController, PhysicalZero,
0, 0, 0, 6, status, PAR_NO_DEVICE_MAP_CREATED);
}
} else {
// unable to create the symbolic link.
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - unable to create SymbolicLink - status = %x\n",status));
newDevExt->CreatedSymbolicLink = FALSE;
RtlFreeUnicodeString(&newDevExt->SymbolicLinkName);
ParLogError(newDevObj->DriverObject, newDevObj,
newDevExt->OriginalController, PhysicalZero,
0, 0, 0, 5, status, PAR_NO_SYMLINK_CREATED);
}
} else {
// extension does not contain a symbolic link name for us to use
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - extension does not contain a symbolic link for us to use\n"));
newDevExt->CreatedSymbolicLink = FALSE;
}
// End-Of-Chain PDO - register for PnP TargetDeviceChange notification
status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange,
0,
(PVOID)newDevExt->PortDeviceFileObject,
driverObject,
(PDRIVER_NOTIFICATION_CALLBACK_ROUTINE) ParPnpNotifyTargetDeviceChange,
(PVOID)newDevObj,
&newDevExt->NotificationHandle);
if( !NT_SUCCESS(status) ) {
// PnP registration for TargetDeviceChange notification failed,
// clean up and bail out
ParDump2(PARPNP1, ("ppa3x::ParCreateLegacyZipPdo - PnP registration failed, killing PDO\n") );
ParAcquireListMutexAndKillDeviceObject(fdo, newDevObj);
return NULL;
}
return newDevObj;
}
PDEVICE_OBJECT
ParCreateAddLegacyZipPdo(
IN PDEVICE_OBJECT LegacyPodo
)
/*++
Create a new PDO for the legacy Zip and add the PDO to the list
of PDOs
--*/
{
PDEVICE_OBJECT newPdo = ParCreateLegacyZipPdo( LegacyPodo, DOT3_LEGACY_ZIP_ID );
if( newPdo ) {
ParAddDevObjToFdoList( newPdo );
}
return newPdo;
}
NTSTATUS
ParSelectLegacyZip( IN PDEVICE_OBJECT PortDeviceObject )
//
// Select Legacy Zip Drive
//
// Note: Caller must have already Acquired the Port prior to calling this function.
//
// Returns: STATUS_SUCCESS if drive selected, !STATUS_SUCCESS otherwise
//
{
PARALLEL_1284_COMMAND par1284Command;
NTSTATUS status;
ParDump2(PARLGZIP, ("rescan::ParSelectLegacyZip - Enter\n"));
par1284Command.ID = 0;
par1284Command.Port = 0;
par1284Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT | PAR_LEGACY_ZIP_DRIVE;
status = ParBuildSendInternalIoctl(IOCTL_INTERNAL_SELECT_DEVICE,
PortDeviceObject,
&par1284Command, sizeof(PARALLEL_1284_COMMAND),
NULL, 0, NULL);
ParDump2(PARLGZIP, ("rescan::ParSelectLegacyZip - returning status = %x\n", status));
return status;
}
NTSTATUS
ParDeselectLegacyZip( IN PDEVICE_OBJECT PortDeviceObject )
//
// Select Legacy Zip Drive
//
// Note: This function does not Release the port so the Caller still has
// the port after this function returns.
//
// Returns: STATUS_SUCCESS if drive deselected, !STATUS_SUCCESS otherwise
// (we don't expect this call to ever fail, but check just
// in case)
//
{
PARALLEL_1284_COMMAND par1284Command;
NTSTATUS status;
ParDump2(PARLGZIP, ("rescan::ParDeselectLegacyZip - Enter\n"));
par1284Command.ID = 0;
par1284Command.Port = 0;
par1284Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT | PAR_LEGACY_ZIP_DRIVE;
status = ParBuildSendInternalIoctl(IOCTL_INTERNAL_DESELECT_DEVICE,
PortDeviceObject,
&par1284Command, sizeof(PARALLEL_1284_COMMAND),
NULL, 0, NULL);
ParDump2(PARLGZIP, ("rescan::ParDeselectLegacyZip - returning status = %x\n", status));
return status;
}
BOOLEAN
ParZipPresent( PDEVICE_OBJECT LegacyPodo )
//
// Legacy Zip is present if we can SELECT it
//
{
BOOLEAN zipPresent = FALSE;
PDEVICE_EXTENSION legacyExt = LegacyPodo->DeviceExtension;
PDEVICE_OBJECT portDeviceObject = legacyExt->PortDeviceObject;
if( NT_SUCCESS( ParSelectLegacyZip( portDeviceObject ) ) ) {
ParDeselectLegacyZip( portDeviceObject );
zipPresent = TRUE;
}
return zipPresent;
}
VOID
ParRescanLegacyZip( IN PPAR_DEVOBJ_STRUCT CurrentNode )
//
// Rescan for change in Legacy Zip Drive, update PDO list if change detected
//
{
BOOLEAN hadZip;
BOOLEAN foundZip;
PDEVICE_OBJECT zipPdo;
ParDump2(PARLGZIP, ("rescan::ParRescanLegacyZip - Enter\n"));
if( !ParEnableLegacyZip ) {
//
// legacy zip detection is disabled
//
ParDump2(PARLGZIP, ("rescan::ParRescanLegacyZip - !ParEnableLegacyZip\n"));
//
// if we had a Legacy Zip then automatically mark it as hardware gone
//
zipPdo = CurrentNode->LegacyZipPdo;
if( zipPdo ) {
// we should never get here, but handle it if we do
ParMarkPdoHardwareGone( zipPdo->DeviceExtension );
}
return;
}
//
// Check for presence of Legacy Zip - update PDO list if we detect a change
//
hadZip = (NULL != CurrentNode->LegacyZipPdo);
foundZip = ParZipPresent( CurrentNode->LegacyPodo );
ParDump2(PARLGZIP, ("rescan::ParRescanLegacyZip - hadZip=%s, foundZip=%s\n",
hadZip?"TRUE":"FALSE", foundZip?"TRUE":"FALSE"));
if( foundZip && !hadZip ) {
// we found a new Zip - create a PDO for it
ParDump2(PARLGZIP, ("rescan::ParRescanLegacyZip - Found new Legacy Zip\n"));
ParCreateAddLegacyZipPdo( CurrentNode->LegacyPodo );
} else if( !foundZip && hadZip ) {
// our Zip went away - mark PDO as hardware gone
ParDump2(PARLGZIP, ("rescan::ParRescanLegacyZip - Had a Legacy Zip but now it's gone\n"));
zipPdo = CurrentNode->LegacyZipPdo;
ParMarkPdoHardwareGone( zipPdo->DeviceExtension );
}
return;
}