#include "setupp.h" #pragma hdrstop #define INTL_ANSWER_FILE L"intl.txt" #define INTL_LANG_SECTION L"regionalsettings" #define INTL_LOCALE L"userlocale" #define INTL_KEYBOARD L"inputlocale" // This turns on some debug spew that lists all the available locales, geo // locations, and keyboards. #define INTL_LIST_OPTIONS 0 #define LANG_LIST_INCREMENT 10 POOBE_LOCALE_INFO LanguageList = NULL; DWORD LanguageListSize; DWORD LanguageIndex; DWORD DefaultID; DWORD DefaultIndex; typedef struct tagPHONEENTRY { LPWSTR Country; LPWSTR TollFreeNumber; LPWSTR TollNumber; } PHONEENTRY, *PPHONEENTRY; PWSTR PhoneList = NULL; DWORD PhoneListSize; DWORD PhoneListLength; // // Boolean value indicating whether we're doing a subset of gui-mode setup. // BOOL OobeSetup = FALSE; // // We need a global variable for OCM, coresponding to the local variable in // InstallWindowsNT(). // #ifdef _OCM PVOID g_OcManagerContext; #endif BOOL WINAPI SetupGetProductType( PWSTR Product, PDWORD pSkuFlags ) { Product[0] = 0; *pSkuFlags = 0; return TRUE; } PID3_RESULT WINAPI SetupPidGen3( PWSTR Pid3, DWORD SkuFlags, PWSTR OemId, BOOL Batch, PWSTR Pid2, LPBYTE lpPid3, LPBOOL Compliance ) { if ( !InitializePidVariables() ) { SetupDebugPrint( L"SETUP: InitializePidVariables failed" ); return PID_INVALID; } if ( !SetPid30Variables( Pid3 ) ) { SetupDebugPrint( L"SETUP: SetPid30Variables failed" ); return PID_INVALID; } if ( !ValidateAndSetPid30() ) { SetupDebugPrint( L"SETUP: ValidateAndSetPid30 failed" ); return PID_INVALID; } if(!SetProductIdInRegistry()) { SetupDebugPrint( L"SETUP: SetProductIdInRegistry failed" ); return PID_INVALID; } return PID_VALID; } BOOL WINAPI SetupGetValidEula( PCWSTR Eula, PWSTR Path ) { return TRUE; } BOOL CheckLangListSize( DWORD StructSize ) { PVOID NewList; // // Check to make sure the LanguageList has at least 1 unused element. // If not, make it bigger. // if ( LanguageIndex == LanguageListSize ) { LanguageListSize *= 2; NewList = MyRealloc( LanguageList, LanguageListSize * StructSize ); if ( NewList ) { LanguageList = NewList; } else { return FALSE; } } return TRUE; } VOID WINAPI SetupDestroyLanguageList( IN POOBE_LOCALE_INFO LanguageList, IN DWORD Count ) { DWORD i; if ( LanguageList ) { for ( i=0; i < Count; i++ ) { if ( LanguageList + i ) { MyFree( LanguageList[i].Name ); } } MyFree( LanguageList ); } } BOOL CALLBACK EnumLocalesProc( PWSTR pszLocale ) { BOOL b; LCID Locale; TCHAR LanguageName[128]; POOBE_LOCALE_INFO pLocaleInfo; Locale = wcstoul (pszLocale, NULL, 16); b = GetLocaleInfo ( Locale, LOCALE_SLANGUAGE | LOCALE_NOUSEROVERRIDE, LanguageName, sizeof(LanguageName) / sizeof(TCHAR) ); MYASSERT(b); if ( !b ) { return FALSE; } // // Add it to our global array // if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) { SetupDestroyLanguageList( LanguageList, LanguageIndex ); LanguageList = NULL; return FALSE; } pLocaleInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex; pLocaleInfo->Name = MyMalloc( (lstrlen(LanguageName) + 1) * sizeof(TCHAR) ); if ( !pLocaleInfo->Name ) { SetupDestroyLanguageList( LanguageList, LanguageIndex ); LanguageList = NULL; return FALSE; } lstrcpy( pLocaleInfo->Name, LanguageName ); pLocaleInfo->Id = Locale; pLocaleInfo->Installed = IsValidLocale( Locale, LCID_INSTALLED ); if ( Locale == DefaultID ) { DefaultIndex = LanguageIndex; } LanguageIndex++; return TRUE; } int __cdecl LocaleCompare( const void *arg1, const void *arg2 ) { return lstrcmp( ((POOBE_LOCALE_INFO)arg1)->Name, ((POOBE_LOCALE_INFO)arg2)->Name ); } BOOL WINAPI SetupGetLocaleOptions( IN DWORD OptionalDefault, OUT POOBE_LOCALE_INFO *ReturnList, OUT PDWORD Items, OUT PDWORD Default ) { BOOL bReturn = FALSE; DWORD i; // // Init our global variables // ASSERT_HEAP_IS_VALID(); *ReturnList = NULL; MYASSERT( LanguageList == NULL ); LanguageListSize = LANG_LIST_INCREMENT; LanguageList = MyMalloc( LanguageListSize * sizeof(OOBE_LOCALE_INFO)); if ( !LanguageList ) { goto exit; } LanguageIndex = 0; DefaultID = OptionalDefault ? OptionalDefault : GetUserDefaultLCID(); DefaultIndex = 0; EnumSystemLocales ( EnumLocalesProc , LCID_INSTALLED ); if ( LanguageList ) { // Success qsort( LanguageList, LanguageIndex, sizeof( OOBE_LOCALE_INFO ), LocaleCompare ); for (i=0; iName = MyMalloc( (lstrlen(pData) + 1) * sizeof(TCHAR) ); if ( !pGeoInfo->Name ) { SetupDestroyLanguageList( LanguageList, LanguageIndex ); LanguageList = NULL; return FALSE; } lstrcpy( pGeoInfo->Name, pData ); pGeoInfo->Id = GeoID; pGeoInfo->Installed = TRUE; if ( GeoID == (GEOID)DefaultID ) { DefaultIndex = LanguageIndex; } LanguageIndex++; return TRUE; } BOOL WINAPI SetupGetGeoOptions( IN DWORD OptionalDefault, OUT POOBE_LOCALE_INFO *ReturnList, OUT PDWORD Items, OUT PDWORD Default ) { BOOL bReturn = FALSE; DWORD i; // // Init our global variables // ASSERT_HEAP_IS_VALID(); *ReturnList = NULL; MYASSERT( LanguageList == NULL ); LanguageListSize = LANG_LIST_INCREMENT; LanguageList = MyMalloc( LanguageListSize * sizeof(OOBE_LOCALE_INFO)); if ( !LanguageList ) { goto exit; } LanguageIndex = 0; DefaultID = OptionalDefault ? OptionalDefault : GetUserGeoID( GEOCLASS_NATION ); DefaultIndex = 0; bReturn = EnumSystemGeoID( GEOCLASS_NATION, 0, EnumGeoInfoProc ); MYASSERT(bReturn); if ( bReturn && LanguageList ) { // Success qsort( LanguageList, LanguageIndex, sizeof( OOBE_LOCALE_INFO ), LocaleCompare ); for (i=0; iName = MyMalloc( (lstrlen(pData) + 1) * sizeof(TCHAR) ); if ( !pLocaleInfo->Name ) { SetupDestroyLanguageList( LanguageList, LanguageIndex ); LanguageList = NULL; goto exit; } lstrcpy( pLocaleInfo->Name, pData ); pLocaleInfo->Id = wcstoul( SubKeyName, NULL, 16 ); pLocaleInfo->Installed = TRUE; LanguageIndex++; } RegCloseKey( hLangKey ); hLangKey = NULL; qsort( LanguageList, LanguageIndex, sizeof( OOBE_LOCALE_INFO ), LocaleCompare ); for (i=0; iCountry, -1, pPhone2->Country, -1 ) - 2; } VOID WINAPI SetupDestroyPhoneList( ) { if ( PhoneList ) { MyFree( PhoneList ); } PhoneList = NULL; } VOID WINAPI SetupFreePhoneList(PPHONEENTRY PhoneList, DWORD cbEntries) { DWORD i; if ( PhoneList ) { for( i=0; i < cbEntries; i++ ) { if (PhoneList[i].Country) { GlobalFree(PhoneList[i].Country); } if (PhoneList[i].TollFreeNumber) { GlobalFree(PhoneList[i].TollFreeNumber); } if (PhoneList[i].TollNumber) { GlobalFree(PhoneList[i].TollNumber); } } GlobalFree(PhoneList); } PhoneList = NULL; } BOOL AddToPhoneList( LPCWSTR Item ) { PVOID NewList; DWORD ItemLength = lstrlen(Item); if ( !PhoneList ) { PhoneListLength = 0; PhoneListSize = 1024; PhoneList = MyMalloc( PhoneListSize * sizeof(TCHAR) ); if (!PhoneList) { return FALSE; } } else if ( PhoneListLength + ItemLength > PhoneListSize ) { PhoneListSize *= 2; NewList = MyRealloc( PhoneList, PhoneListSize * sizeof(TCHAR) ); if ( NewList ) { PhoneList = NewList; } else { MyFree(PhoneList); return FALSE; } } memcpy( PhoneList + PhoneListLength, Item, ItemLength * sizeof(TCHAR) ); PhoneListLength += ItemLength; return TRUE; } BOOL MakePhoneListForScript(PPHONEENTRY PhoneList, DWORD cbEntries) { BOOL bRet = FALSE; DWORD i; if ( PhoneList ) { for( i=0; i < cbEntries; i++ ) { if (!AddToPhoneList(PhoneList[i].Country) || !AddToPhoneList( TEXT("\t") ) || !AddToPhoneList(PhoneList[i].TollFreeNumber) || !AddToPhoneList( TEXT("\t") ) || !AddToPhoneList(PhoneList[i].TollNumber) || !AddToPhoneList( TEXT("\t") ) ) { goto ExitMakePhoneListForScript; } } bRet = TRUE; } ExitMakePhoneListForScript: return bRet; } BOOL AddItemToPhoneEntry(LPCWSTR Item, LPWSTR *pPointer) { BOOL bRet = FALSE; if ((Item) && (pPointer)) { *pPointer = (LPWSTR)GlobalAlloc(GPTR, (lstrlen(Item) + 1)*sizeof(TCHAR)); if (*pPointer) { lstrcpy(*pPointer, Item); bRet = TRUE; } } return bRet; } PTSTR WINAPI SetupReadPhoneList( PWSTR PhoneInfName ) { HINF PhoneInf = NULL; DWORD LineCount; DWORD ItemNo; LPCTSTR SectionName; INFCONTEXT InfContext; BOOL bSucceeded = FALSE; PPHONEENTRY pPhoneList = NULL; SetupDebugPrint( L"START: SetupReadPhoneList"); PhoneList = NULL; PhoneInf = SetupOpenInfFile( PhoneInfName, NULL, INF_STYLE_WIN4, NULL ); if( PhoneInf == INVALID_HANDLE_VALUE ) { return NULL; } SectionName = TEXT("IsoCodes"); LineCount = SetupGetLineCount( PhoneInf, SectionName ); if ( !LineCount ) { goto ReadPhoneListCleanup; } pPhoneList = (PPHONEENTRY)GlobalAlloc(GPTR, (int)(sizeof(PHONEENTRY) * LineCount)); if (!pPhoneList ) { goto ReadPhoneListCleanup; } ZeroMemory( pPhoneList, sizeof(PHONEENTRY) * LineCount ); for( ItemNo=0; ItemNo= _T('0') ) && ( *lpString <= _T('9') ) ) { lpString++; } } // Now walk till we get to the next number or we reach the end. // while ( ( *lpString ) && ( ( *lpString < _T('0') ) || ( *lpString > _T('9') ) ) ) { lpString++; } return lpString; } BOOL WINAPI SetupSetDisplay( LPCTSTR lpszUnattend, LPCTSTR lpszSection, LPCTSTR lpszResolutionKey, LPCTSTR lpszRefreshKey, DWORD dwMinWidth, DWORD dwMinHeight, DWORD dwMinBits ) { DEVMODE devmode; DWORD dwVal; TCHAR szText[256]; LPTSTR lpDisplay; BOOL bRet = TRUE; ZeroMemory(&devmode, sizeof(DEVMODE)); devmode.dmSize = sizeof(DEVMODE); // Check the current resolution, make sure it meets our mins. // if ( EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &devmode) ) { if ( devmode.dmPelsWidth < dwMinWidth ) { devmode.dmPelsWidth = dwMinWidth; devmode.dmFields |= DM_PELSWIDTH; } if ( devmode.dmPelsHeight < dwMinHeight ) { devmode.dmPelsHeight = dwMinHeight; devmode.dmFields |= DM_PELSHEIGHT; } if ( devmode.dmBitsPerPel < dwMinBits ) { devmode.dmBitsPerPel = dwMinBits; devmode.dmFields |= DM_BITSPERPEL; } } // Make sure they passed in an unattend and section to look in. // if ( lpszUnattend && *lpszUnattend && lpszSection && *lpszSection ) { // Now check in the winbom to see if they want to change the current resolution. // szText[0] = _T('\0'); if ( ( lpszResolutionKey ) && ( *lpszResolutionKey ) && ( GetPrivateProfileString(lpszSection, lpszResolutionKey, _T(""), szText, sizeof(szText) / sizeof(szText[0]), lpszUnattend) ) && ( szText[0] ) ) { bRet = FALSE; lpDisplay = NextNumber(szText, FALSE); if ( dwVal = (DWORD) _ttoi(lpDisplay) ) { devmode.dmFields |= DM_PELSWIDTH; devmode.dmPelsWidth = dwVal; } lpDisplay = NextNumber(lpDisplay, TRUE); if ( dwVal = (DWORD) _ttoi(lpDisplay) ) { devmode.dmFields |= DM_PELSHEIGHT; devmode.dmPelsHeight = dwVal; } lpDisplay = NextNumber(lpDisplay, TRUE); if ( dwVal = (DWORD) _ttoi(lpDisplay) ) { devmode.dmFields |= DM_BITSPERPEL; devmode.dmBitsPerPel = dwVal; } } // Now check in the winbom to see if they want to change the default refresh rate. // szText[0] = _T('\0'); if ( ( lpszRefreshKey ) && ( *lpszRefreshKey ) && ( GetPrivateProfileString(lpszSection, lpszRefreshKey, _T(""), szText, sizeof(szText) / sizeof(szText[0]), lpszUnattend) ) && ( szText[0] ) ) { bRet = FALSE; if ( dwVal = (DWORD) _ttoi(szText) ) { devmode.dmFields |= DM_DISPLAYFREQUENCY; devmode.dmDisplayFrequency = dwVal; } } } // If we have anything to change, change it now. // if ( devmode.dmFields ) { DWORD dwRet = ChangeDisplaySettings(&devmode, CDS_UPDATEREGISTRY | CDS_GLOBAL); switch ( dwRet ) { case DISP_CHANGE_SUCCESSFUL: case DISP_CHANGE_RESTART: bRet = TRUE; break; //case DISP_CHANGE_BADFLAGS: //case DISP_CHANGE_BADPARAM: //case DISP_CHANGE_FAILED: //case DISP_CHANGE_BADMODE //case DISP_CHANGE_NOTUPDATED: //bRet = FALSE; } } return bRet; } typedef struct _OEM_FINISH_APPS { LPTSTR szApp; LPTSTR szArgs; } OEM_FINISH_APPS; OEM_FINISH_APPS OEM_Finish_Apps[] = { { L"Rundll32.exe", L"fldrclnr.dll,Wizard_RunDLL silent"}, { NULL, NULL} // End of list. }; void RunOEMExtraTasks() { LPTSTR pApp = NULL; LPTSTR pArgs = NULL; DWORD dwSize; DWORD dwCode; int i; BEGIN_SECTION(L"RunOEMExtraTasks"); i = 0; while (OEM_Finish_Apps[i].szApp != NULL) { // Get the size we need to the expanded app dwSize = ExpandEnvironmentStrings( OEM_Finish_Apps[i].szApp , NULL, 0); if (dwSize) { pApp = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * dwSize); if (pApp) { ExpandEnvironmentStrings( OEM_Finish_Apps[i].szApp , pApp, dwSize); if (OEM_Finish_Apps[i].szArgs) { // Get the size we need to the expanded arguments dwSize = ExpandEnvironmentStrings( OEM_Finish_Apps[i].szArgs , NULL, 0); if (dwSize) { pArgs = (LPTSTR)GlobalAlloc(GPTR, sizeof(TCHAR) * dwSize); if (pArgs) { ExpandEnvironmentStrings( OEM_Finish_Apps[i].szArgs, pArgs, dwSize); } } } // Log what we will start if (pArgs) { SetupDebugPrint2(L"Start command :%s: with arguments :%s:", pApp, pArgs); } else { SetupDebugPrint1(L"Start command :%s: with no arguments", pApp); } // Start the app. dwCode = 0; if (pArgs) { InvokeExternalApplicationEx(pApp, pArgs, &dwCode, INFINITE, TRUE); } else { // If we don't have args. the first parameter is NULL InvokeExternalApplicationEx(NULL, pApp, &dwCode, INFINITE, TRUE); } } } if (pApp) { GlobalFree(pApp); pApp = NULL; } if (pArgs) { GlobalFree(pArgs); pArgs = NULL; } i++; } END_SECTION(L"RunOEMExtraTasks"); } static BOOL SetupCheckRegValue( IN HKEY hKey, IN LPTSTR lpszValueName, IN DWORD dwCompareValue ) { BOOL fRet = FALSE; DWORD dwData = 0, dwType, cbSize = sizeof(dwData); if ( ( ERROR_SUCCESS == RegQueryValueEx( hKey, lpszValueName, 0, &dwType, (LPBYTE) &dwData, &cbSize ) ) && ( REG_DWORD == dwType) && ( dwData == dwCompareValue ) ) { fRet = TRUE; } return fRet; } BOOL SetupGetInstallMode( OUT LPDWORD lpdwMode, OUT LPDWORD lpdwFlags ) { BOOL fRet = FALSE; HKEY hKeySetup; // // Make sure the caller is actually checking for something. // if ( lpdwMode || lpdwFlags ) { // // Also make sure we can open the "HKLM\System\Setup" key. // if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, TEXT("System\\Setup"), 0, KEY_READ, &hKeySetup ) ) { DWORD dwMode = SETUP_MODE_NONE, dwFlags = 0; BOOL fSetup, fOobe, fAudit, fMini, fFactory; // // Check all of the registry values we might care about... // fSetup = SetupCheckRegValue( hKeySetup, TEXT("SystemSetupInProgress"), 1 ); fOobe = SetupCheckRegValue( hKeySetup, TEXT("OobeInProgress"), 1 ); fAudit = SetupCheckRegValue( hKeySetup, TEXT("AuditInProgress"), 1 ); fMini = SetupCheckRegValue( hKeySetup, TEXT("MiniSetupInProgress"), 1 ); fFactory = SetupCheckRegValue( hKeySetup, TEXT("FactoryPreInstallInProgress"), 1 ); // // We are in OOBE if the OobeInProgress value is non-zero... // if ( fOobe ) { dwMode = SETUP_MODE_OOBE; if ( fMini ) { dwFlags |= SETUP_FLAG_OEM; } } else { // // We are in MiniSetup if the MiniSetupInProgress value is non-zero... // if ( fMini ) { dwMode = SETUP_MODE_MINI; dwFlags |= SETUP_FLAG_OEM; } else { // // We are in Audit mode if the AuditInProgress value is non-zero... // if ( fAudit ) { dwMode = SETUP_MODE_AUDIT; dwFlags |= (SETUP_FLAG_OEM | SETUP_FLAG_UNATTENDED); // // If the FactoryPreInstallInProgress flag is non-zero, then we are delaying PNP... // if ( fFactory ) { dwFlags |= SETUP_FLAG_DELAYPNP; } } else { // // We are in Setup if the SystemSetupInProgress and SetupType values are non-zero... // if ( fSetup ) { dwMode = SETUP_MODE_SETUP; } } } } // // Now put our values into the caller's buffers... // if ( lpdwMode ) { *lpdwMode = dwMode; } if ( lpdwFlags ) { *lpdwFlags = dwFlags; } // // We were able to open the Setup key... so return TRUE. // fRet = TRUE; // // We're done, so close the Setup key. // RegCloseKey( hKeySetup ); } } return fRet; }