|
|
//+-------------------------------------------------------------------------
//
// 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, ¶mTable[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, ¶mTable[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; }
|