|
|
/*
* network - Dialog box property sheet for "network goo" */
#include "tweakui.h"
#pragma BEGIN_CONST_DATA
#define c_tszShutdownWithoutLogon TEXT("ShutdownWithoutLogon")
KL const c_klAutoLogon = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszAutoLogon }; KL const c_klDefUser = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszDefaultUserName }; KL const c_klDefPass = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszDefaultPassword }; KL const c_klShutdown = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszShutdownWithoutLogon }; KL const c_klRunServ = { &g_hkLMSMWCV, c_tszRunServices, g_tszName };
const static DWORD CODESEG rgdwHelp[] = { IDC_LOGONAUTO, IDH_AUTOLOGON, IDC_LOGONUSERTXT, IDH_AUTOLOGONUSER, IDC_LOGONUSER, IDH_AUTOLOGONUSER, IDC_LOGONPASSTXT, IDH_AUTOLOGONPASS, IDC_LOGONPASS, IDH_AUTOLOGONPASS, IDC_LOGONSHUTDOWN, IDH_LOGONSHUTDOWN, 0, 0, };
/*
* Instanced. We're a cpl so have only one instance, but I declare * all the instance stuff in one place so it's easy to convert this * code to multiple-instance if ever we need to. * * Note: All our instance data is kept in the dialog itself; don't need this */ #if 0
typedef struct NDII { /* network dialog instance info */ } NDII, *PNDII;
NDII ndii; #define pndii (&ndii)
#endif
/* #define TAMMEB_PERF */ #ifdef TAMMEB_PERF
/*****************************************************************************
* * Network_LogQPC * * Log the current time in "shell perf time", which is basically * milliseconds, but using QPC instead of GetTickCount(). * *****************************************************************************/
void Network_LogQPC(LPCTSTR pszName) { /* For perf testing, log the QPC time when we hit OK. */ { TCHAR tszTemp[40]; LARGE_INTEGER cur, freq; QueryPerformanceFrequency(&freq); QueryPerformanceCounter(&cur); wsprintf(tszTemp, TEXT("%d"), (DWORD)((cur.QuadPart * 1000) / freq.QuadPart)); WritePrivateProfileString(TEXT("NetworkLogon"), pszName, tszTemp, TEXT("C:\\TWEAKUI.LOG")); } } #endif
/*****************************************************************************
* * Network_SetDirty * * Make a control dirty. * *****************************************************************************/
#define Network_SetDirty Common_SetDirty
/*****************************************************************************
* * Network_PklToDlgItemText * * Read dialog item text from the registry. * *****************************************************************************/
#define ctchDlgItem 256
void PASCAL Network_PklToDlgItemText(HWND hdlg, UINT idc, PKL pkl) { TCHAR tsz[ctchDlgItem];
GetStrPkl(tsz, cbX(tsz), pkl); SetDlgItemTextLimit(hdlg, idc, tsz, cA(tsz)); }
/*****************************************************************************
* * Network_DlgItemTextToPkl * * Copy dialog item text to the registry. * *****************************************************************************/
void PASCAL Network_DlgItemTextToPkl(HWND hdlg, UINT idc, PKL pkl) { TCHAR tsz[ctchDlgItem];
GetDlgItemText(hdlg, idc, tsz, cA(tsz)); if (tsz[0]) { SetStrPkl(pkl, tsz); } else { DelPkl(pkl); } }
/*****************************************************************************
* * Network_Reset * * Reset all controls to initial values. This also marks * the control as clean. * *****************************************************************************/
BOOL PASCAL Network_Reset(HWND hdlg) { CheckDlgButton(hdlg, IDC_LOGONAUTO, GetIntPkl(0, &c_klAutoLogon));
Network_PklToDlgItemText(hdlg, IDC_LOGONUSER, &c_klDefUser);
if (g_fNT5) { WCHAR ubuf[ctchDlgItem]; ubuf[0] = TEXT('\0'); GetSecretDefaultPassword(ubuf, ctchDlgItem); SetDlgItemTextW(hdlg, IDC_LOGONPASS, ubuf); SendDlgItemMessageW(hdlg, IDC_LOGONPASS, EM_LIMITTEXT, cA(ubuf) - 1, 0); CheckDlgButton(hdlg, IDC_LOGONSHUTDOWN, GetIntPkl(0, &c_klShutdown)); } else { Network_PklToDlgItemText(hdlg, IDC_LOGONPASS, &c_klDefPass); DestroyWindow(GetDlgItem(hdlg, IDC_LOGONSHUTDOWN)); }
Common_SetClean(hdlg);
return 1; }
/*****************************************************************************
* * Network_Apply * * Write the changes to the registry. * *****************************************************************************/
BOOL NEAR PASCAL Network_Apply(HWND hdlg) { BOOL fAuto;
Network_DlgItemTextToPkl(hdlg, IDC_LOGONUSER, &c_klDefUser);
if (g_fNT5) { WCHAR ubuf[ctchDlgItem]; GetDlgItemTextW(hdlg, IDC_LOGONPASS, ubuf, cA(ubuf)); SetSecretDefaultPassword(ubuf); DelPkl(&c_klDefPass); /* And delete the unsafe one */ SetIntPkl(IsDlgButtonChecked(hdlg, IDC_LOGONSHUTDOWN), &c_klShutdown); } else { Network_DlgItemTextToPkl(hdlg, IDC_LOGONPASS, &c_klDefPass); }
fAuto = IsDlgButtonChecked(hdlg, IDC_LOGONAUTO); if (fAuto) { SetIntPkl(fAuto, &c_klAutoLogon); } else { DelPkl(&c_klAutoLogon); }
/*
* NT does this automatically, so we need to be hacky only on Win95a. */ if (!g_fNT) { if (fAuto) { SetStrPkl(&c_klRunServ, c_tszFixAutoLogon); } else { DelPkl(&c_klRunServ); } }
return Network_Reset(hdlg); }
/*****************************************************************************
* * Network_FactoryReset * * Autologon = false * AutoUser = none * AutoPass = none * *****************************************************************************/
BOOL PASCAL Network_FactoryReset(HWND hdlg) { Network_SetDirty(hdlg);
CheckDlgButton(hdlg, IDC_LOGONAUTO, FALSE); SetDlgItemText(hdlg, IDC_LOGONUSER, c_tszNil); SetDlgItemText(hdlg, IDC_LOGONPASS, c_tszNil); return 1; }
/*****************************************************************************
* * Network_OnCommand * * Ooh, we got a command. * *****************************************************************************/
BOOL PASCAL Network_OnCommand(HWND hdlg, int id, UINT codeNotify) { switch (id) { case IDC_RESET: /* Reset to factory default */ if (codeNotify == BN_CLICKED) return Network_FactoryReset(hdlg); break;
case IDC_LOGONAUTO: case IDC_LOGONSHUTDOWN: if (codeNotify == BN_CLICKED) Network_SetDirty(hdlg); break;
case IDC_LOGONUSER: case IDC_LOGONPASS: if (codeNotify == EN_CHANGE) Network_SetDirty(hdlg); break;
} return 0; }
/*****************************************************************************
* * Network_OnNotify * * Ooh, we got a notification. * *****************************************************************************/
BOOL PASCAL Network_OnNotify(HWND hdlg, NMHDR FAR *pnm) { switch (pnm->code) { case PSN_APPLY: Network_Apply(hdlg); break;
} return 0; }
/*****************************************************************************
* * Network_OnInitDialog * * Initialize the controls. * *****************************************************************************/
BOOL INLINE Network_OnInitDialog(HWND hdlg) { if (g_fNT5) { DestroyWindow(GetDlgItem(hdlg, IDC_LOGONPASSUNSAFE)); } return Network_Reset(hdlg); }
/*****************************************************************************
* * Our window procedure. * *****************************************************************************/
/*
* The HANDLE_WM_* macros weren't designed to be used from a dialog * proc, so we need to handle the messages manually. (But carefully.) */
INT_PTR EXPORT Network_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam) { switch (wm) { case WM_INITDIALOG: return Network_OnInitDialog(hdlg);
case WM_COMMAND: return Network_OnCommand(hdlg, (int)GET_WM_COMMAND_ID(wParam, lParam), (UINT)GET_WM_COMMAND_CMD(wParam, lParam)); case WM_NOTIFY: return Network_OnNotify(hdlg, (NMHDR FAR *)lParam);
case WM_HELP: Common_OnHelp(lParam, &rgdwHelp[0]); break;
case WM_CONTEXTMENU: Common_OnContextMenu(wParam, &rgdwHelp[0]); break;
default: return 0; /* Unhandled */ } return 1; /* Handled */ }
/*****************************************************************************
* * GetClassAtom * *****************************************************************************/
WORD PASCAL GetClassAtom(HWND hwnd) { return GetClassWord(hwnd, GCW_ATOM); }
/*****************************************************************************
* * Network_FindVictim * * Look arund to see if there is a window that meets the following * criteria: * * 1. Is a dialog box. * 2. Contains two edit controls, one of which is password-protected. * * If so, then the hwnd list is filled in with the two edit controls. * *****************************************************************************/
typedef struct AUTOLOGON { TCHAR tszUser[ctchDlgItem]; TCHAR tszPass[ctchDlgItem]; } AUTOLOGON, *PAUTOLOGON;
#define GetWindowClass(hwnd) GetClassWord(hwnd, GCW_ATOM)
HWND PASCAL Network_FindVictim(HWND hwndEdit, HWND rghwnd[]) { WORD atmEdit = GetClassAtom(hwndEdit); HWND hdlg;
for (hdlg = GetWindow(GetDesktopWindow(), GW_CHILD); hdlg; hdlg = GetWindow(hdlg, GW_HWNDNEXT)) {
/*
* If we have a dialog box, study it. */ if (GetClassAtom(hdlg) == 0x8002) { HWND hwnd, hwndUser = 0; for (hwnd = GetWindow(hdlg, GW_CHILD); hwnd; hwnd = GetWindow(hwnd, GW_HWNDNEXT)) {
/*
* We care only about visible non-read-only edit controls. */ if (GetClassAtom(hwnd) == atmEdit) { LONG ws = GetWindowLong(hwnd, GWL_STYLE); if (!(ws & ES_READONLY) && (ws & WS_VISIBLE)) { /*
* If we haven't found a "user name", * then the first edit we find had better * not be password-protected. If it is, * then we punt, because we're confused. * * If we have found a "user name", then the * next edit we find had better be * password-protected. */ if (hwndUser == 0) { if (ws & ES_PASSWORD) goto nextdialog; hwndUser = hwnd; } else { if (!(ws & ES_PASSWORD)) goto nextdialog; rghwnd[0] = hwndUser; rghwnd[1] = hwnd; return hdlg; } } } } } nextdialog:; } return 0; }
/*****************************************************************************
* * Network_ForceString * * Force a string into an edit control. We cannot use SetWindowText * because that doesn't work inter-thread. * *****************************************************************************/
void PASCAL Network_ForceString(HWND hwnd, LPCTSTR ptsz) { Edit_SetSel(hwnd, 0, -1); FORWARD_WM_CLEAR(hwnd, SendMessage);
for (; *ptsz && IsWindow(hwnd); ptsz++) { SendMessage(hwnd, WM_CHAR, *ptsz, 0L); } }
/*****************************************************************************
* * Network_Snoop * * Look to see if we have a winner. The shift key suppresses autologon. * *****************************************************************************/
void PASCAL Network_Snoop(HWND hwnd) { HWND rghwnd[2]; HWND hdlg;
hdlg = Network_FindVictim(hwnd, rghwnd); if (hdlg && GetAsyncKeyState(VK_SHIFT) >= 0) { PAUTOLOGON pal = (PAUTOLOGON)GetWindowLongPtr(hwnd, GWLP_USERDATA); if (pal) { Network_ForceString(rghwnd[0], pal->tszUser); Network_ForceString(rghwnd[1], pal->tszPass); FORWARD_WM_COMMAND(hdlg, IDOK, GetDlgItem(hdlg, IDOK), BN_CLICKED, PostMessage); PostMessage(hwnd, WM_CLOSE, 0, 0L); #ifdef TAMMEB_PERF
Network_LogQPC(TEXT("SuccessQPC")); #endif
} } }
/*****************************************************************************
* * Network_WndProc * * Window procedure for our "Keep an eye on the logon process". * * When the timer fires, we nuke ourselves, under the assumption that the * network dialog box ain't a-comin' so there's no point a-waitin' fer it. * *****************************************************************************/
LRESULT CALLBACK Network_WndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp) { switch (wm) {
case WM_DESTROY: KillTimer(hwnd, 1); PostQuitMessage(0); break;
case WM_TIMER: case WM_KILLFOCUS: Network_Snoop(hwnd); PostMessage(hwnd, WM_CLOSE, 0, 0L); break;
}
return DefWindowProc(hwnd, wm, wp, lp); }
/*****************************************************************************
* * TweakLogon * * Rundll entry point for automatic logon. This is run as a system service. * *****************************************************************************/
#pragma BEGIN_CONST_DATA
void EXPORT TweakLogon(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { AUTOLOGON al;
hwnd; hinst; lpszCmdLine; nCmdShow;
#ifdef TAMMEB_PERF
Network_LogQPC(TEXT("StartQPC")); #endif
GetStrPkl(al.tszUser, cbX(al.tszUser), &c_klDefUser); GetStrPkl(al.tszPass, cbX(al.tszPass), &c_klDefPass);
/*
* Null password is okay. But make sure there's a user and that * the feature has been enabled. And skip it all if the shift key * is down. */ if (GetIntPkl(0, &c_klAutoLogon) && al.tszUser[0] && GetAsyncKeyState(VK_SHIFT) >= 0) { MSG msg;
/*
* We create our window visible but 0 x 0. * * We use a dummy edit control because that lets us extract the * class word for edit controls. * * The GWL_USERDATA of the control points to the logon strings. * */ hwnd = CreateWindow(TEXT("edit"), "dummy text", WS_POPUP | WS_VISIBLE, 0, 0, 0, 0, hwnd, 0, hinstCur, 0);
SubclassWindow(hwnd, Network_WndProc); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&al);
Network_Snoop(hwnd);
/* Thirty seconds */ SetTimer(hwnd, 1, 30000, 0);
while (GetMessage(&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } #ifdef TAMMEB_PERF
Network_LogQPC(TEXT("StopQPC")); #endif
}
|