// Dot4Port.cpp: implementation of the Dot4Port class. // ////////////////////////////////////////////////////////////////////// #include "precomp.h" #include "initguid.h" #include "ntddpar.h" const TCHAR cszCFGMGR32[]=TEXT("cfgmgr32.dll"); const CHAR cszReenumFunc[]="CM_Reenumerate_DevNode_Ex"; ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CDot4Port::CDot4Port( BOOL bActive, LPTSTR pszPortName, LPTSTR pszDevicePath ) : CBasePort( bActive, pszPortName, pszDevicePath, cszDot4PortDesc ) { // Basically let the default constructor do the work. } CDot4Port::~CDot4Port() { } PORTTYPE CDot4Port::getPortType() { return DOT4PORT; } BOOL CDot4Port::checkPnP() { SETUPAPI_INFO SetupApiInfo; BOOL bRet = FALSE; DWORD dwIndex, dwLastError; UINT uOldErrorMode; HANDLE hToken = NULL; HDEVINFO hDevList = INVALID_HANDLE_VALUE; SP_DEVINFO_DATA DeviceInfoData; HINSTANCE hCfgMgr32 = 0; // Library instance. // Pointers to the pnp function... pfCM_Reenumerate_DevNode_Ex pfnReenumDevNode; if ( !LoadSetupApiDll( &SetupApiInfo ) ) return FALSE; // For a dot4 device we need to force a pnp event on the parallel port to get the // dot4 stack rebuilt. // If any of these fail, fail the call just as if the port couldn't be opened. // // Load the pnp dll. uOldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS); hCfgMgr32 = LoadLibrary( cszCFGMGR32 ); if(!hCfgMgr32) { SetErrorMode(uOldErrorMode); goto Done; } SetErrorMode(uOldErrorMode); // // Get the Addressed of pnp functions we want to call... // pfnReenumDevNode = (pfCM_Reenumerate_DevNode_Ex)GetProcAddress( hCfgMgr32, cszReenumFunc ); if( !pfnReenumDevNode ) goto Done; hToken = RevertToPrinterSelf(); if ( !hToken ) { dwLastError = GetLastError(); goto Done; } hDevList = SetupApiInfo.GetClassDevs( (LPGUID) &GUID_PARALLEL_DEVICE, NULL, NULL, DIGCF_INTERFACEDEVICE); if ( hDevList == INVALID_HANDLE_VALUE ) { dwLastError = GetLastError(); goto Done; } // Now get the DevInst handles for each DevNode dwLastError = ERROR_SUCCESS; dwIndex = 0; do { DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA); if ( !SetupApiInfo.EnumDeviceInfo( hDevList, dwIndex, &DeviceInfoData) ) { dwLastError = GetLastError(); if ( dwLastError == ERROR_NO_MORE_ITEMS ) break; // Normal exit DBGMSG(DBG_WARNING, ("DynaMon: Dot4.CheckPnP: SetupDiEnumDeviceInfo failed with %d for index %d\n", dwLastError, dwIndex)); goto Next; } // ReEnum on the current parallel port DevNode pfnReenumDevNode( DeviceInfoData.DevInst, CM_REENUMERATE_NORMAL, NULL ); Next: dwLastError = ERROR_SUCCESS; ++dwIndex; } while ( dwLastError == ERROR_SUCCESS ); // Revert back to the user's context. if ( !ImpersonatePrinterClient(hToken) ) { // Failure - Clear token so it won't happen again and save the error hToken = NULL; dwLastError = GetLastError(); goto Done; } // Impersonate worked so clear token hToken = NULL; // Try and open the port again. // If we fail, then the device must not be there any more or still switched off - fail as usual. m_hDeviceHandle = CreateFile( m_szDevicePath, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if ( m_hDeviceHandle == INVALID_HANDLE_VALUE ) goto Done; bRet = TRUE; Done: if ( hDevList != INVALID_HANDLE_VALUE ) SetupApiInfo.DestroyDeviceInfoList( hDevList ); if (hToken) { if ( !ImpersonatePrinterClient(hToken) ) { if (bRet) { dwLastError = GetLastError(); bRet = FALSE; } } } if ( hCfgMgr32 ) FreeLibrary( hCfgMgr32 ); if ( SetupApiInfo.hSetupApi ) FreeLibrary(SetupApiInfo.hSetupApi); SetLastError( dwLastError ); return bRet; }