windows-nt/Source/XPSP1/NT/base/ntsetup/win95upg/migpwd/migpwd.c

1168 lines
29 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
migpwd.c
Abstract:
Implements a simple password application that sets a default password
for each local account created. This application is placed in the
RunOnce registry key when the Administrator account is set to auto-logon,
and at least one other local account was created.
The list of migrated local accounts is kept in
HKLM\Software\Microsoft\Windows\CurrentVersion\Setup\Win9xUpg\Users
This app prompts the user for a password, explaining what exactly is going
on, and then deletes the RunOnce and Users value on exit.
Author:
Jim Schmidt (jimschm) 18-Mar-1998
Revision History:
jimschm 06-Jul-1998 Added private stress option
--*/
#include "pch.h"
#include "resource.h"
#include "msg.h"
#include <lm.h>
//
// Constants
//
#define MAX_PASSWORD 64
//
// Globals
//
HINSTANCE g_hInst;
HANDLE g_hHeap;
UINT g_TotalUsers;
BOOL g_AutoPassword = FALSE;
TCHAR g_AutoLogonUser[256];
TCHAR g_AutoLogonPassword[MAX_PASSWORD + 1];
//
// !!! This is for internal use only !!! It is used for auto stress.
//
#ifdef PRERELEASE
BOOL g_AutoStress = FALSE;
TCHAR g_AutoStressUser[MAX_USER_NAME];
TCHAR g_AutoStressPwd[MAX_PASSWORD];
TCHAR g_AutoStressOffice[32];
TCHAR g_AutoStressDbg[MAX_COMPUTER_NAME];
DWORD g_AutoStressFlags;
#endif
//
// Library prototypes
//
BOOL
WINAPI
MigUtil_Entry (
HINSTANCE hInstance,
DWORD dwReason,
PVOID lpReserved
);
//
// Local prototypes
//
VOID
pCleanup (
VOID
);
BOOL
pIsAdministratorOnly (
VOID
);
BOOL
CALLBACK
PasswordProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
BOOL
pIsBlankPasswordAllowed (
VOID
);
BOOL
pIsPersonal (
VOID
)
{
static BOOL g_Determined = FALSE;
static BOOL g_Personal = FALSE;
OSVERSIONINFOEX osviex;
//
// Determine if Personal SKU
//
if (!g_Determined) {
g_Determined = TRUE;
osviex.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEX);
if (GetVersionEx ((LPOSVERSIONINFO)&osviex)) {
if (osviex.wProductType == VER_NT_WORKSTATION &&
(osviex.wSuiteMask & VER_SUITE_PERSONAL)
) {
g_Personal = TRUE;
}
}
}
return g_Personal;
}
//
// Implementation
//
INT
WINAPI
WinMain (
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR AnsiCmdLine,
INT CmdShow
)
/*++
Routine Description:
The entry point to migpwd.exe. All the work is done in a dialog box,
so no message loop is necessary.
Arguments:
hInstance - The instance handle of this EXE
hPrevInstance - The previous instance handle of this EXE if it is
running, or NULL if no other instances exist.
AnsiCmdLine - The command line (ANSI version)
CmdShow - The ShowWindow command passed by the shell
Return Value:
Returns -1 if an error occurred, or 0 if the exe completed. The exe
will automatically terminate with 0 if the migration DLL throws an
exception.
--*/
{
UINT Result;
PCTSTR ArgArray[1];
TCHAR UserName[MAX_USER_NAME];
DWORD Size;
HCURSOR OldCursor;
INITCOMMONCONTROLSEX init = {sizeof (INITCOMMONCONTROLSEX), 0};
STARTUPINFO si;
PROCESS_INFORMATION pi;
TCHAR winDir[MAX_PATH];
PTSTR oobeBalnPath;
PTSTR cmdLine;
BOOL ProcessResult;
#ifdef PRERELEASE
HKEY Key;
PCTSTR Data;
#endif
InitCommonControlsEx (&init);
g_hInst = hInstance;
g_hHeap = GetProcessHeap();
OldCursor = SetCursor (LoadCursor (NULL, IDC_ARROW));
MigUtil_Entry (hInstance, DLL_PROCESS_ATTACH, NULL);
#ifdef PRERELEASE
Key = OpenRegKeyStr (S_AUTOSTRESS_KEY);
if (Key) {
g_AutoStress = TRUE;
Data = GetRegValueString (Key, S_AUTOSTRESS_USER);
if (Data) {
StringCopy (g_AutoStressUser, Data);
MemFree (g_hHeap, 0, Data);
} else {
g_AutoStress = FALSE;
}
Data = GetRegValueString (Key, S_AUTOSTRESS_PASSWORD);
if (Data) {
StringCopy (g_AutoStressPwd, Data);
MemFree (g_hHeap, 0, Data);
} else {
g_AutoStress = FALSE;
}
Data = GetRegValueString (Key, S_AUTOSTRESS_OFFICE);
if (Data) {
StringCopy (g_AutoStressOffice, Data);
MemFree (g_hHeap, 0, Data);
} else {
g_AutoStress = FALSE;
}
Data = GetRegValueString (Key, S_AUTOSTRESS_DBG);
if (Data) {
StringCopy (g_AutoStressDbg, Data);
MemFree (g_hHeap, 0, Data);
} else {
g_AutoStress = FALSE;
}
Data = GetRegValueString (Key, S_AUTOSTRESS_FLAGS);
if (Data) {
g_AutoStressFlags = _tcstoul (Data, NULL, 10);
MemFree (g_hHeap, 0, Data);
} else {
g_AutoStress = FALSE;
}
CloseRegKey (Key);
}
#endif
//
// Launch oobebaln.exe /init
//
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
si.dwFlags = STARTF_FORCEOFFFEEDBACK;
if (!GetWindowsDirectory (winDir, ARRAYSIZE(winDir))) {
StringCopy (winDir, TEXT("c:\\windows"));
}
oobeBalnPath = JoinPaths (winDir, TEXT("system32\\oobe\\oobebaln.exe"));
cmdLine = JoinText (oobeBalnPath, TEXT(" /init"));
ProcessResult = CreateProcess (
oobeBalnPath,
cmdLine,
NULL,
NULL,
FALSE,
CREATE_DEFAULT_ERROR_MODE,
NULL,
NULL,
&si,
&pi
);
if (ProcessResult) {
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
} else {
LOG ((LOG_ERROR, "Cannot start %s", cmdLine));
}
FreePathString (oobeBalnPath);
FreeText (cmdLine);
//
// Set passwords
//
if (pIsAdministratorOnly()) {
DEBUGMSG ((DBG_VERBOSE, "Calling Adminitrator password dialog"));
Result = DialogBox (
hInstance,
MAKEINTRESOURCE(IDD_ADMIN_PASSWORD_DLG),
NULL,
PasswordProc
);
} else {
DEBUGMSG ((DBG_VERBOSE, "Calling multi user password dialog"));
Result = DialogBox (
hInstance,
MAKEINTRESOURCE(IDD_PASSWORD_DLG),
NULL,
PasswordProc
);
}
if (Result == IDOK) {
Size = MAX_USER_NAME;
GetUserName (UserName, &Size);
ArgArray[0] = UserName;
pCleanup();
#ifdef PRERELEASE
if (!g_AutoStress) {
#endif
//if (g_TotalUsers) {
// ResourceMessageBox (NULL, MSG_YOU_ARE_ADMIN, MB_ICONINFORMATION|MB_OK, ArgArray);
//}
#ifdef PRERELEASE
} else {
NETRESOURCE nr;
LONG rc;
TCHAR CmdLine[MAX_TCHAR_PATH];
STARTUPINFO si;
PROCESS_INFORMATION pi;
PTSTR UserName;
TCHAR StressCmdLine[MAX_TCHAR_PATH];
TCHAR NtDevDomain[MAX_COMPUTER_NAME];
TCHAR Msg[1024];
//
// Autostress: Create connection to \\ntstress or \\ntstress2
// Turn on autologon
// Create Run key for stress
// Run munge /p
//
nr.dwType = RESOURCETYPE_ANY;
nr.lpLocalName = TEXT("s:");
nr.lpRemoteName = TEXT("\\\\ntstress\\stress");
nr.lpProvider = NULL;
rc = WNetAddConnection2 (&nr, g_AutoStressPwd, g_AutoStressUser, 0);
if (rc != ERROR_SUCCESS) {
nr.lpRemoteName = TEXT("\\\\ntstress2\\stress");
rc = WNetAddConnection2 (&nr, g_AutoStressPwd, g_AutoStressUser, 0);
}
if (rc == ERROR_SUCCESS) {
// Prepare command line
StringCopy (NtDevDomain, g_AutoStressUser);
UserName = _tcschr (NtDevDomain, TEXT('\\'));
if (UserName) {
*UserName = 0;
UserName++;
} else {
UserName = g_AutoStressUser;
StringCopy (NtDevDomain, TEXT("ntdev"));
}
wsprintf (
StressCmdLine,
TEXT("%s\\stress.cmd /o %s /n %s /d c:\\stress /k %s /g"),
nr.lpRemoteName,
g_AutoStressOffice,
UserName,
g_AutoStressDbg
);
if (g_AutoStressFlags & AUTOSTRESS_PRIVATE) {
StringCat (StressCmdLine, TEXT(" /P"));
}
if (g_AutoStressFlags & AUTOSTRESS_MANUAL_TESTS) {
StringCat (StressCmdLine, TEXT(" /M"));
}
// Turn on autologon
Key = OpenRegKeyStr (S_WINLOGON_REGKEY);
MYASSERT (Key);
RegSetValueEx (
Key,
S_AUTOADMIN_LOGON_VALUE,
0,
REG_SZ,
(PBYTE) TEXT("1"),
sizeof (TCHAR) * 2
);
RegSetValueEx (
Key,
S_DEFAULT_USER_NAME_VALUE,
0,
REG_SZ,
(PBYTE) UserName,
SizeOfString (UserName)
);
RegSetValueEx (
Key,
S_DEFAULT_PASSWORD_VALUE,
0,
REG_SZ,
(PBYTE) g_AutoStressPwd,
SizeOfString (g_AutoStressPwd)
);
RegSetValueEx (
Key,
S_DEFAULT_DOMAIN_NAME_VALUE,
0,
REG_SZ,
(PBYTE) NtDevDomain,
SizeOfString (NtDevDomain)
);
CloseRegKey (Key);
// Prepare the launch of stress
Key = OpenRegKeyStr (S_RUN_KEY);
MYASSERT (Key);
RegSetValueEx (
Key,
TEXT("Stress"),
0,
REG_SZ,
(PBYTE) StressCmdLine,
SizeOfString (StressCmdLine)
);
CloseRegKey (Key);
// Run munge /p /q /y (to set preferred stress settings and reboot)
wsprintf (CmdLine, TEXT("%s\\munge.bat /p /q /y"), nr.lpRemoteName);
ZeroMemory (&si, sizeof (si));
si.cb = sizeof (si);
if (!CreateProcess (
NULL,
CmdLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi
)) {
wsprintf (Msg, TEXT("Can't start %s. rc=%u"), CmdLine, GetLastError());
MessageBox (NULL, Msg, NULL, MB_OK);
}
} else {
wsprintf (Msg, TEXT("Can't connect to ntstress or ntstress2. rc=%u"), GetLastError());
MessageBox (NULL, Msg, NULL, MB_OK);
}
}
#endif
}
MigUtil_Entry (hInstance, DLL_PROCESS_DETACH, NULL);
SetCursor (OldCursor);
return 0;
}
VOID
pCopyRegString (
IN HKEY DestKey,
IN HKEY SrcKey,
IN PCTSTR SrcValue
)
/*++
Routine Description:
pCopyRegString copies a REG_SZ value from one key to another. If the value
does not exist or is not a REG_SZ, nothing is copied.
Arguments:
DestKey - Specifies the destination key handle
SrcKey - Specifies the source key handle
SrcValue - Specifies the value in SrcKey to copy
Return Value:
None.
--*/
{
PCTSTR Data;
Data = GetRegValueString (SrcKey, SrcValue);
if (Data) {
RegSetValueEx (
DestKey,
SrcValue,
0,
REG_SZ,
(PBYTE) Data,
SizeOfString (Data)
);
MemFree (g_hHeap, 0, Data);
}
}
VOID
pCleanup (
VOID
)
/*++
Routine Description:
pCleanup performs all cleanup necessary to remove auto-logon and migpwd.exe.
Arguments:
None.
Return Value:
None.
--*/
{
HKEY Key;
HKEY DestKey;
TCHAR ExeName[MAX_PATH];
//
// This is the place where we will delete the Run or RunOnce entry,
// remove the Setup\Win9xUpg\Users key, remove the auto logon,
// and delete this EXE.
//
Key = OpenRegKeyStr (S_RUNONCE_KEY);
if (Key) {
RegDeleteValue (Key, S_MIGPWD);
CloseRegKey (Key);
}
Key = OpenRegKeyStr (S_RUN_KEY);
if (Key) {
RegDeleteValue (Key, S_MIGPWD);
CloseRegKey (Key);
}
Key = OpenRegKeyStr (S_WINLOGON_REGKEY);
if (Key) {
RegDeleteValue (Key, S_AUTOADMIN_LOGON_VALUE);
RegDeleteValue (Key, S_DEFAULT_PASSWORD_VALUE);
CloseRegKey (Key);
}
Key = OpenRegKeyStr (S_WIN9XUPG_KEY);
if (Key) {
RegDeleteKey (Key, S_USERS_SUBKEY);
CloseRegKey (Key);
}
GetModuleFileName (NULL, ExeName, MAX_PATH);
MoveFileEx (ExeName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
//
// Transfer auto logon from Win9xUpg
//
Key = OpenRegKeyStr (S_WIN9XUPG_KEY);
if (Key) {
DestKey = OpenRegKeyStr (S_WINLOGON_REGKEY);
if (DestKey) {
pCopyRegString (DestKey, Key, S_AUTOADMIN_LOGON_VALUE);
if (g_AutoLogonUser[0]) {
//
// We changed the password for this user
//
RegSetValueEx (
DestKey,
S_DEFAULT_PASSWORD_VALUE,
0,
REG_SZ,
(PBYTE) g_AutoLogonPassword,
SizeOfString (g_AutoLogonPassword)
);
} else {
pCopyRegString (DestKey, Key, S_DEFAULT_PASSWORD_VALUE);
}
pCopyRegString (DestKey, Key, S_DEFAULT_USER_NAME_VALUE);
pCopyRegString (DestKey, Key, S_DEFAULT_DOMAIN_NAME_VALUE);
CloseRegKey (DestKey);
}
CloseRegKey (Key);
}
}
BOOL
pSetUserPassword (
IN PCTSTR User,
IN PCTSTR Password
)
/*++
Routine Description:
pSetUserPassword changes the password on the specified user account.
Arguments:
User - Specifies the user name to change
Password - Specifies the new password
Return Value:
TRUE if the password was changed, or FALSE if an error occurred.
--*/
{
LONG rc;
PCWSTR UnicodeUser;
PCWSTR UnicodePassword;
PUSER_INFO_1 ui1;
UnicodeUser = CreateUnicode (User);
UnicodePassword = CreateUnicode (Password);
rc = NetUserGetInfo (NULL, (PWSTR) UnicodeUser, 1, (PBYTE *) (&ui1));
if (rc != NO_ERROR) {
SetLastError (rc);
DEBUGMSG ((DBG_ERROR, "User %s does not exist", User));
rc = NO_ERROR;
} else {
ui1->usri1_password = (PWSTR) UnicodePassword;
rc = NetUserSetInfo (NULL, (PWSTR) UnicodeUser, 1, (PBYTE) ui1, NULL);
NetApiBufferFree ((PVOID) ui1);
}
DestroyUnicode (UnicodeUser);
DestroyUnicode (UnicodePassword);
DEBUGMSG_IF ((rc != NO_ERROR, DBG_ERROR, "Password could not be set, rc=%u", rc));
SetLastError (rc);
return rc == NO_ERROR;
}
BOOL
CALLBACK
PasswordProc (
HWND hdlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
/*++
Routine Description:
PasswordProc is the dialog procedure for the password dialog. It
initializes the list box with the names of all new accounts. When the user
choses Change, the password is tested and changed if possible. A popup is
presented if the user tries to enter a blank password.
Arguments:
hdlg - Dialog window handle
uMsg - Message to process
wParam - Message-specific
lParam - Message-specific
Return Value:
TRUE if the message was processed, or FALSE if the message should be
processed by the OS.
--*/
{
HKEY Key;
HKEY win9xUpgKey;
static HWND List;
REGVALUE_ENUM e;
PCTSTR Data;
//LONG Index;
//LONG Count;
TCHAR Pwd[MAX_PASSWORD + 1];
TCHAR ConfirmPwd[MAX_PASSWORD + 1];
static HWND Edit1, Edit2;
GROWBUFFER Line = GROWBUF_INIT;
BOOL b;
SIZE Size;
INT MaxWidth;
INT IntegralWidth;
TEXTMETRIC tm;
HDC dc;
RECT rect;
DWORD bufSize;
TCHAR computerName[MAX_PATH];
PCTSTR domainName;
BOOL changingAutoLogonPwd;
*Pwd = 0;
*ConfirmPwd = 0;
switch (uMsg) {
case WM_INITDIALOG:
//
// Enable a timer so the dialog never goes to sleep
// and we ensure it's always the foreground window
//
SetTimer (hdlg, 1, 30000, NULL);
SetTimer (hdlg, 2, 1000, NULL);
//
// Fill list box with user names from registry
//
List = GetDlgItem (hdlg, IDC_USER_LIST);
Edit1 = GetDlgItem (hdlg, IDC_PASSWORD);
Edit2 = GetDlgItem (hdlg, IDC_CONFIRM);
SendMessage (Edit1, EM_LIMITTEXT, MAX_PASSWORD, 0);
SendMessage (Edit2, EM_LIMITTEXT, MAX_PASSWORD, 0);
g_TotalUsers = 0;
if (List) {
//
// Compute text metrics for list
//
dc = CreateDC (TEXT("DISPLAY"), NULL, NULL, NULL);
SelectObject (dc, (HFONT) SendMessage (List, WM_GETFONT, 0, 0));
GetTextMetrics (dc, &tm);
Key = OpenRegKeyStr (S_USER_LIST_KEY);
if (Key) {
//
// Enumerate the users in this key. Data is saved with
// each list entry, though it is not currently used.
//
MaxWidth = 0;
if (EnumFirstRegValue (&e, Key)) {
do {
Data = GetRegValueString (e.KeyHandle, e.ValueName);
if (Data) {
GetTextExtentPoint (
dc,
e.ValueName,
TcharCount (e.ValueName),
&Size
);
MaxWidth = max (MaxWidth, Size.cx);
if (g_TotalUsers) {
GrowBufAppendString (&Line, TEXT("\t"));
}
GrowBufAppendString (&Line, e.ValueName);
g_TotalUsers++;
MemFree (g_hHeap, 0, Data); // edit ctrl version
//
// List box code:
//
//
//Index = SendMessage (
// List,
// LB_ADDSTRING,
// 0,
// (LPARAM) e.ValueName
// );
//
//MYASSERT (Index != LB_ERR);
//SendMessage (
// List,
// LB_SETITEMDATA,
// Index,
// (LPARAM) Data
// );
//
// free Data later
}
} while (EnumNextRegValue (&e));
}
GrowBufAppendString (&Line, TEXT("\r\n"));
SetWindowText (List, (PCTSTR) Line.Buf);
MaxWidth += tm.tmAveCharWidth * 2;
GetWindowRect (List, &rect);
IntegralWidth = (rect.right - rect.left) / MaxWidth;
IntegralWidth = max (IntegralWidth, 1);
MaxWidth = IntegralWidth * (rect.right - rect.left);
rect.left = 0;
rect.right = 100;
rect.top = 0;
rect.bottom = 100;
MapDialogRect (hdlg, &rect);
MaxWidth = (MaxWidth * 100) / (rect.right - rect.left);
SendMessage (List, EM_SETTABSTOPS, 1, (LPARAM) (&MaxWidth));
CloseRegKey (Key);
DeleteDC (dc);
}
ELSE_DEBUGMSG ((DBG_WARNING, "%s not found", S_USER_LIST_KEY));
FreeGrowBuffer (&Line);
if (!g_TotalUsers) {
EndDialog (hdlg, IDOK);
} else {
SetForegroundWindow (hdlg);
}
}
if (pIsPersonal ()) {
g_AutoPassword = TRUE;
PostMessage (hdlg, WM_COMMAND, IDOK, 0);
}
#ifdef PRERELEASE
//
// !!! This is for internal use only !!! It is used for auto stress.
//
else if (g_AutoStress) {
PostMessage (hdlg, WM_COMMAND, IDOK, 0);
}
#endif
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
if (pIsPersonal () && g_AutoPassword) {
StringCopy (Pwd, TEXT(""));
StringCopy (ConfirmPwd, Pwd);
} else {
GetWindowText (Edit1, Pwd, MAX_PASSWORD + 1);
GetWindowText (Edit2, ConfirmPwd, MAX_PASSWORD + 1);
if (lstrcmp (Pwd, ConfirmPwd)) {
OkBox (hdlg, MSG_PASSWORDS_DO_NOT_MATCH);
SetWindowText (Edit1, S_EMPTY);
SetWindowText (Edit2, S_EMPTY);
SetFocus (Edit1);
break;
}
#ifdef PRERELEASE
//
// !!! This is for internal use only !!! It is used for auto stress.
//
if (g_AutoStress) {
StringCopy (Pwd, TEXT("Password1"));
StringCopy (ConfirmPwd, Pwd);
}
#endif
if (*Pwd == 0) {
if (pIsBlankPasswordAllowed()) {
//
// Don't warn about blank passwords, since on Whistler they
// are safe.
//
//if (IDYES != YesNoBox (hdlg, MSG_EMPTY_PASSWORD_WARNING)) {
// break;
//}
} else {
OkBox (hdlg, MSG_MUST_SPECIFY_PASSWORD);
break;
}
}
}
//
// Enumerate all the users and set the password on each
//
b = TRUE;
Key = OpenRegKeyStr (S_USER_LIST_KEY);
if (Key) {
//
// Get the user name & pwd of the autologon (if any)
//
g_AutoLogonUser[0] = 0;
g_AutoLogonPassword[0] = 0;
bufSize = ARRAYSIZE (computerName);
if (GetComputerName (computerName, &bufSize)) {
win9xUpgKey = OpenRegKeyStr (S_WIN9XUPG_KEY);
if (win9xUpgKey) {
domainName = GetRegValueString (win9xUpgKey, S_DEFAULT_DOMAIN_NAME_VALUE);
if (domainName) {
if (StringIMatch (computerName, domainName)) {
//
// Process local accounts only
//
Data = GetRegValueString (win9xUpgKey, S_DEFAULT_USER_NAME_VALUE);
if (Data) {
StringCopyByteCount (g_AutoLogonUser, Data, sizeof(g_AutoLogonUser));
MemFree (g_hHeap, 0, Data);
}
}
ELSE_DEBUGMSG ((DBG_VERBOSE, "Autologon set for non-local user (domain is %s)", domainName));
MemFree (g_hHeap, 0, domainName);
}
CloseRegKey (win9xUpgKey);
}
}
//
// Enumerate the users in this key
//
changingAutoLogonPwd = FALSE;
if (EnumFirstRegValue (&e, Key)) {
do {
if (g_AutoLogonUser[0]) {
if (!changingAutoLogonPwd && StringIMatch (e.ValueName, g_AutoLogonUser)) {
changingAutoLogonPwd = TRUE;
StringCopy (g_AutoLogonPassword, Pwd);
}
}
if (!pSetUserPassword (e.ValueName, Pwd)) {
if (!g_AutoPassword) {
if (GetLastError() == NERR_PasswordTooShort) {
OkBox (hdlg, MSG_PASSWORD_TOO_SHORT);
} else {
OkBox (hdlg, MSG_PASSWORD_INVALID);
}
}
b = FALSE;
g_AutoPassword = FALSE;
break;
}
} while (EnumNextRegValue (&e));
}
//
// NOTE: b might be FALSE; changingAutoLogonPwd only matters
// when b is TRUE, because we just stay in the dialog until
// then.
//
if (b && !changingAutoLogonPwd) {
g_AutoLogonUser[0] = 0;
}
CloseRegKey (Key);
}
if (b) {
EndDialog (hdlg, LOWORD (wParam));
}
break;
}
break;
case WM_TIMER:
if (wParam == 2) {
//
// This timer ensures we have the keyboard focus
// even if another process tries to take it while
// the dialog is being shown.
//
if (GetForegroundWindow () != hdlg) {
SetForegroundWindow (hdlg);
}
} else {
//
// Make this thread a no-sleep thread
//
SetThreadExecutionState (ES_SYSTEM_REQUIRED|ES_DISPLAY_REQUIRED|ES_CONTINUOUS);
}
break;
case WM_DESTROY:
KillTimer (hdlg, 1);
KillTimer (hdlg, 2);
//List = GetDlgItem (hdlg, IDC_LIST);
//if (List) {
//
// Count = SendMessage (List, LB_GETCOUNT, 0, 0);
// for (Index = 0 ; Index < Count ; Index++) {
// Data = (PCTSTR) SendMessage (List, LB_GETITEMDATA, Index, 0);
// if (Data) {
// MemFree (g_hHeap, 0, Data);
// }
// }
//}
break;
}
return FALSE;
}
BOOL
pIsAdministratorOnly (
VOID
)
{
BOOL NonAdminExists = FALSE;
PCTSTR AdministratorName;
HKEY Key;
REGVALUE_ENUM e;
PCTSTR Data;
BOOL AdministratorExists = FALSE;
AdministratorName = GetStringResource (MSG_ADMINISTRATOR);
MYASSERT (AdministratorName);
Key = OpenRegKeyStr (S_USER_LIST_KEY);
if (Key) {
//
// Enumerate the users in this key. Data is saved with
// each list entry, though it is not currently used.
//
if (EnumFirstRegValue (&e, Key)) {
do {
Data = GetRegValueString (e.KeyHandle, e.ValueName);
if (Data) {
if (!StringIMatch (e.ValueName, AdministratorName)) {
NonAdminExists = TRUE;
} else {
AdministratorExists = TRUE;
}
MemFree (g_hHeap, 0, Data);
}
} while (EnumNextRegValue (&e));
}
CloseRegKey (Key);
}
ELSE_DEBUGMSG ((DBG_WARNING, "%s not found", S_USER_LIST_KEY));
FreeStringResource (AdministratorName);
return !NonAdminExists && AdministratorExists;
}
BOOL
pIsBlankPasswordAllowed (
VOID
)
{
PUSER_MODALS_INFO_0 umi;
NET_API_STATUS rc;
BOOL b;
rc = NetUserModalsGet (
NULL,
0,
(PBYTE *) &umi
);
if (rc != ERROR_SUCCESS) {
SetLastError(rc);
DEBUGMSG ((DBG_ERROR, "Can't get password policy info"));
return TRUE;
}
b = (umi->usrmod0_min_passwd_len == 0);
NetApiBufferFree ((PVOID) umi);
return b;
}