1158 lines
32 KiB
C
1158 lines
32 KiB
C
#include "setupp.h"
|
||
#pragma hdrstop
|
||
|
||
//
|
||
// List of characters that are not legal in netnames.
|
||
//
|
||
PCWSTR IllegalNetNameChars = L"\"/\\[]:|<>+=;,?*";
|
||
|
||
//
|
||
// Computer name.
|
||
//
|
||
WCHAR ComputerName[DNS_MAX_LABEL_LENGTH+1];
|
||
WCHAR Win32ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
|
||
BOOL IsNameTruncated;
|
||
BOOL IsNameNonRfc;
|
||
|
||
//
|
||
// Copy disincentive name/organization strings.
|
||
//
|
||
WCHAR NameOrgName[MAX_NAMEORG_NAME+1];
|
||
WCHAR NameOrgOrg[MAX_NAMEORG_ORG+1];
|
||
|
||
#ifdef DOLOCALUSER
|
||
//
|
||
// User name and password
|
||
//
|
||
WCHAR UserName[MAX_USERNAME+1];
|
||
WCHAR UserPassword[MAX_PASSWORD+1];
|
||
BOOL CreateUserAccount = FALSE;
|
||
#endif // def DOLOCALUSER
|
||
|
||
//
|
||
// Administrator password.
|
||
//
|
||
WCHAR CurrentAdminPassword[MAX_PASSWORD+1];
|
||
WCHAR AdminPassword[MAX_PASSWORD+1];
|
||
BOOL EncryptedAdminPasswordSet = FALSE;
|
||
BOOL DontChangeAdminPassword = FALSE;
|
||
|
||
|
||
|
||
VOID
|
||
GenerateName(
|
||
OUT PWSTR GeneratedString,
|
||
IN DWORD DesiredStrLen
|
||
)
|
||
{
|
||
static DWORD Seed = 98725757;
|
||
static PCWSTR UsableChars = L"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||
|
||
//
|
||
// How many characters will come from the org/name string.
|
||
//
|
||
DWORD BaseLength = 8;
|
||
DWORD i,j;
|
||
DWORD UsableCount;
|
||
|
||
if( DesiredStrLen < BaseLength ) {
|
||
BaseLength = DesiredStrLen - 1;
|
||
}
|
||
|
||
|
||
if( NameOrgOrg[0] ) {
|
||
wcscpy( GeneratedString, NameOrgOrg );
|
||
} else if( NameOrgName[0] ) {
|
||
wcscpy( GeneratedString, NameOrgName );
|
||
} else {
|
||
wcscpy( GeneratedString, TEXT("X") );
|
||
for( i = 1; i < BaseLength; i++ ) {
|
||
wcscat( GeneratedString, TEXT("X") );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Get him upper-case for our filter...
|
||
//
|
||
CharUpper(GeneratedString);
|
||
|
||
//
|
||
// Now we want to put a '-' at the end
|
||
// of our GeneratedString. We'd like it to
|
||
// be placed in the BASE_LENGTH character, but
|
||
// the string may be shorter than that, or may
|
||
// even have a ' ' in it. Figure out where to
|
||
// put the '-' now.
|
||
//
|
||
for( i = 0; i <= BaseLength; i++ ) {
|
||
|
||
//
|
||
// Check for a short string.
|
||
//
|
||
if( (GeneratedString[i] == 0 ) ||
|
||
(GeneratedString[i] == L' ') ||
|
||
(!wcschr(UsableChars, GeneratedString[i])) ||
|
||
(i == BaseLength )
|
||
) {
|
||
GeneratedString[i] = L'-';
|
||
GeneratedString[i+1] = 0;
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Special case the scenario where we had no usable
|
||
// characters.
|
||
//
|
||
if( GeneratedString[0] == L'-' ) {
|
||
GeneratedString[0] = 0;
|
||
}
|
||
|
||
UsableCount = lstrlen(UsableChars);
|
||
Seed ^= GetCurrentTime();
|
||
srand( Seed );
|
||
|
||
j = lstrlen( GeneratedString );
|
||
for( i = j; i < DesiredStrLen; i++ ) {
|
||
GeneratedString[i] = UsableChars[rand() % UsableCount];
|
||
}
|
||
GeneratedString[i] = 0;
|
||
|
||
//
|
||
// In the normal case, the edit control in the wizard page
|
||
// has the ES_UPPER bit set. In the normal unattend case
|
||
// there is code in unattend.txt that uppercases the name.
|
||
// But if we get to generating the name then then the text
|
||
// in unattend.txt was * and we thus never had any text in
|
||
// the edit control or unattend.txt to be uppercased.
|
||
//
|
||
CharUpper(GeneratedString);
|
||
}
|
||
|
||
|
||
BOOL
|
||
ContainsDot(
|
||
IN PCWSTR NameToCheck
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determine whether a given name contains a '.'
|
||
|
||
Arguments:
|
||
|
||
NameToCheck - supplies name to be checked.
|
||
|
||
Return Value:
|
||
|
||
TRUE if the name contains a '.'; FALSE if not.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT Length,u;
|
||
|
||
if (!NameToCheck)
|
||
return FALSE;
|
||
|
||
Length = lstrlen(NameToCheck);
|
||
|
||
for (u = 0; u < Length; u++) {
|
||
if (NameToCheck[u] == L'.')
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
IsNetNameValid(
|
||
IN PCWSTR NameToCheck,
|
||
IN BOOL AlphaNumericOnly
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determine whether a given name is valid as a netname, such as
|
||
a computer name.
|
||
|
||
Arguments:
|
||
|
||
NameToCheck - supplies name to be checked.
|
||
|
||
Return Value:
|
||
|
||
TRUE if the name is valid; FALSE if not.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT Length,u;
|
||
|
||
Length = lstrlen(NameToCheck);
|
||
|
||
//
|
||
// Want at least one character.
|
||
//
|
||
if(!Length) {
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Leading/trailing spaces are invalid.
|
||
//
|
||
if((NameToCheck[0] == L' ') || (NameToCheck[Length-1] == L' ')) {
|
||
return(FALSE);
|
||
}
|
||
|
||
//
|
||
// Control chars are invalid, as are characters in the illegal chars list.
|
||
//
|
||
for(u=0; u<Length; u++) {
|
||
if (AlphaNumericOnly) {
|
||
if (NameToCheck[u] == L'-' || NameToCheck[u] == L'_') {
|
||
continue;
|
||
}
|
||
if (!iswalnum(NameToCheck[u])) {
|
||
return(FALSE);
|
||
}
|
||
} else {
|
||
if((NameToCheck[u] < L' ') || wcschr(IllegalNetNameChars,NameToCheck[u])) {
|
||
return(FALSE);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// We got here, name is ok.
|
||
//
|
||
return(TRUE);
|
||
}
|
||
|
||
BOOL SetIMEOpenStatus(
|
||
IN HWND hDlg,
|
||
IN BOOL bSetActive)
|
||
{
|
||
typedef HIMC (WINAPI* PFN_IMMGETCONTEXT)(HWND);
|
||
typedef BOOL (WINAPI* PFN_IMMSETOPENSTATUS)(HIMC,BOOL);
|
||
typedef BOOL (WINAPI* PFN_IMMGETOPENSTATUS)(HIMC);
|
||
typedef BOOL (WINAPI* PFN_IMMRELEASECONTEXT)(HWND,HIMC);
|
||
|
||
PFN_IMMGETCONTEXT PFN_ImmGetContext;
|
||
PFN_IMMSETOPENSTATUS PFN_ImmSetOpenStatus;
|
||
PFN_IMMGETOPENSTATUS PFN_ImmGetOpenStatus;
|
||
PFN_IMMRELEASECONTEXT PFN_ImmReleaseContext;
|
||
|
||
HIMC hIMC;
|
||
HKL hKL;
|
||
HMODULE hImmDll;
|
||
static BOOL bImeEnable=TRUE;
|
||
|
||
hKL = GetKeyboardLayout(0);
|
||
|
||
if ((HIWORD(HandleToUlong(hKL)) & 0xF000) != 0xE000) {
|
||
//
|
||
// not an IME, do nothing !
|
||
//
|
||
return TRUE;
|
||
}
|
||
|
||
hImmDll = GetModuleHandle(TEXT("IMM32.DLL"));
|
||
|
||
if (hImmDll == NULL) {
|
||
//
|
||
// weird case, if the kbd layout is an IME, then
|
||
// Imm32.dll should have already been loaded into process.
|
||
//
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
PFN_ImmGetContext = (PFN_IMMGETCONTEXT) GetProcAddress(hImmDll,"ImmGetContext");
|
||
if (PFN_ImmGetContext == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
PFN_ImmReleaseContext = (PFN_IMMRELEASECONTEXT) GetProcAddress(hImmDll,"ImmReleaseContext");
|
||
if (PFN_ImmReleaseContext == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
PFN_ImmSetOpenStatus = (PFN_IMMSETOPENSTATUS) GetProcAddress(hImmDll,"ImmSetOpenStatus");
|
||
if (PFN_ImmSetOpenStatus == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
PFN_ImmGetOpenStatus = (PFN_IMMGETOPENSTATUS) GetProcAddress(hImmDll,"ImmGetOpenStatus");
|
||
if (PFN_ImmGetOpenStatus == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Get Current Input Context.
|
||
//
|
||
hIMC = PFN_ImmGetContext(hDlg);
|
||
if (hIMC == NULL) {
|
||
return FALSE;
|
||
}
|
||
|
||
if (bSetActive) {
|
||
PFN_ImmSetOpenStatus(hIMC,bImeEnable);
|
||
}
|
||
else {
|
||
//
|
||
// Save Current Status.
|
||
//
|
||
bImeEnable = PFN_ImmGetOpenStatus(hIMC);
|
||
//
|
||
// Close IME.
|
||
//
|
||
PFN_ImmSetOpenStatus(hIMC,FALSE);
|
||
}
|
||
|
||
PFN_ImmReleaseContext(hDlg,hIMC);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
// returns TRUE if the name is valid, FALSE if it is not
|
||
BOOL ValidateNameOrgName (
|
||
WCHAR* pszName
|
||
)
|
||
{
|
||
WCHAR adminName[MAX_USERNAME+1];
|
||
WCHAR guestName[MAX_USERNAME+1];
|
||
|
||
LoadString(MyModuleHandle,IDS_ADMINISTRATOR,adminName,MAX_USERNAME+1);
|
||
LoadString(MyModuleHandle,IDS_GUEST,guestName,MAX_USERNAME+1);
|
||
|
||
if ( pszName == NULL )
|
||
return FALSE;
|
||
|
||
if(pszName[0] == 0)
|
||
return FALSE;
|
||
|
||
if(lstrcmpi(pszName,adminName) == 0 )
|
||
return FALSE;
|
||
|
||
if ( lstrcmpi(pszName,guestName) == 0 )
|
||
return FALSE;
|
||
|
||
return TRUE;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
INT_PTR
|
||
CALLBACK
|
||
NameOrgDlgProc(
|
||
IN HWND hdlg,
|
||
IN UINT msg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
{
|
||
NMHDR *NotifyParams;
|
||
|
||
switch(msg) {
|
||
|
||
case WM_INITDIALOG: {
|
||
|
||
//
|
||
// Limit text fields to maximum lengths
|
||
//
|
||
|
||
SendDlgItemMessage(hdlg,IDT_NAME,EM_LIMITTEXT,MAX_NAMEORG_NAME,0);
|
||
SendDlgItemMessage(hdlg,IDT_ORGANIZATION,EM_LIMITTEXT,MAX_NAMEORG_ORG,0);
|
||
|
||
//
|
||
// Set Initial Values
|
||
//
|
||
|
||
SetDlgItemText(hdlg,IDT_NAME,NameOrgName);
|
||
SetDlgItemText(hdlg,IDT_ORGANIZATION,NameOrgOrg);
|
||
|
||
break;
|
||
}
|
||
case WM_IAMVISIBLE:
|
||
//
|
||
// If an error occured during out INIT phase, show the box to the
|
||
// user so that they know there is a problem
|
||
//
|
||
MessageBoxFromMessage(hdlg,MSG_NO_NAMEORG_NAME,NULL,IDS_ERROR,
|
||
MB_OK | MB_ICONSTOP);
|
||
SetFocus(GetDlgItem(hdlg,IDT_NAME));
|
||
break;
|
||
case WM_SIMULATENEXT:
|
||
// Simulate the next button somehow
|
||
PropSheet_PressButton( GetParent(hdlg), PSBTN_NEXT);
|
||
break;
|
||
|
||
case WM_COMMAND:
|
||
if (HIWORD(wParam) == EN_CHANGE) {
|
||
if(LOWORD(wParam) == IDT_ORGANIZATION) {
|
||
GetDlgItemText( hdlg, IDT_ORGANIZATION, NameOrgOrg, MAX_NAMEORG_ORG+1);
|
||
#ifdef DOLOCALUSER
|
||
} else if(LOWORD(wParam) == IDT_NAME) {
|
||
GetDlgItemText( hdlg, IDT_NAME, NameOrgName, MAX_NAMEORG_NAME+1);
|
||
#endif
|
||
}
|
||
}
|
||
break;
|
||
|
||
|
||
case WMX_VALIDATE:
|
||
//
|
||
// lParam == 0 for no UI, or 1 for UI
|
||
// Return 1 for success, -1 for error.
|
||
//
|
||
|
||
GetDlgItemText(hdlg,IDT_ORGANIZATION,NameOrgOrg,MAX_NAMEORG_ORG+1);
|
||
GetDlgItemText(hdlg,IDT_NAME,NameOrgName,MAX_NAMEORG_NAME+1);
|
||
|
||
// JMH - NameOrgName cannot be "Administrator", "Guest" or "" (blank).
|
||
|
||
if(ValidateNameOrgName(NameOrgName) == FALSE) {
|
||
//
|
||
// Skip UI?
|
||
//
|
||
|
||
if (!lParam) {
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}
|
||
|
||
//
|
||
// Tell user he must at least enter a name, and
|
||
// don't allow next page to be activated.
|
||
//
|
||
if (Unattended) {
|
||
UnattendErrorDlg(hdlg,IDD_NAMEORG);
|
||
} // if
|
||
MessageBoxFromMessage(hdlg,MSG_NO_NAMEORG_NAME,NULL,IDS_ERROR,MB_OK|MB_ICONSTOP);
|
||
SetFocus(GetDlgItem(hdlg,IDT_NAME));
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_OK);
|
||
|
||
case WM_NOTIFY:
|
||
|
||
NotifyParams = (NMHDR *)lParam;
|
||
|
||
switch(NotifyParams->code) {
|
||
|
||
case PSN_SETACTIVE:
|
||
TESTHOOK(503);
|
||
BEGIN_SECTION(L"Personalize Your Software Page");
|
||
SetWizardButtons(hdlg,WizPageNameOrg);
|
||
|
||
if (Unattended) {
|
||
if (!UnattendSetActiveDlg(hdlg,IDD_NAMEORG)) {
|
||
break;
|
||
}
|
||
}
|
||
// Page becomes active, make page visible.
|
||
SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
|
||
//
|
||
// Set focus on the name edit control.
|
||
//
|
||
SetFocus(GetDlgItem(hdlg,IDT_NAME));
|
||
|
||
//
|
||
// Open/Close IME.
|
||
//
|
||
SetIMEOpenStatus(hdlg,TRUE);
|
||
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
case PSN_WIZFINISH:
|
||
|
||
UnattendAdvanceIfValid (hdlg); // see WMX_VALIDATE
|
||
break;
|
||
|
||
case PSN_KILLACTIVE:
|
||
WizardKillHelp(hdlg);
|
||
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FALSE);
|
||
|
||
//
|
||
// Close IME.
|
||
//
|
||
SetIMEOpenStatus(hdlg,FALSE);
|
||
|
||
END_SECTION(L"Personalize Your Software Page");
|
||
break;
|
||
|
||
case PSN_HELP:
|
||
WizardBringUpHelp(hdlg,WizPageNameOrg);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
return(FALSE);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
INT_PTR
|
||
CALLBACK
|
||
ComputerNameDlgProc(
|
||
IN HWND hdlg,
|
||
IN UINT msg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
{
|
||
NMHDR *NotifyParams;
|
||
DWORD err, Win32NameSize = MAX_COMPUTERNAME_LENGTH + 1;
|
||
static BOOL EncryptedAdminPasswordBad = FALSE;
|
||
static BOOL bPersonal = FALSE;
|
||
|
||
switch(msg) {
|
||
|
||
case WM_INITDIALOG: {
|
||
|
||
bPersonal = ( GetProductFlavor() == 4);
|
||
//
|
||
// Limit text to maximum length
|
||
//
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_LIMITTEXT,DNS_MAX_LABEL_LENGTH,0);
|
||
if (!bPersonal)
|
||
{
|
||
SendDlgItemMessage(hdlg,IDT_EDIT2,EM_LIMITTEXT,MAX_PASSWORD,0);
|
||
SendDlgItemMessage(hdlg,IDT_EDIT3,EM_LIMITTEXT,MAX_PASSWORD,0);
|
||
}
|
||
//
|
||
// Set the Edit boxes to the initial text
|
||
//
|
||
|
||
//
|
||
// Generate a computer name if we're unattended and
|
||
// the user has requested a random name, or if we're
|
||
// attended.
|
||
//
|
||
|
||
GenerateName( ComputerName, 15 );
|
||
if( (Unattended) &&
|
||
(UnattendAnswerTable[UAE_COMPNAME].Answer.String) &&
|
||
(UnattendAnswerTable[UAE_COMPNAME].Answer.String[0] == L'*') ) {
|
||
//
|
||
// The unattend engine has asked us to generate a Computer
|
||
// name. Let's write the data back into the unattend
|
||
// database.
|
||
//
|
||
MyFree( UnattendAnswerTable[UAE_COMPNAME].Answer.String );
|
||
UnattendAnswerTable[UAE_COMPNAME].Answer.String = ComputerName;
|
||
}
|
||
|
||
if (!bPersonal)
|
||
{
|
||
if(DontChangeAdminPassword) {
|
||
EnableWindow(GetDlgItem(hdlg,IDT_EDIT2),FALSE);
|
||
EnableWindow(GetDlgItem(hdlg,IDT_EDIT3),FALSE);
|
||
} else {
|
||
SetDlgItemText(hdlg,IDT_EDIT2,AdminPassword);
|
||
SetDlgItemText(hdlg,IDT_EDIT3,AdminPassword);
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
case WM_IAMVISIBLE:
|
||
MessageBoxFromMessage(
|
||
hdlg,
|
||
ComputerName[0] ? MSG_BAD_COMPUTER_NAME1 : MSG_BAD_COMPUTER_NAME2,
|
||
NULL,
|
||
IDS_ERROR,MB_OK|MB_ICONSTOP);
|
||
break;
|
||
|
||
case WM_SIMULATENEXT:
|
||
// Simulate the next button somehow
|
||
PropSheet_PressButton( GetParent(hdlg), PSBTN_NEXT);
|
||
break;
|
||
|
||
case WMX_VALIDATE:
|
||
//
|
||
// lParam == 0 for no UI, or 1 for UI
|
||
// Return 1 for success, -1 for error.
|
||
//
|
||
|
||
IsNameNonRfc = FALSE;
|
||
IsNameTruncated = FALSE;
|
||
|
||
GetDlgItemText(hdlg,IDT_EDIT1,ComputerName,DNS_MAX_LABEL_LENGTH+1);
|
||
|
||
// StrTrim removes both leading and trailing spaces
|
||
StrTrim(ComputerName, TEXT(" "));
|
||
|
||
if (ContainsDot(ComputerName)) {
|
||
err = ERROR_INVALID_NAME;
|
||
} else {
|
||
err = DnsValidateDnsName_W(ComputerName);
|
||
if (err == DNS_ERROR_NON_RFC_NAME) {
|
||
IsNameNonRfc = TRUE;
|
||
err = ERROR_SUCCESS;
|
||
}
|
||
|
||
if(err == ERROR_SUCCESS) {
|
||
//The name is a valid DNS name. Now verify that it is
|
||
//also a valid WIN32 computer name.
|
||
|
||
if (!DnsHostnameToComputerNameW(ComputerName,
|
||
Win32ComputerName,
|
||
&Win32NameSize) ||
|
||
!IsNetNameValid(Win32ComputerName, FALSE)) {
|
||
err = ERROR_INVALID_NAME;
|
||
}
|
||
else {
|
||
if (Win32NameSize < (UINT)lstrlen(ComputerName) ) {
|
||
//The DNSName was truncated to get a Win32 ComputerName.
|
||
IsNameTruncated = TRUE;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// If the name has non-RFC characters or if it was truncated, warn
|
||
// user if it is not an unattended install and we have GUI.
|
||
//
|
||
if (err == ERROR_SUCCESS && !Unattended && lParam) {
|
||
|
||
if (IsNameNonRfc) {
|
||
//ComputerName has non-standard characters.
|
||
if (MessageBoxFromMessage(
|
||
hdlg,
|
||
MSG_DNS_NON_RFC_NAME,
|
||
NULL,
|
||
IDS_SETUP,MB_YESNO|MB_ICONWARNING,
|
||
ComputerName) == IDNO) {
|
||
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_SETSEL,0,-1);
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
|
||
}
|
||
}
|
||
|
||
if (IsNameTruncated) {
|
||
//The computer name was truncated.
|
||
if (MessageBoxFromMessage(
|
||
hdlg,
|
||
MSG_DNS_NAME_TRUNCATED,
|
||
NULL,
|
||
IDS_SETUP,MB_YESNO|MB_ICONWARNING,
|
||
ComputerName, Win32ComputerName) == IDNO) {
|
||
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_SETSEL,0,-1);
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
if(err == ERROR_SUCCESS) {
|
||
WCHAR pw1[MAX_PASSWORD+1],pw2[MAX_PASSWORD+1];
|
||
if (bPersonal)
|
||
{
|
||
// if we are in personal we are done.
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_OK);
|
||
}
|
||
//
|
||
// Good computer name. Now make sure passwords match.
|
||
//
|
||
GetDlgItemText(hdlg,IDT_EDIT2,pw1,MAX_PASSWORD+1);
|
||
GetDlgItemText(hdlg,IDT_EDIT3,pw2,MAX_PASSWORD+1);
|
||
if(lstrcmp(pw1,pw2)) {
|
||
//
|
||
// Skip UI?
|
||
//
|
||
|
||
if (!lParam) {
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}
|
||
|
||
//
|
||
//
|
||
// Inform user of password mismatch, and don't allow next page
|
||
// to be activated.
|
||
//
|
||
if (Unattended) {
|
||
UnattendErrorDlg(hdlg, IDD_COMPUTERNAME);
|
||
}
|
||
MessageBoxFromMessage(hdlg,MSG_PW_MISMATCH,NULL,IDS_ERROR,MB_OK|MB_ICONSTOP);
|
||
SetDlgItemText(hdlg,IDT_EDIT2,L"");
|
||
SetDlgItemText(hdlg,IDT_EDIT3,L"");
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT2));
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
|
||
} else {
|
||
|
||
WCHAR adminName[MAX_USERNAME+1];
|
||
|
||
GetAdminAccountName( adminName );
|
||
|
||
|
||
//
|
||
// Process the encrypted password if
|
||
// 1) We are unattended and
|
||
// 2) The EncryptedAdminPassword key is "Yes" in the unatttend file and
|
||
// 3) We are not back here after setting it - i.e. via the back button etc.
|
||
// 4) We are not back here after failing to set it once.
|
||
|
||
|
||
if( Unattended && IsEncryptedAdminPasswordPresent() &&
|
||
!DontChangeAdminPassword && !EncryptedAdminPasswordBad){
|
||
|
||
// Logging is done inside the call to ProcessEncryptedAdminPassword
|
||
|
||
if(!(ProcessEncryptedAdminPassword(adminName))){
|
||
|
||
EncryptedAdminPasswordBad = TRUE;
|
||
|
||
// Page becomes active, make page visible.
|
||
SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
|
||
// Inform the user and enable the password fields
|
||
|
||
UnattendErrorDlg(hdlg, IDD_COMPUTERNAME);
|
||
MessageBoxFromMessage(hdlg,MSG_CHANGING_PW_FAIL,NULL,IDS_ERROR,MB_OK|MB_ICONSTOP, adminName );
|
||
SetDlgItemText(hdlg,IDT_EDIT2,L"");
|
||
SetDlgItemText(hdlg,IDT_EDIT3,L"");
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT2));
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}else{
|
||
EncryptedAdminPasswordSet = TRUE;
|
||
|
||
//
|
||
// Set DontChangeAdminPassword to avoid the user from ever trying to
|
||
// reset the password using the dialog. This is needed in the case where the
|
||
// unattend fails, say, in the next page and the user gets here using the back button.
|
||
//
|
||
|
||
DontChangeAdminPassword = TRUE;
|
||
}
|
||
|
||
|
||
}else{
|
||
|
||
|
||
|
||
//
|
||
// They match; allow next page to be activated.
|
||
//
|
||
if (Unattended && pw1[0] == L'*') {
|
||
pw1[0] = L'\0';
|
||
}
|
||
|
||
|
||
// Set administrator password. We need to do some checking here though.
|
||
// There are 3 scenarios that can occur in mini-setup:
|
||
// 1. The OEM doesn't want to have the admin password changed.
|
||
// In this case, he's set OEMAdminPassword = "NoChange". If that's
|
||
// what we find, we don't assign the password. Remember that this
|
||
// system has already been installed, so there's already an admin
|
||
// password.
|
||
// 2. The OEM wants to set the admin password to a specific string.
|
||
// In this case, he's set OEMAdminPassword = <some quoted word>.
|
||
// If this is the case, we've already caught this string in the
|
||
// wizard page.
|
||
// 3. The OEM wants to let the user set the admin password. In this
|
||
// case, there's no OEMAdminpassword in the answer file. If this
|
||
// is the case, we've already caught this and gotten a password
|
||
// from the user in the wizard page.
|
||
//
|
||
// The good news is that the unattend engine has already looked
|
||
// for a password in the unattend file called "NoChange" and has
|
||
// set a global called "DontChangeAdminPassword" to indicate.
|
||
|
||
|
||
|
||
if(!DontChangeAdminPassword) {
|
||
|
||
lstrcpy(AdminPassword,pw1);
|
||
|
||
//
|
||
// The user may have changed the name of the Administrator
|
||
// account. We'll call some special code to retrieve the
|
||
// name on the account. This is really only needed in the
|
||
// case of a sysprep run, but it can't hurt to do it always.
|
||
//
|
||
// In the Win9x case their code in winnt32 generates a random
|
||
// password and passes it to us through the unattend file and
|
||
// so we set it here and do the right thing.
|
||
|
||
// For Minisetup the behavior for now is to silently fail setting
|
||
// the admin password if there was an existing Password on the system.
|
||
// WE only allow setting the admin password from NULL i.e. one time change.
|
||
// In any other case we log the error and move on.
|
||
//
|
||
|
||
|
||
|
||
if(!SetLocalUserPassword(adminName,CurrentAdminPassword,AdminPassword) && !MiniSetup) {
|
||
|
||
SetupDebugPrint( L"SETUP: SetLocalUserPassword failed" );
|
||
// Page becomes active, make page visible.
|
||
SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
|
||
|
||
MessageBoxFromMessage(hdlg,MSG_CHANGING_PW_FAIL,NULL,IDS_ERROR,MB_OK|MB_ICONSTOP, adminName );
|
||
SetDlgItemText(hdlg,IDT_EDIT2,L"");
|
||
SetDlgItemText(hdlg,IDT_EDIT3,L"");
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT2));
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
|
||
}
|
||
//
|
||
// Now store this so that we work fine when the user comes to this page by hitting "Back".
|
||
//
|
||
lstrcpy( CurrentAdminPassword, AdminPassword );
|
||
|
||
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
//
|
||
// Skip UI?
|
||
//
|
||
|
||
if (!lParam) {
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}
|
||
|
||
//
|
||
// Inform user of bogus computer name, and don't allow next page
|
||
// to be activated.
|
||
//
|
||
if (Unattended) {
|
||
UnattendErrorDlg(hdlg, IDD_COMPUTERNAME);
|
||
}
|
||
MessageBoxFromMessage(
|
||
hdlg,
|
||
ComputerName[0] ? MSG_BAD_COMPUTER_NAME1 : MSG_BAD_COMPUTER_NAME2,
|
||
NULL,
|
||
IDS_ERROR,MB_OK|MB_ICONSTOP
|
||
);
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_SETSEL,0,-1);
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
}
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_OK);
|
||
|
||
case WM_NOTIFY:
|
||
|
||
NotifyParams = (NMHDR *)lParam;
|
||
|
||
switch(NotifyParams->code) {
|
||
|
||
case PSN_SETACTIVE:
|
||
TESTHOOK(504);
|
||
|
||
BEGIN_SECTION(L"Computer Name Page");
|
||
SetWizardButtons(hdlg,WizPageComputerName);
|
||
|
||
//
|
||
// Load ComputerName because it may have been set when the user
|
||
// entered the organization name.
|
||
//
|
||
SetDlgItemText(hdlg,IDT_EDIT1,ComputerName);
|
||
|
||
if(Unattended && !UnattendSetActiveDlg(hdlg,IDD_COMPUTERNAME)) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Post ourselves a message we'll get once displayed.
|
||
//
|
||
PostMessage(hdlg,WM_USER,0,0);
|
||
break;
|
||
|
||
case PSN_WIZBACK:
|
||
//
|
||
// Save ComputerName because we're going to load it into the dialog
|
||
// again when we come back.
|
||
//
|
||
GetDlgItemText(hdlg,IDT_EDIT1,ComputerName,DNS_MAX_LABEL_LENGTH+1);
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
case PSN_WIZFINISH:
|
||
UnattendAdvanceIfValid (hdlg); // see WMX_VALIDATE
|
||
break;
|
||
|
||
case PSN_KILLACTIVE:
|
||
WizardKillHelp(hdlg);
|
||
SetWindowLongPtr(hdlg, DWLP_MSGRESULT, FALSE);
|
||
END_SECTION(L"Computer Name Page");
|
||
break;
|
||
|
||
case PSN_HELP:
|
||
WizardBringUpHelp(hdlg,WizPageComputerName);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
case WM_USER:
|
||
// Page becomes active, make page visible.
|
||
SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
|
||
//
|
||
// Select the computer name string and set focus to it.
|
||
//
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_SETSEL,0,-1);
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
break;
|
||
|
||
default:
|
||
return(FALSE);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
|
||
#ifdef DOLOCALUSER
|
||
BOOL
|
||
CheckUserAccountData(
|
||
IN HWND hdlg,
|
||
OUT BOOL ValidateOnly
|
||
)
|
||
{
|
||
WCHAR userName[MAX_USERNAME+1];
|
||
WCHAR pw1[MAX_PASSWORD+1];
|
||
WCHAR pw2[MAX_PASSWORD+1];
|
||
WCHAR adminName[MAX_USERNAME+1];
|
||
WCHAR guestName[MAX_USERNAME+1];
|
||
UINT MessageId;
|
||
|
||
FocusId = 0;
|
||
|
||
//
|
||
// Load names of built-in accounts.
|
||
//
|
||
LoadString(MyModuleHandle,IDS_ADMINISTRATOR,adminName,MAX_USERNAME+1);
|
||
LoadString(MyModuleHandle,IDS_GUEST,guestName,MAX_USERNAME+1);
|
||
|
||
//
|
||
// Fetch data user typed in for username and password.
|
||
//
|
||
GetDlgItemText(hdlg,IDT_EDIT1,userName,MAX_USERNAME+1);
|
||
GetDlgItemText(hdlg,IDT_EDIT2,pw1,MAX_PASSWORD+1);
|
||
GetDlgItemText(hdlg,IDT_EDIT3,pw2,MAX_PASSWORD+1);
|
||
|
||
if(lstrcmpi(userName,adminName) && lstrcmpi(userName,guestName)) {
|
||
if(userName[0]) {
|
||
if(IsNetNameValid(userName,FALSE)) {
|
||
if(lstrcmp(pw1,pw2)) {
|
||
//
|
||
// Passwords don't match.
|
||
//
|
||
MessageId = MSG_PW_MISMATCH;
|
||
SetDlgItemText(hdlg,IDT_EDIT2,L"");
|
||
SetDlgItemText(hdlg,IDT_EDIT3,L"");
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT2));
|
||
} else {
|
||
//
|
||
// Name is non-empty, is not a built-in, is valid,
|
||
// and the passwords match.
|
||
//
|
||
MessageId = 0;
|
||
}
|
||
} else {
|
||
//
|
||
// Name is not valid.
|
||
//
|
||
MessageId = MSG_BAD_USER_NAME1;
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
}
|
||
} else {
|
||
//
|
||
// Don't allow empty name.
|
||
//
|
||
MessageId = MSG_BAD_USER_NAME2;
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
}
|
||
} else {
|
||
//
|
||
// User entered name of a built-in account.
|
||
//
|
||
MessageId = MSG_BAD_USER_NAME3;
|
||
SetFocus(GetDlgItem(hdlg,IDT_EDIT1));
|
||
}
|
||
|
||
if(MessageId && !ValidateOnly) {
|
||
MessageBoxFromMessage(hdlg,MessageId,NULL,IDS_ERROR,MB_OK|MB_ICONSTOP);
|
||
}
|
||
|
||
return(MessageId == 0);
|
||
}
|
||
|
||
BOOL
|
||
CALLBACK
|
||
UserAccountDlgProc(
|
||
IN HWND hdlg,
|
||
IN UINT msg,
|
||
IN WPARAM wParam,
|
||
IN LPARAM lParam
|
||
)
|
||
{
|
||
NMHDR *NotifyParams;
|
||
|
||
switch(msg) {
|
||
|
||
case WM_INITDIALOG:
|
||
//
|
||
// Limit text to maximum length of a user account name,
|
||
// and limit password text to max langth of a password.
|
||
// Also set initial text.
|
||
//
|
||
SendDlgItemMessage(hdlg,IDT_EDIT1,EM_LIMITTEXT,MAX_USERNAME,0);
|
||
SendDlgItemMessage(hdlg,IDT_EDIT2,EM_LIMITTEXT,MAX_PASSWORD,0);
|
||
SendDlgItemMessage(hdlg,IDT_EDIT3,EM_LIMITTEXT,MAX_PASSWORD,0);
|
||
SetDlgItemText(hdlg,IDT_EDIT1,UserName);
|
||
SetDlgItemText(hdlg,IDT_EDIT2,UserPassword);
|
||
SetDlgItemText(hdlg,IDT_EDIT3,UserPassword);
|
||
break;
|
||
|
||
case WM_SIMULATENEXT:
|
||
// Simulate the next button somehow
|
||
PropSheet_PressButton( GetParent(hdlg), PSBTN_NEXT);
|
||
break;
|
||
|
||
case WMX_VALIDATE:
|
||
//
|
||
// lParam == 0 for no UI, or 1 for UI
|
||
// Return 1 for success, -1 for error.
|
||
//
|
||
|
||
//
|
||
// Check name.
|
||
//
|
||
if(CheckUserAccountData(hdlg, lParam == 0)) {
|
||
//
|
||
// Data is valid. Move on to next page.
|
||
//
|
||
GetDlgItemText(hdlg,IDT_EDIT1,UserName,MAX_USERNAME+1);
|
||
GetDlgItemText(hdlg,IDT_EDIT2,UserPassword,MAX_PASSWORD+1);
|
||
CreateUserAccount = TRUE;
|
||
} else if (Unattended) {
|
||
//
|
||
// Data is invalid but we're unattended, so just don't create
|
||
// the account.
|
||
//
|
||
CreateUserAccount = FALSE;
|
||
GetDlgItemText(hdlg,IDT_EDIT1,UserName,MAX_USERNAME+1);
|
||
SetDlgItemText(hdlg,IDT_EDIT2,L"");
|
||
SetDlgItemText(hdlg,IDT_EDIT3,L"");
|
||
UserPassword[0] = 0;
|
||
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_OK);
|
||
}
|
||
|
||
//
|
||
// Don't allow next page to be activated.
|
||
//
|
||
return ReturnDlgResult (hdlg, VALIDATE_DATA_INVALID);
|
||
|
||
case WM_NOTIFY:
|
||
|
||
NotifyParams = (NMHDR *)lParam;
|
||
|
||
switch(NotifyParams->code) {
|
||
|
||
case PSN_SETACTIVE:
|
||
TESTHOOK(505);
|
||
BEGIN_SECTION(L"User Name and Password Page");
|
||
SetWizardButtons(hdlg,WizPageUserAccount);
|
||
|
||
//
|
||
// Load ComputerName because it may have been set when the user
|
||
// entered the user name.
|
||
//
|
||
SetDlgItemText(hdlg,IDT_EDIT1,UserName);
|
||
|
||
//
|
||
// Always activate in ui test mode
|
||
//
|
||
if(!UiTest) {
|
||
//
|
||
// Don't activate if this is a dc server or Win9x upgrade.
|
||
//
|
||
if(ISDC(ProductType) || Win95Upgrade) {
|
||
SetWindowLongPtr(hdlg,DWLP_MSGRESULT,-1);
|
||
break;
|
||
}
|
||
}
|
||
if (Unattended) {
|
||
if (!UnattendSetActiveDlg(hdlg,IDD_USERACCOUNT)) {
|
||
break;
|
||
}
|
||
}
|
||
// Page becomes active, make page visible.
|
||
SendMessage(GetParent(hdlg), WMX_BBTEXT, (WPARAM)FALSE, 0);
|
||
|
||
break;
|
||
|
||
case PSN_WIZBACK:
|
||
//
|
||
// Save UserName because we're going to load it into the dialog
|
||
// again when we come back.
|
||
//
|
||
GetDlgItemText(hdlg,IDT_EDIT1,UserName,MAX_USERNAME+1);
|
||
break;
|
||
|
||
case PSN_WIZNEXT:
|
||
case PSN_WIZFINISH:
|
||
UnattendAdvanceIfValid (hdlg); // see WMX_VALIDATE
|
||
break;
|
||
|
||
case PSN_KILLACTIVE:
|
||
WizardKillHelp(hdlg);
|
||
SetWindowLongPtr( hdlg, DWLP_MSGRESULT, FALSE );
|
||
END_SECTION(L"User Name and Password Page");
|
||
break;
|
||
|
||
case PSN_HELP:
|
||
WizardBringUpHelp(hdlg,WizPageUserAccount);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
return(FALSE);
|
||
}
|
||
|
||
return(TRUE);
|
||
}
|
||
#endif //def DOLOCALUSER
|
||
|
||
|