//------------------------------------------------------------------- // // // //------------------------------------------------------------------- #include "pch.hxx" #pragma hdrstop static const WCHAR PSZ_SETUPDLL[] = L"SetupDll.Dll"; static const WCHAR PSZ_SETUPEXE[] = L"Setup.Exe"; static const CHAR PSZ_SETUPENTRY[] = "LegacyInfInterpret"; // setup command line flags static const WCHAR PSZ_SETUP_NOBLUEWASH[] = L"/f" ; static const WCHAR PSZ_SETUP_INFNAME[] = L"/I" ; static const WCHAR PSZ_SETUP_SYMOPTION[] = L"/t" ; static const WCHAR PSZ_SETUP_HWND[] = L"/w" ; static const WCHAR PSZ_SETUP_INFSECTION[] = L"/c" ; // origination state strings static WCHAR PSZ_SETUP_ORIGIN_NCPA[] = L"ncpa" ; static WCHAR PSZ_SETUP_ORIGIN_INSTALL[] = L"install" ; // install mode state strings static WCHAR PSZ_SETUP_MODE_INSTALL[] = L"install" ; static WCHAR PSZ_SETUP_MODE_REMOVE[] = L"deinstall" ; static WCHAR PSZ_SETUP_MODE_PROPERTIES[] = L"configure" ; static WCHAR PSZ_SETUP_MODE_BIND[] = L"bind" ; static WCHAR PSZ_SETUP_MODE_UPDATE[] = L"update" ; // net symbols static const WCHAR PSZ_SETUP_NET_INFSECTION[] = L"NTN_InfSection" ; static const WCHAR PSZ_SETUP_NET_INFNAME[] = L"NTN_Infname" ; static const WCHAR PSZ_SETUP_NET_INFOPTION[] = L"NTN_InfOption" ; static const WCHAR PSZ_SETUP_NET_ORIGINATION[] = L"NTN_Origination" ; static const WCHAR PSZ_SETUP_NET_INSTALLMODE[] = L"NTN_InstallMode" ; static const WCHAR PSZ_SETUP_NET_REGBASE[] = L"NTN_RegBase" ; // these are unused // static const WCHAR PSZ_SETUP_NET_SERVICEBASE[] = L"NTN_ServiceBase" ; // static const WCHAR PSZ_SETUP_NET_SERVICEKEY[] = L"NTN_ServicekeyName" ; // static const WCHAR PSZ_SETUP_NET_REGPRODUCT[] = L"NTN_RegProduct" ; typedef DWORD (* SETUPINTERPRETERPROC) ( IN HWND OwnerWindow, IN PCSTR InfFilename, IN PCSTR InfSection, IN PCHAR ExtraVariables, OUT PSTR InfResult, IN DWORD BufferSize, OUT int *InterpResult, IN PCSTR InfSourceDir OPTIONAL ); //------------------------------------------------------------------- // // // //------------------------------------------------------------------- //------------------------------------------------------------------- // // // //------------------------------------------------------------------- void Arguments::Clear() { while (_argc > 0) { _argc--; delete [] _argv[_argc]; } delete [] _argv; _argv = NULL; _argc = 0; } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL Arguments::Include(PCWSTR pszArgument, BOOL fAddQuotes ) { PSTR pszNewArg; PSTR pszTemp; int cchNewArg; ASSERT( pszArgument != NULL ); BOOL frt = TRUE; do { // make a local copy of the string in CHAR // cchNewArg = (lstrlen(pszArgument) * 2); // need room for converting if (fAddQuotes) { cchNewArg += 2; } pszTemp = pszNewArg = new CHAR[ cchNewArg + 1 ]; if (NULL == pszNewArg) { frt = FALSE; break; } if (fAddQuotes) { pszTemp[0] = '\"'; pszTemp++; cchNewArg--; } // use Windows api // ::WideCharToMultiByte(CP_ACP,0,pszArgument,-1,pszTemp,cchNewArg,NULL,NULL); // wcstombs( pszTemp, pszArgument, cchNewArg ); if (fAddQuotes) { lstrcatA( pszNewArg, "\"" ); } // increase the size of _argv to hold another // CHAR** argvNew; argvNew = new PSTR[_argc+1]; if (NULL == argvNew) { frt = FALSE; break; } memcpy( argvNew, _argv, _argc * sizeof( PSTR ) ); delete _argv; _argv = argvNew; // add new entry _argv[_argc] = pszNewArg; _argc++; } while (FALSE); if (!frt) { delete [] pszNewArg; } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL Arguments::IncludeAsDec( DWORD dwArgument ) { WCHAR pszTemp[11]; // 4294967295 wsprintf( pszTemp, L"%ld", dwArgument ); return( Include( pszTemp ) ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL Arguments::IncludeAsHex( DWORD dwArgument ) { WCHAR pszTemp[11]; // 0xFFFFFFFF wsprintf( pszTemp, L"%lx", dwArgument ); return( Include( pszTemp ) ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- PSTR Arguments::CreateCommandLineA( PCSTR pszExe ) { PSTR pszTemp; INT iArgs; INT cchTemp = 0; if (NULL != pszExe) { cchTemp = lstrlenA( pszExe ); } // get total length for (iArgs = 0 ; iArgs < _argc; iArgs++) { // include a space delemitor for each arg cchTemp += lstrlenA( _argv[iArgs] ) + 1; } pszTemp = new CHAR[cchTemp + 1]; if (NULL != pszTemp) { if (NULL != pszExe) { lstrcpyA(pszTemp, pszExe); } else { pszTemp[0] = '\0'; } // copy the items over for (iArgs = 0; iArgs < _argc; iArgs++) { lstrcatA( pszTemp, _argv[iArgs] ); lstrcatA( pszTemp, " " ); // place a space between args } } return( pszTemp ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- PWSTR Arguments::CreateCommandLineW( PCWSTR pszExe ) { PSTR pszTemp; PWSTR pszWide = NULL; PWSTR pszPostExe; INT cchTemp; pszTemp = CreateCommandLineA(); if (NULL != pszTemp) { cchTemp = lstrlenA( pszTemp ); if (NULL != pszExe) { cchTemp += lstrlen( pszExe ) + 1; // and a space } pszPostExe = pszWide = new WCHAR[ cchTemp + 1 ]; if (NULL != pszWide) { if (NULL != pszExe) { lstrcpy( pszWide, pszExe ); lstrcat( pszWide, L" " ); pszPostExe += lstrlen( pszExe ) + 1; // and a space } mbstowcs( pszPostExe, pszTemp, cchTemp + 1 ); } delete [] pszTemp; } return( pszWide ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- void InfExeSymbols::Clear() { Reset(); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- void InfExeSymbols::Reset() { } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL InfExeSymbols::Include( PCWSTR pszSymbol, DWORD dwValue, BOOL fAsHex ) { WCHAR pszTemp[11]; // 4294967295 or 0xFFFFFFFF String( pszTemp, dwValue, fAsHex ); return( Include( pszSymbol, pszTemp ) ); }; //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL InfExeSymbols::Include( PCWSTR pszSymbol, PCWSTR pszValue, BOOL fQuoted ) { BOOL frt = TRUE; ASSERT( pszSymbol != NULL ); ASSERT( pszValue != NULL ); if ((NULL != pszSymbol) && (NULL != pszValue) ) { PWSTR pszNewValue; INT cchNewValue; INT cchConverted; cchNewValue = lstrlen(pszValue); if (fQuoted) { cchNewValue += 2; // we will be adding quotes to the value } // create new buffer pszNewValue = new WCHAR[ cchNewValue + 1 ]; if (NULL == pszNewValue) { frt = FALSE; } else { // create new value if (fQuoted) { lstrcpy( pszNewValue, L"\"" ); } else { pszNewValue[0] = L'\0'; } lstrcat( pszNewValue, pszValue ); if (fQuoted) { lstrcat( pszNewValue, L"\"" ); } // add the arguments if ( !_argSymbols.Include( PSZ_SETUP_SYMOPTION ) || !_argSymbols.Include( pszSymbol ) || !_argSymbols.Include( L"=" ) || !_argSymbols.Include( pszNewValue ) ) { frt = FALSE; } } } else { frt = FALSE; } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- void InfDllSymbols::Clear() { delete [] _plszSymbols; Reset(); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- void InfDllSymbols::Reset() { _cchSymbols = 0; _plszSymbols = NULL; }; //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL InfDllSymbols::Include( PCWSTR pszSymbol, DWORD dwValue, BOOL fAsHex ) { WCHAR pszTemp[11]; // 4294967295 or 0xFFFFFFFF String( pszTemp, dwValue, fAsHex ); return( Include( pszSymbol, pszTemp ) ); }; //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL InfDllSymbols::Include( PCWSTR pszSymbol, PCWSTR pszValue, BOOL fQuoted ) { BOOL frt = TRUE; ASSERT( pszSymbol != NULL ); ASSERT( pszValue != NULL ); if ((NULL != pszSymbol) && (NULL != pszValue) ) { PSTR plszNewSymbols; INT cchNewSymbols; INT cbConverted; PSTR pmbszValue; INT cbValue; do { // since value maybe localized, the conversion from WideChar to MultiByte // may require more space cbValue = lstrlen(pszValue) * 2 + 1; pmbszValue = new CHAR[ cbValue ]; if (NULL == pmbszValue) { frt = FALSE; break; } // use Windows api // cbValue = ::WideCharToMultiByte(CP_ACP,0,pszValue,-1,pmbszValue,cbValue,NULL,NULL); cbValue--; // elimitate null-terminate. // cbValue = wcstombs( pmbszValue, pszValue, cbValue); // _cchSymbols never includes the extra terminating null // so we must always allocate that extra one // cchNewSymbols = _cchSymbols + lstrlen(pszSymbol) + cbValue + 2; if (fQuoted) { cchNewSymbols += 2; // we will be adding quotes to the value } // create new buffer plszNewSymbols = new CHAR[ cchNewSymbols + 1 ]; if (NULL == plszNewSymbols) { frt = FALSE; break; } // copy old data memcpy( plszNewSymbols, _plszSymbols, _cchSymbols ); // free old data delete [] _plszSymbols; // use the new stuff _plszSymbols = plszNewSymbols; // append new symbol and value plszNewSymbols += _cchSymbols; // use Windows api // cbConverted = ::WideCharToMultiByte(CP_ACP,0,pszSymbol,-1,plszNewSymbols,lstrlen(pszSymbol) + 1,NULL,NULL); cbConverted--; // elimitate null-terminate. // cbConverted = wcstombs( plszNewSymbols, pszSymbol, lstrlen(pszSymbol) + 1 ); plszNewSymbols += cbConverted + 1; if (fQuoted) { plszNewSymbols[0] = '\"'; plszNewSymbols++; } lstrcpyA( plszNewSymbols, pmbszValue ); plszNewSymbols += cbValue; if (fQuoted) { plszNewSymbols[0] = '\"'; plszNewSymbols++; } // null terminate the value and null terminate the list plszNewSymbols[0] = '\0'; plszNewSymbols[1] = '\0'; _cchSymbols = cchNewSymbols; } while (FALSE); delete [] pmbszValue; } else { frt = FALSE; } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- PWSTR InfSymbols::String( PWSTR pszString, DWORD dwValue, BOOL fAsHex ) { if (fAsHex) { wsprintf( pszString, L"%lx", dwValue ); } else { wsprintf( pszString, L"%ld", dwValue ); } return( pszString ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- SetupInterpreter::SetupInterpreter( BOOL fInProcess ) { _fInProcess = fInProcess; _hwnd = NULL; _pszInfName = NULL; _pszInfSection = NULL; _hthrd = NULL; _dwRt = 0; _pinfDllSymbols = NULL; _pinfExeSymbols = NULL; }; void SetupInterpreter::Clear() { if (NULL != _hthrd) { ::CloseHandle( _hthrd ); } delete [] _pszInfName; delete [] _pszInfSection; delete _pinfExeSymbols; delete _pinfDllSymbols; _hwnd = NULL; _pszInfName = NULL; _pszInfSection = NULL; _hthrd = NULL; _dwRt = 0; _pinfDllSymbols = NULL; _pinfExeSymbols = NULL; }; //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL SetupInterpreter::Initialize( HWND hwnd, PCWSTR pszInfSection, PCWSTR pszInfName ) { BOOL frt = TRUE; INT cbTemp; ASSERT( NULL != pszInfName ); // a thread is still running, cannot re-Initialize if ((NULL == _hthrd) && (NULL != pszInfName)) { do { Clear(); _hwnd = hwnd; if (NULL != pszInfSection) { _pszInfSection = new WCHAR[ lstrlen( pszInfSection ) + 1 ]; if (NULL == _pszInfSection) { frt = FALSE; break; } lstrcpy( _pszInfSection, pszInfSection ); } _pszInfName = new WCHAR[ lstrlen( pszInfName ) + 1 ]; if (NULL == _pszInfName) { frt = FALSE; break; } lstrcpy( _pszInfName, pszInfName ); if (_fInProcess) { _pinfDllSymbols = new InfDllSymbols; if (NULL == _pinfDllSymbols) { frt = FALSE; break; } } else { _pinfExeSymbols = new InfExeSymbols; if (NULL == _pinfExeSymbols) { frt = FALSE; break; } frt = _pinfExeSymbols->Include( PSZ_SETUP_NOBLUEWASH ); } } while (FALSE); if (!frt) { Clear(); } } else { frt = FALSE; } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL SetupInterpreter::SetNetShellModes( SETUP_INSTALL_MODE simMode, SETUP_INSTALL_ORIGIN sioOrigin) { BOOL frt = FALSE; if (NULL == _hthrd) { // set origination // PWSTR pszOrigin; switch ( sioOrigin ) { case SIO_NCPA: pszOrigin = PSZ_SETUP_ORIGIN_NCPA ; break; case SIO_INSTALL: pszOrigin = PSZ_SETUP_ORIGIN_INSTALL ; break ; } if (IncludeSymbol( PSZ_SETUP_NET_ORIGINATION, pszOrigin )) { // set install modes // PWSTR pszMode = NULL; switch ( simMode ) { case SIM_INSTALL: pszMode = PSZ_SETUP_MODE_INSTALL ; break ; case SIM_DEINSTALL: pszMode = PSZ_SETUP_MODE_REMOVE ; break ; case SIM_CONFIGURE: pszMode = PSZ_SETUP_MODE_PROPERTIES ; break ; case SIM_UPDATE: pszMode = PSZ_SETUP_MODE_UPDATE ; break ; case SIM_BIND: pszMode = PSZ_SETUP_MODE_BIND ; break ; } frt = IncludeSymbol( PSZ_SETUP_NET_INSTALLMODE, pszMode ); } } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- DWORD SetupInterpreter::SetNetComponent( PCWSTR pszOption, PCWSTR pszInfName, PCWSTR pszRegBase ) { DWORD dwrt = ERROR_SUCCESS; ASSERT( pszOption != NULL ); ASSERT( pszInfName != NULL ); if (!IncludeSymbol( PSZ_SETUP_NET_INFNAME, pszInfName ) || !IncludeSymbol( PSZ_SETUP_NET_INFOPTION, pszOption, TRUE ) ) { dwrt = ERROR_NOT_ENOUGH_MEMORY; } if (pszRegBase != NULL) { if (!IncludeSymbol( PSZ_SETUP_NET_REGBASE, pszRegBase, TRUE ) ) { dwrt = ERROR_NOT_ENOUGH_MEMORY; } } return( dwrt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- DWORD SetupInterpreter::SetNetComponent( REG_KEY& rnComponent ) { DWORD dwrt = ERROR_SUCCESS; ASSERT( &rnComponent != NULL ); if (NULL == _hthrd) { NLS_STR nlsRegProductName ; NLS_STR nlsNetRulesName( RGAS_NETRULES_NAME ) ; NLS_STR nlsInfOption; NLS_STR nlsInfName; do { // Get the Registry key name. if ( dwrt = nlsRegProductName.QueryError()) break; if ( dwrt = rnComponent.QueryName( & nlsRegProductName, FALSE )) break ; REG_KEY rnNetRules( rnComponent, nlsNetRulesName ) ; if ( dwrt = nlsInfName.QueryError() ) break ; if ( dwrt = nlsNetRulesName.QueryError() ) break ; // Check that the NetRules key really exists. if ( rnNetRules.QueryError() ) { dwrt = IDS_NCPA_COMP_KEY_NF ; break ; } // Get the name of the INF file from the Registry dwrt = rnNetRules.QueryValue( RGAS_INF_FILE_NAME, &nlsInfName ) ; if ( dwrt ) { dwrt = IDS_NCPA_COMP_INF_VALUE_NF ; break ; } if ( dwrt = rnNetRules.QueryValue( RGAS_INF_OPTION, & nlsInfOption ) ) break ; dwrt = ERROR_NOT_ENOUGH_MEMORY ; dwrt = SetNetComponent( nlsInfOption.QueryPch(), nlsInfName.QueryPch(), nlsRegProductName.QueryPch() ); } while (FALSE); } else { dwrt = ERROR_MAX_THRDS_REACHED; } return( dwrt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL SetupInterpreter::SetNetInf( PCWSTR pszInfSection, PCWSTR pszInfName ) { BOOL frt = TRUE; ASSERT( pszInfSection != NULL ); ASSERT( pszInfName != NULL ); if ( (NULL == _hthrd) && (NULL != pszInfSection) && (NULL != pszInfName) ) { frt = (IncludeSymbol( PSZ_SETUP_NET_INFNAME, pszInfName ) && IncludeSymbol( PSZ_SETUP_NET_INFSECTION, pszInfSection, TRUE ) ); } else { frt = FALSE; } return( frt ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- DWORD SetupInterpreter::InProcessRun( BOOL fDisableParent ) { HINSTANCE hinstSetup; DWORD dwError = ERROR_SUCCESS ; #ifdef DBG { ::OutputDebugString(L"NETCFG: "); ::OutputDebugString(L"\n"); } #endif hinstSetup = ::LoadLibrary( PSZ_SETUPDLL ); if (NULL != hinstSetup) { SETUPINTERPRETERPROC fp; fp = (SETUPINTERPRETERPROC)::GetProcAddress( hinstSetup, PSZ_SETUPENTRY ); if (NULL != fp) { PSTR pszInfName = NULL; PSTR pszInfSection = NULL; INT cbTemp; HWND hwndFocus = NULL; if (fDisableParent) { // need to get the focus and save it hwndFocus = GetFocus(); ::EnableWindow( _hwnd, FALSE ); } do { if (NULL != _pszInfSection) { // convert inf section name cbTemp = lstrlen( _pszInfSection ) * 2 + 1; pszInfSection = new CHAR[ cbTemp ]; if (NULL == pszInfSection) { dwError = ERROR_NOT_ENOUGH_MEMORY; break; } // use Windows api // ::WideCharToMultiByte(CP_ACP,0,_pszInfSection,-1,pszInfSection,cbTemp,NULL,NULL); // wcstombs( pszInfSection, _pszInfSection, cbTemp ); } // convert inf name cbTemp = lstrlen( _pszInfName ) * 2 + 1; pszInfName = new CHAR[ cbTemp ]; if (NULL == pszInfName) { dwError = ERROR_NOT_ENOUGH_MEMORY; break; } // use Windows api // ::WideCharToMultiByte(CP_ACP,0,_pszInfName,-1,pszInfName,cbTemp,NULL,NULL); // wcstombs( pszInfName, _pszInfName, cbTemp ); if (!fp( _hwnd, pszInfName, pszInfSection, _pinfDllSymbols->QuerySymbols(), _pszInfResult, CB_INFRESULT, (PINT)&_dwRt, NULL )) { dwError = ERROR_PROCESS_ABORTED; } } while (FALSE); delete [] pszInfName; delete [] pszInfSection; if (fDisableParent) { // need to restore the focus that was saved ::EnableWindow( _hwnd, TRUE ); if (NULL != hwndFocus) { SetFocus( hwndFocus ); } } } else { dwError = GetLastError(); } // make sure that the library is unloaded before continuing // { WCHAR pszDllName[MAX_PATH + 1]; while (0 != ::GetModuleFileName(hinstSetup, pszDllName, MAX_PATH + 1)) { ::FreeLibrary( hinstSetup ); } } } else { dwError = GetLastError(); } return( dwError ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- DWORD SetupInterpreter::OutProcessRun( BOOL fDisableParent ) { DWORD dwError = ERROR_SUCCESS ; PWSTR pszCommandLine = NULL; STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; do { if (NULL != _pszInfSection) { if (!IncludeSymbol( PSZ_SETUP_INFSECTION, _pszInfSection, TRUE )) { dwError = ERROR_NOT_ENOUGH_MEMORY; break; } } if (!_pinfExeSymbols->Include( PSZ_SETUP_INFNAME ) || !_pinfExeSymbols->Include( _pszInfName ) || !_pinfExeSymbols->Include( PSZ_SETUP_HWND ) || !_pinfExeSymbols->Include( (DWORD)_hwnd ) ) { dwError = ERROR_NOT_ENOUGH_MEMORY; break; } pszCommandLine = _pinfExeSymbols->CreateCommandLine( PSZ_SETUPEXE ); if (NULL == pszCommandLine) { dwError = ERROR_NOT_ENOUGH_MEMORY; break; } StartupInfo.cb = sizeof( STARTUPINFO ); StartupInfo.lpReserved = NULL; StartupInfo.lpDesktop = NULL; StartupInfo.lpTitle = NULL; StartupInfo.dwFlags = STARTF_USESHOWWINDOW; StartupInfo.cbReserved2 = 0; StartupInfo.lpReserved2 = NULL; StartupInfo.wShowWindow = SW_SHOWMINNOACTIVE; if (!::CreateProcess( NULL, pszCommandLine, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &ProcessInfo )) { dwError = GetLastError(); break; } ::WaitForSingleObject( ProcessInfo.hProcess, INFINITE ); ::GetExitCodeProcess( ProcessInfo.hProcess, &_dwRt ); ::CloseHandle( ProcessInfo.hProcess ); ::CloseHandle( ProcessInfo.hThread ); } while (FALSE); delete [] pszCommandLine; return( dwError ); } //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL SetupInterpreter::IncludeSymbol( PCWSTR pszSymbol, PCWSTR pszValue, BOOL fQuoted ) { BOOL frt; if (_fInProcess) { frt = _pinfDllSymbols->Include( pszSymbol, pszValue, fQuoted ); } else { frt = _pinfExeSymbols->Include( pszSymbol, pszValue, fQuoted ); } return( frt ); }; //------------------------------------------------------------------- // // // //------------------------------------------------------------------- BOOL SetupInterpreter::IncludeSymbol( PCWSTR pszSymbol, DWORD dwValue, BOOL fAsHex ) { BOOL frt; if (_fInProcess) { frt = _pinfDllSymbols->Include( pszSymbol, dwValue, fAsHex ); } else { frt = _pinfExeSymbols->Include( pszSymbol, dwValue, fAsHex ); } return( frt ); };