windows-nt/Source/XPSP1/NT/base/ntsetup/syssetup/oobe.c

1610 lines
37 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#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; i<LanguageIndex; i++) {
if (LanguageList[i].Id == DefaultID) {
DefaultIndex = i;
break;
}
}
#if INTL_LIST_OPTIONS
for (i=0; i<LanguageIndex; i++) {
SetupDebugPrint2( L"Setup: SetupGetLocaleOptions|%x|%s",
LanguageList[i].Id,
LanguageList[i].Name );
}
#endif
*ReturnList = LanguageList;
LanguageList = NULL;
*Items = LanguageIndex;
*Default = DefaultIndex;
bReturn = TRUE;
}
exit:
ASSERT_HEAP_IS_VALID();
return bReturn;
}
BOOL
CALLBACK
EnumGeoInfoProc(
GEOID GeoID
)
{
TCHAR pData[128];
POOBE_LOCALE_INFO pGeoInfo;
//
// Add it to our global array
//
if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) {
SetupDestroyLanguageList( LanguageList, LanguageIndex );
LanguageList = NULL;
return FALSE;
}
if( !GetGeoInfo(
GeoID,
GEO_FRIENDLYNAME,
pData,
sizeof(pData) / sizeof(TCHAR),
0
)) {
// Skip this one.
MYASSERT(0);
return TRUE;
}
pGeoInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex;
pGeoInfo->Name = 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; i<LanguageIndex; i++) {
if (LanguageList[i].Id == DefaultID) {
DefaultIndex = i;
break;
}
}
#if INTL_LIST_OPTIONS
for (i=0; i<LanguageIndex; i++) {
SetupDebugPrint2( L"Setup: SetupGetGeoOptions|%d|%s",
LanguageList[i].Id,
LanguageList[i].Name );
}
#endif
bReturn = TRUE;
*ReturnList = LanguageList;
LanguageList = NULL;
*Items = LanguageIndex;
*Default = DefaultIndex;
}
exit:
ASSERT_HEAP_IS_VALID();
return bReturn;
}
BOOL
WINAPI
SetupGetKeyboardOptions(
IN DWORD OptionalDefault,
OUT POOBE_LOCALE_INFO *ReturnList,
OUT PDWORD Items,
OUT PDWORD Default
)
{
DWORD DefaultKeyboard;
DWORD i;
BOOL bReturn = FALSE;
TCHAR pData[128];
TCHAR Substitute[9];
POOBE_LOCALE_INFO pLocaleInfo;
DWORD rc;
HKEY hLangKey = NULL;
HKEY hLangSubKey = NULL;
DWORD Index;
TCHAR SubKeyName[9];
DWORD SubKeyNameLength;
DWORD DataSize;
DWORD Type;
//
// Initialize our 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;
// DefaultIndex = -1;
*Default = 0;
if (OptionalDefault) {
DefaultKeyboard = OptionalDefault;
} else {
//
// Lookup default keyboard in the registry
//
rc = RegOpenKeyEx( HKEY_USERS,
L".DEFAULT\\Keyboard Layout\\Preload",
0,
KEY_READ,
&hLangKey );
if( rc != NO_ERROR ) {
SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(.DEFAULT\\Keyboard Layout\\Preload) failed (%d)", rc );
MYASSERT(0);
goto exit;
}
DataSize = sizeof(pData);
rc = RegQueryValueEx(
hLangKey,
L"1",
NULL,
&Type,
(LPBYTE)pData,
&DataSize
);
RegCloseKey( hLangKey );
hLangKey = NULL;
if( rc != NO_ERROR ) {
SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegQueryValueEx(1) failed (%d)", rc );
MYASSERT(0);
goto exit;
}
DefaultKeyboard = wcstoul( pData, NULL, 16 );
//
// Now we look in the Substitutes key to see whether there is a
// substitute there.
//
if( RegOpenKeyEx( HKEY_USERS,
L".DEFAULT\\Keyboard Layout\\Substitutes",
0,
KEY_READ,
&hLangKey ) == NO_ERROR) {
DataSize = sizeof(Substitute);
if( (RegQueryValueEx( hLangKey,
pData,
NULL,
&Type,
(LPBYTE)Substitute,
&DataSize ) == NO_ERROR) &&
(Type == REG_SZ)
) {
DefaultKeyboard = wcstoul( Substitute, NULL, 16 );
}
RegCloseKey(hLangKey);
hLangKey = NULL;
}
}
rc = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
L"System\\CurrentControlSet\\Control\\Keyboard Layouts",
0,
KEY_ENUMERATE_SUB_KEYS | KEY_READ,
&hLangKey );
if( rc != NO_ERROR ) {
SetupDebugPrint1( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(System\\CurrentControlSet\\Control\\Keyboard Layouts) failed (%d)", rc );
goto exit;
}
for( Index = 0; ; Index++ ) {
SubKeyNameLength = sizeof(SubKeyName) / sizeof(TCHAR);
rc = RegEnumKeyEx( hLangKey,
Index,
SubKeyName,
&SubKeyNameLength,
NULL,
NULL,
NULL,
NULL );
//
// Did we error?
//
if( rc != ERROR_SUCCESS ) {
//
// Are we done?
//
if( rc != ERROR_NO_MORE_ITEMS ) {
SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegEnumKeyEx failed (%d). Index = %d", rc, Index );
MYASSERT(0);
}
break;
}
rc = RegOpenKeyEx( hLangKey,
SubKeyName,
0,
KEY_READ,
&hLangSubKey );
if( rc != NO_ERROR ) {
SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegOpenKeyEx(%s) failed (%d)", SubKeyName, rc );
MYASSERT(0);
continue;
}
DataSize = sizeof(pData);
rc = RegQueryValueEx(
hLangSubKey,
L"Layout Text",
NULL,
&Type,
(LPBYTE)pData,
&DataSize
);
RegCloseKey( hLangSubKey );
hLangSubKey = NULL;
if( rc != NO_ERROR ) {
SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions - RegQueryValueEx(Layout Text) for %s failed (%d)", SubKeyName, rc );
MYASSERT(0);
continue;
}
//
// Add it to our global array
//
if ( !CheckLangListSize( sizeof(OOBE_LOCALE_INFO) ) ) {
SetupDestroyLanguageList( LanguageList, LanguageIndex );
LanguageList = NULL;
goto exit;
}
pLocaleInfo = (POOBE_LOCALE_INFO)LanguageList + LanguageIndex;
pLocaleInfo->Name = 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; i<LanguageIndex; i++) {
if (LanguageList[i].Id == DefaultKeyboard) {
*Default = i;
break;
}
}
#if INTL_LIST_OPTIONS
for (i=0; i<LanguageIndex; i++) {
SetupDebugPrint2( L"Setup: SetupGetKeyboardOptions|%x|%s",
LanguageList[i].Id,
LanguageList[i].Name );
}
#endif
bReturn = TRUE;
*ReturnList = LanguageList;
LanguageList = NULL;
*Items = LanguageIndex;
exit:
if ( hLangKey ) {
RegCloseKey( hLangKey );
}
if ( hLangSubKey ) {
RegCloseKey( hLangSubKey );
}
ASSERT_HEAP_IS_VALID();
return bReturn;
}
BOOL
WINAPI
SetupSetIntlOptions(
DWORD LocationIndex,
DWORD LanguageIndex,
DWORD KeyboardIndex
)
{
WCHAR PathBuffer[MAX_PATH];
WCHAR KeyValue[128];
WCHAR CmdLine[MAX_PATH];
BOOL bResult;
SetupDebugPrint3(
L"SetupSetIntlOptions: Location = %d, Language = 0x%08x, Keyboard = 0x%08x",
LocationIndex,
LanguageIndex,
KeyboardIndex );
GetSystemDirectory( PathBuffer, MAX_PATH );
pSetupConcatenatePaths( PathBuffer, INTL_ANSWER_FILE, MAX_PATH, NULL );
DeleteFile( PathBuffer );
//
// Write language value
//
wsprintf(
KeyValue,
L"\"%08x\"",
LanguageIndex
);
WritePrivateProfileString(
INTL_LANG_SECTION,
INTL_LOCALE,
KeyValue,
PathBuffer
);
//
// Write keyboard value
//
wsprintf(
KeyValue,
L"\"%04x:%08x\"",
KeyboardIndex & 0x0000ffff,
KeyboardIndex
);
WritePrivateProfileString(
INTL_LANG_SECTION,
INTL_KEYBOARD,
KeyValue,
PathBuffer
);
//
// Call intl.cpl to do the work
//
wsprintf(
CmdLine,
L"/f:\"%s\" /s:\"%s\"",
PathBuffer,
LegacySourcePath
);
InvokeControlPanelApplet(L"intl.cpl",L"",0,CmdLine);
DeleteFile( PathBuffer );
//
// Set the GEO location
//
bResult = SetUserGeoID( LocationIndex );
if ( !bResult ) {
SetupDebugPrint1(
L"SetupSetIntlOptions: SetUserGeoID failed. Status = %d.",
GetLastError()
);
}
MYASSERT( bResult );
return bResult;
}
//+---------------------------------------------------------------------------
//
// Function: CompareCntryNameLookUpElements()
//
// Synopsis: Function to compare names used by sort
//
//+---------------------------------------------------------------------------
int __cdecl ComparePhoneEntry(const void *e1, const void *e2)
{
PPHONEENTRY pPhone1 = (PPHONEENTRY)e1;
PPHONEENTRY pPhone2 = (PPHONEENTRY)e2;
return CompareStringW(LOCALE_USER_DEFAULT, 0,
pPhone1->Country, -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++ )
{
GlobalFree(PhoneList[i].Country);
GlobalFree(PhoneList[i].TollFreeNumber);
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) );
} else if ( PhoneListLength + ItemLength > PhoneListSize ) {
PhoneListSize *= 2;
NewList = MyRealloc(
PhoneList,
PhoneListSize * sizeof(TCHAR)
);
if ( NewList ) {
PhoneList = NewList;
} else {
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;
}
for( ItemNo=0; ItemNo<LineCount; ItemNo++ ) {
if( SetupGetLineByIndex( PhoneInf, SectionName, ItemNo, &InfContext )) {
if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 4 ), &pPhoneList[ItemNo].Country ) ) {
goto ReadPhoneListCleanup;
}
if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 5 ), &pPhoneList[ItemNo].TollFreeNumber ) ) {
goto ReadPhoneListCleanup;
}
if ( !AddItemToPhoneEntry( pSetupGetField( &InfContext, 6 ), &pPhoneList[ItemNo].TollNumber ) ) {
goto ReadPhoneListCleanup;
}
}
}
// sort the array
qsort(pPhoneList, (int)LineCount,sizeof(PHONEENTRY),
ComparePhoneEntry);
// Convert the array into a TAB delimited list for script.
if (MakePhoneListForScript(pPhoneList,LineCount))
{
//
// Replace the final TAB with a NUL.
//
PhoneList[PhoneListLength-1] = '\0';
bSucceeded = TRUE;
}
ReadPhoneListCleanup:
if (pPhoneList)
{
SetupFreePhoneList(pPhoneList,LineCount);
}
SetupCloseInfFile( PhoneInf );
SetupDebugPrint( L"END: SetupReadPhoneList");
if ( bSucceeded ) {
return PhoneList;
} else {
SetupDestroyPhoneList();
return NULL;
}
}
//
// Read INF to map a TAPI country id to a 3 letter ISO code.
//
VOID
SetupMapTapiToIso (
IN PWSTR PhoneInfName,
IN DWORD dwCountryID,
OUT PWSTR szIsoCode
)
{
HINF PhoneInf;
WCHAR szCountryID[9];
BOOL bResult;
INFCONTEXT Context;
szIsoCode[0] = L'\0';
PhoneInf = SetupOpenInfFile( PhoneInfName, NULL, INF_STYLE_WIN4, NULL );
if( PhoneInf == INVALID_HANDLE_VALUE ) {
return;
}
wsprintf ( szCountryID, L"%d", dwCountryID);
bResult = SetupFindFirstLine (
PhoneInf,
L"TapiCodes",
szCountryID,
&Context
);
if (bResult) {
SetupGetStringField ( &Context, 1, szIsoCode, 4, NULL );
SetupDebugPrint2 ( L"SetupMapTapiToIso: %d mapped to %s", dwCountryID, szIsoCode );
}
SetupCloseInfFile( PhoneInf );
}
BOOL
WINAPI
SetupGetSetupInfo(
PWSTR Name, OPTIONAL
DWORD cbName,
PWSTR Org, OPTIONAL
DWORD cbOrg,
PWSTR OemId, OPTIONAL
DWORD cbOemId,
LPBOOL IntlSet OPTIONAL
)
{
BOOL b = TRUE;
HKEY hkey = NULL;
DWORD Size;
DWORD Type;
//
// Open the key if we need it
//
if( (Name || Org) &&
RegOpenKeyEx(HKEY_LOCAL_MACHINE,WinntSoftwareKeyName,0,
KEY_QUERY_VALUE,&hkey) != NO_ERROR) {
return FALSE;
}
//
// Get Name
//
if (Name) {
Size = cbName;
if((RegQueryValueEx(hkey,szRegisteredOwner,NULL,&Type,
(LPBYTE)Name,&Size) != NO_ERROR)
|| (Type != REG_SZ)
) {
b = FALSE;
}
}
//
// Get Org
//
if (Org) {
Size = cbOrg;
if((RegQueryValueEx(hkey,szRegisteredOrganization,NULL,&Type,
(LPBYTE)Org,&Size) != NO_ERROR)
|| (Type != REG_SZ)
) {
b = FALSE;
}
}
// TBD: figure out what this is for
if (OemId) {
OemId[0] = 0;
cbOemId = 0;
}
//
// Note: IntlSet is not used currently
//
if (hkey) {
RegCloseKey(hkey);
}
return b;
}
BOOL
WINAPI
SetupSetSetupInfo(
PCWSTR Name,
PCWSTR Org
)
{
BOOL b;
b = StoreNameOrgInRegistry( (PWSTR)Name, (PWSTR)Org );
return b;
}
BOOL
WINAPI
SetupSetAdminPassword(
PCWSTR OldPassword,
PCWSTR NewPassword
)
{
WCHAR AdminName[MAX_USERNAME+1];
BOOL Status;
GetAdminAccountName( AdminName );
Status = SetLocalUserPassword( AdminName, OldPassword, NewPassword );
if ( !Status ) {
SetupDebugPrint( L"SetupSetAdminPassword: SetLocalUserPassword failed.");
}
return Status;
}
VOID
WINAPI
SetupOobeInitDebugLog(
)
{
//
// Do no UI. Note that we must set OobeSetup before our first call to
// SetupDebugPrint.
//
OobeSetup = TRUE;
SetupDebugPrint( L"SetupOobeInitDebugLog" );
}
// Run initialization that is known not to requires services to run.
//
VOID
WINAPI
SetupOobeInitPreServices(
IN BOOL DoMiniSetupStuff
)
{
//
// Turn off logging.
//
// IsSetup = FALSE;
SetupDebugPrint( L"SetupOobeInitPreServices" );
if ( DoMiniSetupStuff ) {
//
// Act like the miniwizard (except with no UI)
//
MiniSetup = TRUE;
Preinstall = TRUE;
//
// Tell SetupAPI not to bother backing up files and not to verify
// that any INFs are digitally signed.
//
pSetupSetGlobalFlags(pSetupGetGlobalFlags()|PSPGF_NO_BACKUP|PSPGF_NO_VERIFY_INF);
CommonInitialization();
SetUpDataBlock();
InternalSetupData.CallSpecificData1 = 0;
#if 0
//
// We aren't going to do this for rev 1.
//
if( PnPReEnumeration ) {
//
// The user wants us to do PnP re-enumeration.
// Go do it.
//
InstallPnpDevices( hdlg,
SyssetupInf,
GetDlgItem(hdlg,IDC_PROGRESS1),
StartAtPercent,
StopAtPercent );
}
#endif
} else { // DoMiniSetupStuff
//
// Get handle to heap so we can periodically validate it.
//
#if DBG
g_hSysSetupHeap = GetProcessHeap();
#endif
}
}
// Run initialization that may or does require services.
//
VOID
WINAPI
SetupOobeInitPostServices(
IN BOOL DoMiniSetupStuff
)
{
InitializeExternalModules(
DoMiniSetupStuff,
&g_OcManagerContext
);
}
VOID
WINAPI
SetupOobeCleanup(
IN BOOL DoMiniSetupStuff
)
{
static FINISH_THREAD_PARAMS Context;
SetupDebugPrint( L"SetupOobeCleanup" );
if ( DoMiniSetupStuff ) {
RestoreBootTimeout();
Context.ThreadId = GetCurrentThreadId();
Context.OcManagerContext = g_OcManagerContext;
FinishThread( &Context );
}
}
// Resets the activation days (allowed 3 times only)
//
DWORD
SetupReArmWPA(
VOID
)
{
LPCSTR lpszReArmInterface = (LPCSTR)124;
typedef HRESULT (WINAPI* lpReArmEntryPoint) ();
HMODULE hRearmdll = NULL;
DWORD dwError = ERROR_SUCCESS;
hRearmdll = LoadLibraryA("licdll.dll");
if (hRearmdll)
{
lpReArmEntryPoint pReArmEntry =
(lpReArmEntryPoint) GetProcAddress(hRearmdll,lpszReArmInterface);
if (pReArmEntry)
{
//
// ValidateDigitalPid returns zero if success, otherwise its custom error code
//
HRESULT hr = (*pReArmEntry )();
if (FAILED(hr))
{
// If PID cannot be validated we should force activation/PID reentry.
SetupDebugPrint1(L"SETUP: Rollback WPA failed! HRESULT=%ld", hr);
dwError = (DWORD)hr;
}
else
SetupDebugPrint(L"SETUP: Rollback WPA succeeded.");
}
else {
SetupDebugPrint(L"SETUP: Failed to get WPA entry point!");
dwError = ERROR_INVALID_FUNCTION;
}
FreeLibrary (hRearmdll);
}
else {
SetupDebugPrint(L"SETUP: Failed to load WPA library!");
dwError = ERROR_FILE_NOT_FOUND;
}
// Return error code or success
//
return dwError;
}
// Once Windows is activated the Activate Windows shortcut is removed by msoobe.exe /a.
// If OEMs sysprep a machine they will need to re-activate Windows and the shortcut
// needs to be restored. Msoobe.exe cannot restore it because it does not
// run in server skus.
//
DWORD
SetupRestoreWPAShortcuts(
VOID
)
{
DWORD dwError = ERROR_SUCCESS;
HINF hinf;
hinf = SetupOpenInfFile(L"syssetup.inf",NULL,INF_STYLE_WIN4,NULL);
if(hinf != INVALID_HANDLE_VALUE)
{
if (SetupInstallFromInfSection(NULL,
hinf,
L"RESTORE_OOBE_ACTIVATE",
SPINST_PROFILEITEMS , //SPINST_ALL,
NULL,
NULL,
0,
NULL,
NULL,
NULL,
NULL) != 0)
{
// Success
SetupDebugPrint(L"SETUP: Restore Activation shortcut succeeded");
}
else
{
// Failure
dwError = GetLastError();
SetupDebugPrint1(L"SETUP: Restore Activation shortcut failed. GetLastError=%ld",dwError);
}
SetupCloseInfFile(hinf);
}
else
{
dwError = GetLastError();
SetupDebugPrint1(L"SETUP: Restore Activation shortcut failed to open syssetup.inf. GetLastError=%ld",dwError);
}
return dwError;
}
BOOL Activationrequired(VOID);
// Rollback the activation days and put back the activate windows shortcut(s). X86 only.
//
DWORD
WINAPI
SetupOobeBnk(
LPBYTE pDummy
)
{
DWORD dwError = ERROR_SUCCESS;
// Return if we failed to rollback so we don'put the shortcut back
// On volume license skus this always returns successful
//
if (ERROR_SUCCESS != (dwError = SetupReArmWPA()))
return dwError;
// If not activated, restore the shortcuts, or if we don't
// require activation (for volume license skus)
//
if (Activationrequired())
{
// Restore the Activate Windows shortcut(s)
//
dwError = SetupRestoreWPAShortcuts();
}
return dwError;
}
static
LPTSTR
NextNumber(
LPTSTR lpString,
BOOL bSkipFirst
)
{
// The first time we just want to walk past any non-numbers,
// we don't want to skip any numbers if they are right at the
// begining of the string.
//
if ( bSkipFirst )
{
// Walk past the first number in the string.
//
while ( ( *lpString >= _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");
}