|
|
#include "precomp.h"
#pragma hdrstop
#include <spidgen.h>
#include <pencrypt.h>
#include "digpid.h"
#define SETUP_TYPE_BUFFER_LEN 8
#define MAX_PID30_SITE 3
#define MAX_PID30_RPC 5
TCHAR Pid30Rpc[7] = TEXT("00000"); TCHAR Pid30Site[4];
LONG SourceInstallType = RetailInstall; BOOL EulaComplete = TRUE;
#ifdef PRERELEASE
BOOL NoPid = FALSE; #endif
//
// global variable used for subclassing.
//
WNDPROC OldPidEditProc[5]; WNDPROC OldEulaEditProc;
static BOOL PidMatchesMedia;
BOOL ValidatePid30( LPTSTR Edit1, LPTSTR Edit2, LPTSTR Edit3, LPTSTR Edit4, LPTSTR Edit5 );
void GetPID();
VOID ShowPidBox();
VOID GetSourceInstallType( OUT OPTIONAL LPDWORD InstallVariation ) /*++
Routine Description:
Determines the installation type (by looking in setupp.ini in the source directory)
Arguments:
Installvaration - one of the install variations defined in compliance.h
Returns:
none. sets SourceInstallType global variable.
--*/ { TCHAR TypeBuffer[256]; TCHAR FilePath[MAX_PATH]; DWORD InstallVar = COMPLIANCE_INSTALLVAR_UNKNOWN; TCHAR MPCode[6] = { -1 };
//
// SourcePaths is guaranteed to be valid at this point, so just use it
//
lstrcpy(FilePath,NativeSourcePaths[0]);
ConcatenatePaths (FilePath, SETUPP_INI, MAX_PATH );
GetPrivateProfileString(PID_SECTION, PID_KEY, TEXT(""), TypeBuffer, sizeof(TypeBuffer)/sizeof(TCHAR), FilePath);
if (lstrlen(TypeBuffer)==SETUP_TYPE_BUFFER_LEN) { if (lstrcmp(&TypeBuffer[5], OEM_INSTALL_RPC) == 0) { SourceInstallType = OEMInstall; InstallVar = COMPLIANCE_INSTALLVAR_OEM; } else if (lstrcmp(&TypeBuffer[5], SELECT_INSTALL_RPC) == 0) { SourceInstallType = SelectInstall; InstallVar = COMPLIANCE_INSTALLVAR_SELECT; // Since Select also requires a PID, don't zero the PID and call.
/* // get/set the pid.
{ TCHAR Temp[5][ MAX_PID30_EDIT + 1 ]; Temp[0][0] = TEXT('\0'); ValidatePid30(Temp[0],Temp[1],Temp[2],Temp[3],Temp[4]); }*/ } else if (lstrcmp(&TypeBuffer[5], MSDN_INSTALL_RPC) == 0) { SourceInstallType = RetailInstall; InstallVar = COMPLIANCE_INSTALLVAR_MSDN; } else { // defaulting
SourceInstallType = RetailInstall; InstallVar = COMPLIANCE_INSTALLVAR_CDRETAIL; }
StringCchCopy(Pid30Site, ARRAYSIZE(Pid30Site), &TypeBuffer[5]); StringCchCopy(Pid30Rpc, 6, TypeBuffer); Pid30Rpc[MAX_PID30_RPC] = (TCHAR)0; } else { //
// the retail install doesn't have an RPC code in the PID, so it's shorter in length
//
SourceInstallType = RetailInstall; InstallVar = COMPLIANCE_INSTALLVAR_CDRETAIL; }
if (lstrlen(TypeBuffer) >= 5) { StringCchCopy(MPCode, 6, TypeBuffer);
if ( (lstrcmp(MPCode, EVAL_MPC) == 0) || (lstrcmp(MPCode, DOTNET_EVAL_MPC) == 0)) { InstallVar = COMPLIANCE_INSTALLVAR_EVAL; } else if ((lstrcmp(MPCode, SRV_NFR_MPC) == 0) || (lstrcmp(MPCode, ASRV_NFR_MPC) == 0)) { InstallVar = COMPLIANCE_INSTALLVAR_NFR; } }
if (InstallVariation){ *InstallVariation = InstallVar; }
}
BOOL SetPid30( HWND hdlg, LONG ExpectedPidType, LPTSTR pProductId ) /*++
Routine Description:
sets the pid in the wizard page to the data specified in the answer file.
Arguments:
hdlg - window handle to pid dialog ExpectedPidType - InstallType enum identifying what sort of pid we're looking for. pProductId - string passed in from unattend file
Returns:
true on successfully setting the data, false means the data was missing or invalid. may set some the dialog text in the specified dialog
--*/ { TCHAR *ptr; TCHAR Temp[5][ MAX_PID30_EDIT + 1 ]; UINT i;
//
// make sure we were provided with a product ID
//
if (!pProductId || !*pProductId) { return(FALSE); }
if ( (ExpectedPidType != RetailInstall) && (ExpectedPidType != OEMInstall) && (ExpectedPidType != SelectInstall) ){ return(FALSE); }
//
// OEM and cd retail are the same case
// Check that the string specified on the unattended script file
// represents a valid 25 digit product id:
//
// 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5 - 1 2 3 4 5
// 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8
//
// As a first validation test, we verify that the length is correct,
// then we check if the "-" characters are in the correct place
//
// Note - we rely on left to right evaluation, so that we don't access
// pProductId[23] if length is only 5.
if( ( lstrlen( pProductId ) != (4+ MAX_PID30_EDIT*5)) || ( pProductId[5] != (TCHAR)TEXT('-') ) || ( pProductId[11] != (TCHAR)TEXT('-') ) || ( pProductId[17] != (TCHAR)TEXT('-') ) || ( pProductId[23] != (TCHAR)TEXT('-') ) ) { //
// The Pid in the unattended script file is invalid.
//
return(FALSE); }
for (i = 0;i<5;i++) { //
// quintet i
//
ptr = &pProductId[i*(MAX_PID30_EDIT+1)]; StringCchCopy(Temp[i], MAX_PID30_EDIT+1, ptr); Temp[i][MAX_PID30_EDIT] = (TCHAR)'\0';
}
//
// check with pid30 to make sure it's valid
//
if (!ValidatePid30(Temp[0],Temp[1],Temp[2],Temp[3],Temp[4])) { return(FALSE); }
//
// all of the specified pid items are valid, set the dialog text and return.
//
SetDlgItemText( hdlg,IDT_EDIT_PID1, Temp[0] ); SetDlgItemText( hdlg,IDT_EDIT_PID2, Temp[1] ); SetDlgItemText( hdlg,IDT_EDIT_PID3, Temp[2] ); SetDlgItemText( hdlg,IDT_EDIT_PID4, Temp[3] ); SetDlgItemText( hdlg,IDT_EDIT_PID5, Temp[4] );
return(TRUE);
}
//
// This function assumes CdKey points to a buffer of 16 bytes.
//
BOOL pGetCdKey ( OUT PBYTE CdKey ) { DIGITALPID dpid; DWORD type; DWORD rc; HKEY key; DWORD size = sizeof (dpid); BOOL b = FALSE;
rc = RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), &key); if (rc == ERROR_SUCCESS) { rc = RegQueryValueEx (key, TEXT("DigitalProductId"), NULL, &type, (LPBYTE)&dpid, &size); if (rc == ERROR_SUCCESS && type == REG_BINARY && size == sizeof(dpid)) { CopyMemory (CdKey, &dpid.abCdKey, sizeof (dpid.abCdKey)); b = TRUE; }
RegCloseKey (key); }
return b; }
const unsigned int iBase = 24;
//
// obtained from Jim Harkins 11/27/2000
//
void EncodePid3g( TCHAR *pchCDKey3Chars, // [OUT] pointer to 29+1 character Secure Product key
LPBYTE pbCDKey3) // [IN] pointer to 15-byte binary Secure Product Key
{ // Given the binary PID 3.0 we need to encode
// it into ASCII characters. We're only allowed to
// use 24 characters so we need to do a base 2 to
// base 24 conversion. It's just like any other
// base conversion execpt the numbers are bigger
// so we have to do the long division ourselves.
const TCHAR achDigits[] = TEXT("BCDFGHJKMPQRTVWXY2346789"); int iCDKey3Chars = 29; int cGroup = 0;
pchCDKey3Chars[iCDKey3Chars--] = TEXT('\0');
while (0 <= iCDKey3Chars) { unsigned int i = 0; // accumulator
int iCDKey3;
for (iCDKey3 = 15-1; 0 <= iCDKey3; --iCDKey3) { i = (i * 256) + pbCDKey3[iCDKey3]; pbCDKey3[iCDKey3] = (BYTE)(i / iBase); i %= iBase; }
// i now contains the remainder, which is the current digit
pchCDKey3Chars[iCDKey3Chars--] = achDigits[i];
// add '-' between groups of 5 chars
if (++cGroup % 5 == 0 && iCDKey3Chars > 0) { pchCDKey3Chars[iCDKey3Chars--] = TEXT('-'); } }
return; }
LRESULT CALLBACK PidEditSubProc( IN HWND hwnd, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam )
/*++
Routine Description:
Edit control subclass routine, sets the focus to the correct edit box when the user enters text. This routine assumes that the pid controls ids are in sequential order.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{ DWORD len, id;
//
// eat spaces
//
if ((msg == WM_CHAR) && (wParam == VK_SPACE)) { return(0); }
if ((msg == WM_CHAR)) { //
// First override: if we have the max characters in the current edit
// box, let's post the character to the next box and set focus to that
// control.
//
if ( ( (len = (DWORD)SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0)) == MAX_PID30_EDIT) && ((wParam != VK_DELETE) && (wParam != VK_BACK)) ) { //
// set the focus to the next edit control and post the character
// to that edit control
//
if ((id = GetDlgCtrlID(hwnd)) < IDT_EDIT_PID5 ) { DWORD start, end; SendMessage(hwnd, EM_GETSEL, (WPARAM)&start,(LPARAM)&end); if (start == end) { HWND hNext = GetDlgItem(GetParent(hwnd),id+1); SetFocus(hNext); SendMessage(hNext, EM_SETSEL, (WPARAM)-1,(LPARAM)-1); PostMessage( GetDlgItem(GetParent(hwnd),id+1), WM_CHAR, wParam, lParam ); return(0); } } //
// Second override: if the user hit's a delete key and they are at the
// the start of an edit box, then post the delete to the previous edit
// box.
//
} else if ( (len == 0) && ((id = GetDlgCtrlID(hwnd)) > IDT_EDIT_PID1) && ((wParam == VK_DELETE) || (wParam == VK_BACK) )) { //
// set the focus to the previous edit control and post the command
// to that edit control
//
HWND hPrev = GetDlgItem(GetParent(hwnd),id-1); SetFocus(hPrev); SendMessage(hPrev, EM_SETSEL, (WPARAM)MAX_PID30_EDIT-1,(LPARAM)MAX_PID30_EDIT); PostMessage( hPrev, WM_CHAR, wParam, lParam ); return(0); //
// Third override: if posting this message will give us the maximum
// characters in our in the current edit box, let's post the character
// to the next box and set focus to that control.
//
} else if ( (len == MAX_PID30_EDIT-1) && ((wParam != VK_DELETE) && (wParam != VK_BACK)) && ((id = GetDlgCtrlID(hwnd)) < IDT_EDIT_PID5) ) { DWORD start, end; SendMessage(hwnd, EM_GETSEL, (WPARAM)&start,(LPARAM)&end); if (start == end) { HWND hNext = GetDlgItem(GetParent(hwnd),id+1); //
// post the message to the edit box
//
CallWindowProc(OldPidEditProc[GetDlgCtrlID(hwnd)-IDT_EDIT_PID1],hwnd,msg,wParam,lParam); //
// now set the focus to the next edit control
//
SetFocus(hNext); SendMessage(hNext, EM_SETSEL, (WPARAM)-1,(LPARAM)-1); return(0); } } }
return(CallWindowProc(OldPidEditProc[GetDlgCtrlID(hwnd)-IDT_EDIT_PID1],hwnd,msg,wParam,lParam)); }
LRESULT CALLBACK EulaEditSubProc( IN HWND hwnd, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam )
/*++
Routine Description:
Edit control subclass routine, to avoid highlighting text when user tabs to the edit control.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{ static BOOL firstTime = TRUE; //
// For setsel messages, make start and end the same.
//
if((msg == EM_SETSEL) && ((LPARAM)wParam != lParam)) { lParam = wParam; }
//
// also, if the user hits tab, set focus to the correct radio button
// after the first time, the tab starts working like we want it to
//
if ((msg == WM_KEYDOWN) && (wParam == VK_TAB) && firstTime) { firstTime = FALSE; if (! ((IsDlgButtonChecked(GetParent(hwnd), IDYES) == BST_CHECKED) || (IsDlgButtonChecked(GetParent(hwnd), IDNO ) == BST_CHECKED))) { CheckDlgButton( GetParent(hwnd),IDYES, BST_CHECKED ); PostMessage(GetParent(hwnd),WM_COMMAND,IDYES,0); SetFocus(GetDlgItem(GetParent(hwnd),IDYES)); } }
return(CallWindowProc(OldEulaEditProc,hwnd,msg,wParam,lParam)); }
LPTSTR DoInitializeEulaText( HWND EditControl, PBOOL TranslationProblem ) /*++
Routine Description:
retrieves the text out of eula.txt, and sets up the eula subclass routine
Arguments:
EditControl - window handle for edit control TranslationProblem - if we fail, was is because we couldn't translate the text?
Returns:
pointer to eula text so that it can be freed, NULL on failure
--*/ { TCHAR EulaPath[MAX_PATH]; DWORD err; HANDLE hFile, hFileMapping; DWORD FileSize; BYTE *pbFile; LPTSTR EulaText = NULL; int i; // HFONT hFont;
// accoding to MSDN LOCALE_IDEFAULTANSICODEPAGE and LOCALE_IDEFAULTCODEPAGE
// are a max of 6 characters. Unsure of whether or not this includes ending
// null character, and we need a leading _T('.')
TCHAR cpName[8];
if (TranslationProblem) { *TranslationProblem = FALSE; }
//
// Map the file containing the licensing agreement.
//
lstrcpy(EulaPath, NativeSourcePaths[0]); //
// Make sure this operation succeeds. We don't want to possibly load the wrong eula.txt!
//
if (!ConcatenatePaths (EulaPath, TEXT("eula.txt"), MAX_PATH )) { goto c0; }
//
// Open and map the inf file.
//
err = MapFileForRead(EulaPath,&FileSize,&hFile,&hFileMapping,&pbFile); if(err != NO_ERROR) { goto c0; }
if(FileSize == 0xFFFFFFFF) { goto c1; }
EulaText = MALLOC((FileSize+1) * sizeof(TCHAR)); if(EulaText == NULL) { goto c1; }
#ifdef UNICODE
// the Eula will be in the language of the build, so we should set out locale
// to use the codepage that the source wants.
if(!GetLocaleInfo(SourceNativeLangID,LOCALE_IDEFAULTANSICODEPAGE,&cpName[1], ( ( sizeof( cpName ) / sizeof( TCHAR ) ) - 1 ) )){ if(!GetLocaleInfo(SourceNativeLangID,LOCALE_IDEFAULTCODEPAGE,&cpName[1], ( ( sizeof( cpName ) / sizeof( TCHAR ) ) - 1 ) )){ FREE(EulaText); EulaText = NULL; if (TranslationProblem){ *TranslationProblem = TRUE; } goto c1; } } cpName[0] = _T('.'); _tsetlocale(LC_ALL,cpName);
//
// Translate the text from ANSI to Unicode.
//
if(!mbstowcs(EulaText,pbFile,FileSize)){ FREE(EulaText); EulaText = NULL; if (TranslationProblem) { *TranslationProblem = TRUE; } goto c1; } _tsetlocale(LC_ALL,_T("")); /*
// we use mbstowcs instead of MultiByteToWideChar because mbstowcs will
// take into account the code page of the locale, which we've just set
// to be in relation to the language of the build
if (!MultiByteToWideChar ( CP_ACP, MB_ERR_INVALID_CHARS, pbFile, FileSize, EulaText, (FileSize+1) * sizeof(WCHAR) ) ) { FREE( EulaText ); EulaText = NULL; if (TranslationProblem) { *TranslationProblem = TRUE; } goto c1; } */ #else
CopyMemory(EulaText, pbFile, FileSize); #endif
//
// add the trailing NULL character
//
EulaText[FileSize] = 0;
//
// setup the eula subclass
//
OldEulaEditProc = (WNDPROC)GetWindowLongPtr(EditControl,GWLP_WNDPROC); SetWindowLongPtr(EditControl,GWLP_WNDPROC,(LONG_PTR)EulaEditSubProc);
#if 0
//
// need a fixed width font for the EULA so it's formatted correctly for all resolutions
//
hFont = GetStockObject(SYSTEM_FIXED_FONT); if (hFont) { SendMessage( EditControl, WM_SETFONT, hFont, TRUE ); } #endif
//
// set the actual text
//
SetWindowText(EditControl,(LPCTSTR)EulaText);
c1: UnmapFile( hFileMapping, pbFile ); CloseHandle( hFile ); c0: return EulaText; }
BOOL EulaWizPage( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) /*++
Routine Description:
Eula wizard page.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/ { BOOL b; PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER); static LPTSTR EulaText = NULL; static BOOL ShowEula = TRUE; BOOL TranslationProblem;
CHECKUPGRADEONLY();
switch(msg) {
case WM_INITDIALOG:
//
// check if the current language and target language match
//
ShowEula = IsLanguageMatched;
//
// Set eula radio buttons.
//
CheckDlgButton( hdlg,IDYES, BST_UNCHECKED ); CheckDlgButton( hdlg,IDNO, BST_UNCHECKED );
//
// setup the eula
//
EulaText = DoInitializeEulaText( GetDlgItem( hdlg, IDT_EULA_LIC_TEXT ), &TranslationProblem );
//
// if we couldn't read the eula, check if it was because of a translation problem,
// in which case we defer to textmode setup
//
if (!EulaText && TranslationProblem == TRUE) { ShowEula = FALSE; }
//
// if this fails, only bail out if we were going to show the EULA in the first place.
//
if (!EulaText && ShowEula) { MessageBoxFromMessage( hdlg, MSG_EULA_FAILED, FALSE, AppTitleStringId, MB_OK | MB_ICONERROR | MB_TASKMODAL );
Cancelled = TRUE; PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL);
b = FALSE; }
PropSheet_SetWizButtons( GetParent(hdlg), WizPage->CommonData.Buttons & (~PSWIZB_NEXT) );
//
// Set focus to radio button
//
SetFocus(GetDlgItem(hdlg,IDYES)); b = FALSE; break;
case WM_COMMAND: if (wParam == IDYES) { PropSheet_SetWizButtons( GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT ); b = TRUE; } else if (wParam == IDNO) { PropSheet_SetWizButtons( GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT ); b = TRUE; } else b = FALSE;
break; case WMX_ACTIVATEPAGE:
b = TRUE; if(wParam) { //
// don't activate the page in restart mode
//
if (Winnt32RestartedWithAF ()) { EulaComplete = TRUE; return FALSE; } //
// activation
//
if (!ShowEula) { //
// the target install language and the source language do not match up
// since this means that we might not have fonts installed for the current
// language, we'll just defer this to textmode setup where we know we have
// the correct fonts
//
EulaComplete = FALSE; if (IsDlgButtonChecked(hdlg, IDYES) == BST_CHECKED) { PropSheet_PressButton(GetParent(hdlg), (lParam == PSN_WIZBACK) ? PSBTN_BACK : PSBTN_NEXT); } else { CheckDlgButton( hdlg,IDYES, BST_CHECKED ); PropSheet_PressButton(GetParent(hdlg),PSBTN_NEXT); } return(b); }
//
// set state of next button if user has backed up and reentered this dialog
//
if ( (IsDlgButtonChecked(hdlg, IDYES) == BST_CHECKED) || (IsDlgButtonChecked(hdlg, IDNO ) == BST_CHECKED) ) { PropSheet_SetWizButtons( GetParent(hdlg), WizPage->CommonData.Buttons | PSWIZB_NEXT ); } else { SendMessage(GetParent(hdlg), PSM_SETWIZBUTTONS, 0, (LPARAM)WizPage->CommonData.Buttons & (~PSWIZB_NEXT)); }
//
// If unattended, check the value of OemSkipEula first (NTBUG9:492934)
//
if (UnattendedScriptFile) { TCHAR Buffer[10]; if (GetPrivateProfileString( WINNT_UNATTENDED, TEXT("OemSkipEula"), TEXT(""), Buffer, sizeof(Buffer)/sizeof(Buffer[0]), UnattendedScriptFile )) { EulaComplete = lstrcmpi(Buffer,WINNT_A_YES) == 0; return FALSE; } } //
// Advance page in unattended case.
//
UNATTENDED(PSBTN_NEXT);
} else { //
// deactivation
//
if (EulaText) FREE( EulaText ); EulaText = NULL;
if (IsDlgButtonChecked(hdlg, IDNO ) == BST_CHECKED) { Cancelled = TRUE; PropSheet_PressButton(GetParent(hdlg),PSBTN_CANCEL); }
}
break;
case WMX_UNATTENDED:
//
// necessary?
//
if (EulaText) FREE( EulaText ); EulaText = NULL; b = FALSE; break;
case WMX_I_AM_VISIBLE:
//
// Force repainting first to make sure the page is visible.
//
InvalidateRect(hdlg,NULL,FALSE); UpdateWindow(hdlg); b = TRUE; break;
default: b = FALSE; break; }
return(b); }
BOOL SelectPid30WizPage( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) /*++
Routine Description:
OEM Pid wizard page. depends on SourceInstallType being set correctly.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{ BOOL b; PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER); static BOOL bUnattendPid = FALSE; DWORD i;
switch(msg) {
case WM_INITDIALOG: GetPID();
// Disable the IME on the PID edit controls
for (i = 0; i < 5;i++) { ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL); }
//
// subclass the edit controls and limit the number of characters
//
for (i = 0; i < 5;i++) { SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0); OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC); SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc); }
//
// set focus to first pid entry
//
SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
b = FALSE; break;
case WMX_ACTIVATEPAGE:
CHECKUPGRADEONLY(); if (BuildCmdcons) { return(FALSE); }
// If we have an ecrypted PID and don't have the right crypto installed
// defer the PID validation until GUI mode
if (g_bDeferPIDValidation) { return FALSE; } b = TRUE; if(wParam) { //
// activation
//
#ifdef PRERELEASE
if (NoPid) { //
// don't show the page in this case
//
b = FALSE; break; } #endif
if (SourceInstallType != SelectInstall) { //
// don't show the page in this case
//
b = FALSE; break; } //
// don't activate the page in restart mode
//
if (Winnt32RestartedWithAF ()) { if (GetPrivateProfileString ( WINNT_USERDATA, WINNT_US_PRODUCTKEY, TEXT(""), ProductId, sizeof (ProductId) / sizeof (ProductId[0]), g_DynUpdtStatus->RestartAnswerFile )) { return FALSE; } } if (UnattendedOperation) { //
// make sure the pid is specified in the unattend file else we should stop
//
ShowPidBox(hdlg, SW_HIDE); if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId) ) { UNATTENDED(PSBTN_NEXT); } else { //
// a hack so that the correct wizard page is active when we put up our message box
//
bUnattendPid = TRUE; ShowPidBox(hdlg, SW_SHOW); PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
} }
} else { //
// deactivation. don't verify anything if they are backing up
//
if (!Cancelled && lParam != PSN_WIZBACK) { TCHAR tmpBuffer1[6]; TCHAR tmpBuffer2[6]; TCHAR tmpBuffer3[6]; TCHAR tmpBuffer4[6]; TCHAR tmpBuffer5[6]; GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
b = ValidatePid30( tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 );
if (!b) {
if (UnattendedOperation) { // We should not fail ValidatePid30 if we succeeded
// in the SetPid30 above. If we failed in SetPid30 above
// we should already be showing the pid boxes.
ShowPidBox(hdlg, SW_SHOW); } MessageBoxFromMessage(hdlg, bUnattendPid ? MSG_UNATTEND_OEM_PID_IS_INVALID : MSG_OEM_PID_IS_INVALID, FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1)); b = FALSE; } else { //
// user entered a valid PID, save it for later on.
//
wsprintf( ProductId, TEXT("%s-%s-%s-%s-%s"), tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 );
} }
}
break;
case WMX_I_AM_VISIBLE:
//
// Force repainting first to make sure the page is visible.
//
InvalidateRect(hdlg,NULL,FALSE); UpdateWindow(hdlg);
if (bUnattendPid) { MessageBoxFromMessage(hdlg,MSG_UNATTEND_OEM_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); bUnattendPid = FALSE; } b = TRUE; break;
default: b = FALSE; break; }
return(b); }
BOOL OemPid30WizPage( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) /*++
Routine Description:
OEM Pid wizard page. depends on SourceInstallType being set correctly.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/
{ BOOL b; PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER); static BOOL bUnattendPid = FALSE; DWORD i; // HFONT hFont;
switch(msg) {
case WM_INITDIALOG: GetPID();
// hFont = GetStockObject(SYSTEM_FIXED_FONT);
// Disable the IME on the PID edit controls
for (i = 0; i < 5;i++) { ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL); }
//
// subclass the edit controls and limit the number of characters
//
for (i = 0; i < 5;i++) { SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0); // SendDlgItemMessage(hdlg, IDT_EDIT_PID1+i, WM_SETFONT, hFont, TRUE );
OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC); SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc); }
//
// set focus to first pid entry
//
SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
b = FALSE; break;
case WM_COMMAND: b = FALSE; break;
case WMX_ACTIVATEPAGE:
CHECKUPGRADEONLY(); if (BuildCmdcons) { return(FALSE); }
// If we have an ecrypted PID and don't have the right crypto installed
// defer the PID validation until GUI mode
if (g_bDeferPIDValidation) { return FALSE; } b = TRUE; if(wParam) { //
// activation
//
#ifdef PRERELEASE
if (NoPid) { //
// don't show the page in this case
//
b = FALSE; break; } #endif
if (SourceInstallType != OEMInstall) { //
// don't show the page in this case
//
b = FALSE; break; } //
// don't activate the page in restart mode
//
if (Winnt32RestartedWithAF ()) { if (GetPrivateProfileString ( WINNT_USERDATA, WINNT_US_PRODUCTKEY, TEXT(""), ProductId, sizeof (ProductId) / sizeof (ProductId[0]), g_DynUpdtStatus->RestartAnswerFile )) { return FALSE; } } if (UnattendedOperation) { //
// make sure the pid is specified in the unattend file else we should stop
//
if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId) ) { UNATTENDED(PSBTN_NEXT); } else { //
// a hack so that the correct wizard page is active when we put up our message box
//
bUnattendPid = TRUE; PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0);
} }
#if 0
if (!Upgrade || (SourceInstallType != OEMInstall)) { //
// don't show the page in this case
//
b = FALSE; break; } else { NOTHING; } #endif
} else { //
// deactivation. don't verify anything if they are backing up
//
if (!Cancelled && lParam != PSN_WIZBACK) { TCHAR tmpBuffer1[6]; TCHAR tmpBuffer2[6]; TCHAR tmpBuffer3[6]; TCHAR tmpBuffer4[6]; TCHAR tmpBuffer5[6]; GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
b = ValidatePid30( tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 );
if (!b) { MessageBoxFromMessage(hdlg, bUnattendPid ? MSG_UNATTEND_OEM_PID_IS_INVALID : MSG_OEM_PID_IS_INVALID, FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1)); b = FALSE; } else { //
// user entered a valid PID, save it for later on.
//
wsprintf( ProductId, TEXT("%s-%s-%s-%s-%s"), tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 );
} }
}
break;
case WMX_I_AM_VISIBLE:
//
// Force repainting first to make sure the page is visible.
//
InvalidateRect(hdlg,NULL,FALSE); UpdateWindow(hdlg);
if (bUnattendPid) { MessageBoxFromMessage(hdlg,MSG_UNATTEND_OEM_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); bUnattendPid = FALSE; } b = TRUE; break;
default: b = FALSE; break; }
return(b); }
BOOL CdPid30WizPage( IN HWND hdlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam ) /*++
Routine Description:
CD Retail pid wizard page. depends on SourceInstallType being set correctly.
Arguments:
Standard window proc arguments.
Returns:
Message-dependent value.
--*/ { BOOL b; PPAGE_RUNTIME_DATA WizPage = (PPAGE_RUNTIME_DATA)GetWindowLongPtr(hdlg,DWLP_USER); static BOOL bUnattendPid = FALSE; DWORD i; // HFONT hFont;
switch(msg) {
case WM_INITDIALOG: GetPID();
// hFont = GetStockObject(SYSTEM_FIXED_FONT);
// Disable the IME on the PID edit controls
for (i = 0; i < 5;i++) { ImmAssociateContext(GetDlgItem(hdlg, IDT_EDIT_PID1+i), (HIMC)NULL); }
//
// subclass the edit controls and limit the number of characters
//
for (i = 0; i < 5;i++) { SendDlgItemMessage(hdlg,IDT_EDIT_PID1+i,EM_LIMITTEXT,MAX_PID30_EDIT,0); // SendDlgItemMessage(hdlg, IDT_EDIT_PID1+i, WM_SETFONT, hFont, TRUE );
OldPidEditProc[i] = (WNDPROC)GetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC); SetWindowLongPtr(GetDlgItem(hdlg, IDT_EDIT_PID1+i),GWLP_WNDPROC,(LONG_PTR)PidEditSubProc); }
//
// set focus to first pid entry
//
SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1));
b = FALSE; break;
case WM_COMMAND: //
// nothing to do here
//
b = FALSE;
break;
case WMX_ACTIVATEPAGE:
CHECKUPGRADEONLY(); if (BuildCmdcons) { return(FALSE); }
// If we have an ecrypted PID and don't have the right crypto installed
// defer the PID validation until GUI mode
if (g_bDeferPIDValidation) { return FALSE; } b = TRUE; if(wParam) { //
// activation
//
#ifdef PRERELEASE
if (NoPid) { //
// don't show the page in this case
//
b = FALSE; break; } #endif
if (SourceInstallType != RetailInstall) { //
// don't show the page in this case
//
b = FALSE; break; }
//
// don't activate the page in restart mode
//
if (Winnt32RestartedWithAF ()) { if (GetPrivateProfileString ( WINNT_USERDATA, WINNT_US_PRODUCTKEY, TEXT(""), ProductId, sizeof (ProductId) / sizeof (ProductId[0]), g_DynUpdtStatus->RestartAnswerFile )) { return FALSE; } }
if (UnattendedOperation) { //
// make sure the pid is specified in the unattend file else we should stop
//
if (SetPid30(hdlg,SourceInstallType, (LPTSTR)&ProductId)) { UNATTENDED(PSBTN_NEXT); } else { //
// a hack so that the correct wizard page is active when we put up our message box
//
bUnattendPid = TRUE; PostMessage(hdlg,WMX_I_AM_VISIBLE,0,0); } }
} else { //
// deactivation. don't verify anything if they are backing up
//
if ( !Cancelled && lParam != PSN_WIZBACK ) { TCHAR tmpBuffer1[6]; TCHAR tmpBuffer2[6]; TCHAR tmpBuffer3[6]; TCHAR tmpBuffer4[6]; TCHAR tmpBuffer5[6]; GetDlgItemText(hdlg,IDT_EDIT_PID1,tmpBuffer1,sizeof(tmpBuffer1)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID2,tmpBuffer2,sizeof(tmpBuffer2)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID3,tmpBuffer3,sizeof(tmpBuffer3)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID4,tmpBuffer4,sizeof(tmpBuffer4)/sizeof(TCHAR)); GetDlgItemText(hdlg,IDT_EDIT_PID5,tmpBuffer5,sizeof(tmpBuffer5)/sizeof(TCHAR));
b = ValidatePid30( tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 );
if (!b) { if (PidMatchesMedia){ MessageBoxFromMessage(hdlg, bUnattendPid ? MSG_UNATTEND_CD_PID_IS_INVALID :MSG_CD_PID_IS_INVALID, FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); } else { MessageBoxFromMessage(hdlg, UpgradeOnly ? MSG_CCP_MEDIA_FPP_PID : MSG_FPP_MEDIA_CCP_PID, FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); }
SetFocus(GetDlgItem(hdlg,IDT_EDIT_PID1)); b = FALSE; } else { //
// user entered a valid PID, save it for later on.
//
wsprintf( ProductId, TEXT("%s-%s-%s-%s-%s"), tmpBuffer1, tmpBuffer2, tmpBuffer3, tmpBuffer4, tmpBuffer5 ); } } }
break;
case WMX_I_AM_VISIBLE:
//
// Force repainting first to make sure the page is visible.
//
InvalidateRect(hdlg,NULL,FALSE); UpdateWindow(hdlg);
if (bUnattendPid) { MessageBoxFromMessage(hdlg,MSG_UNATTEND_CD_PID_IS_INVALID,FALSE,AppTitleStringId,MB_OK|MB_ICONSTOP); bUnattendPid = FALSE; }
b = TRUE; break;
default: b = FALSE; break; }
return(b); }
BOOL ValidatePidEx(LPTSTR PID, BOOL *pbStepup, BOOL *bSelect) { TCHAR Pid20Id[MAX_PATH]; BYTE Pid30[1024]={0}; TCHAR pszSkuCode[10]; BOOL fStepUp; // it seems that sku code really doesn't matter in winnt32, only syssetup
lstrcpy(pszSkuCode,TEXT("1797XYZZY"));
#if 0
wsprintf(DebugBuffer, TEXT("cd-key: %s\nRPC: %s\nOEM Key: %d"), PID, Pid30Rpc, (SourceInstallType == OEMInstall) ); OutputDebugString(DebugBuffer); #endif
*(LPDWORD)Pid30 = sizeof(Pid30);
if (!SetupPIDGenEx( PID, // [IN] 25-character Secure CD-Key (gets U-Cased)
Pid30Rpc, // [IN] 5-character Release Product Code
// note sku code is not kept around in winnt32, only syssetup.
pszSkuCode, // [IN] Stock Keeping Unit (formatted like 123-12345)
(SourceInstallType == OEMInstall), // [IN] is this an OEM install?
Pid20Id, // [OUT] PID 2.0, pass in ptr to 24 character array
Pid30, // [OUT] pointer to binary PID3 buffer. First DWORD is the length
pbStepup, // [OUT] optional ptr to Compliance Checking flag (can be NULL)
bSelect // [OUT] optional ptr to Volume Licensing flag (can be NULL)
)) { if (g_EncryptedPID) { GlobalFree(g_EncryptedPID); g_EncryptedPID = NULL; } return(FALSE); } return TRUE; }
BOOL ValidatePid30( LPTSTR Edit1, LPTSTR Edit2, LPTSTR Edit3, LPTSTR Edit4, LPTSTR Edit5 ) { TCHAR tmpProductId[MAX_PATH]={0}; TCHAR Pid20Id[MAX_PATH]; BYTE Pid30[1024]={0}; TCHAR pszSkuCode[10]; BOOL fStepUp; //TCHAR DebugBuffer[1024];
// until we know better, assume the Pid matches the media type
PidMatchesMedia = TRUE;
if (!Edit1 || !Edit2 || !Edit3 || !Edit4 || !Edit5) { return(FALSE); }
// Since we now need a PID in the select case too, fill in the string.
/*
if (SourceInstallType == SelectInstall){ tmpProductId[0] = TEXT('\0'); } else */ { StringCchPrintf( tmpProductId, ARRAYSIZE(tmpProductId), TEXT("%s-%s-%s-%s-%s"), Edit1, Edit2, Edit3, Edit4, Edit5 ); }
if (!ValidatePidEx(tmpProductId, &fStepUp, NULL)) { return(FALSE); } if (SourceInstallType != OEMInstall){ // we want OEM FPP and CCP keys to be accepted by either media. It seems like
// there will be OEM CCP media, but only FPP keys, which is why we aren't
// checking to make sure they match, as it's broken by design.
if (UpgradeOnly != fStepUp){ // user is trying to do a clean install with upgrade only media. Bad user, bad.
PidMatchesMedia = FALSE; return FALSE; } } return(TRUE); }
void GetPID() { if (!ProductId[0] && UnattendedOperation && !g_bDeferPIDValidation){ //
// On upgrades, reuse existing DPID
//
BYTE abCdKey[16]; BOOL bDontCare, bSelect; if (Upgrade && ISNT() && OsVersionNumber >= 501 && // PID format is compatible
pGetCdKey (abCdKey) ) { EncodePid3g (ProductId, abCdKey); if (ValidatePidEx(ProductId, &bDontCare, &bSelect) && bSelect) { HRESULT hr; if (g_EncryptedPID) { GlobalFree(g_EncryptedPID); g_EncryptedPID = NULL; } // Prepare the encrypted PID so that we can write it to winnt.sif
hr = PrepareEncryptedPID(ProductId, 1, &g_EncryptedPID); if (hr != S_OK) { DebugLog (Winnt32LogInformation, TEXT("PrepareEncryptedPID failed: <hr=0x%1!lX!>"), 0, hr); } } } } }
VOID ShowPidBox( IN HWND hdlg, IN int nCmdShow ) /*++
Routine Description:
shows or hide the pid boxes in the wizard page
Arguments:
hdlg - window handle to pid dialog nCmdShow - SW_SHOW or SW_HIDE
--*/ {
int i; for (i = 0; i<5; i++) { ShowWindow(GetDlgItem(hdlg,IDT_EDIT_PID1+i), nCmdShow); } }
|