Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

555 lines
15 KiB

  1. /*
  2. * network - Dialog box property sheet for "network goo"
  3. */
  4. #include "tweakui.h"
  5. #pragma BEGIN_CONST_DATA
  6. #define c_tszShutdownWithoutLogon TEXT("ShutdownWithoutLogon")
  7. KL const c_klAutoLogon = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszAutoLogon };
  8. KL const c_klDefUser = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszDefaultUserName };
  9. KL const c_klDefPass = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszDefaultPassword };
  10. KL const c_klShutdown = { &g_hkLMSMWNTCV, c_tszWinlogon, c_tszShutdownWithoutLogon };
  11. KL const c_klRunServ = { &g_hkLMSMWCV, c_tszRunServices, g_tszName };
  12. const static DWORD CODESEG rgdwHelp[] = {
  13. IDC_LOGONAUTO, IDH_AUTOLOGON,
  14. IDC_LOGONUSERTXT, IDH_AUTOLOGONUSER,
  15. IDC_LOGONUSER, IDH_AUTOLOGONUSER,
  16. IDC_LOGONPASSTXT, IDH_AUTOLOGONPASS,
  17. IDC_LOGONPASS, IDH_AUTOLOGONPASS,
  18. IDC_LOGONSHUTDOWN, IDH_LOGONSHUTDOWN,
  19. 0, 0,
  20. };
  21. /*
  22. * Instanced. We're a cpl so have only one instance, but I declare
  23. * all the instance stuff in one place so it's easy to convert this
  24. * code to multiple-instance if ever we need to.
  25. *
  26. * Note: All our instance data is kept in the dialog itself; don't need this
  27. */
  28. #if 0
  29. typedef struct NDII { /* network dialog instance info */
  30. } NDII, *PNDII;
  31. NDII ndii;
  32. #define pndii (&ndii)
  33. #endif
  34. /* #define TAMMEB_PERF */
  35. #ifdef TAMMEB_PERF
  36. /*****************************************************************************
  37. *
  38. * Network_LogQPC
  39. *
  40. * Log the current time in "shell perf time", which is basically
  41. * milliseconds, but using QPC instead of GetTickCount().
  42. *
  43. *****************************************************************************/
  44. void
  45. Network_LogQPC(LPCTSTR pszName)
  46. {
  47. /* For perf testing, log the QPC time when we hit OK. */
  48. {
  49. TCHAR tszTemp[40];
  50. LARGE_INTEGER cur, freq;
  51. QueryPerformanceFrequency(&freq);
  52. QueryPerformanceCounter(&cur);
  53. wsprintf(tszTemp, TEXT("%d"), (DWORD)((cur.QuadPart * 1000) / freq.QuadPart));
  54. WritePrivateProfileString(TEXT("NetworkLogon"), pszName, tszTemp, TEXT("C:\\TWEAKUI.LOG"));
  55. }
  56. }
  57. #endif
  58. /*****************************************************************************
  59. *
  60. * Network_SetDirty
  61. *
  62. * Make a control dirty.
  63. *
  64. *****************************************************************************/
  65. #define Network_SetDirty Common_SetDirty
  66. /*****************************************************************************
  67. *
  68. * Network_PklToDlgItemText
  69. *
  70. * Read dialog item text from the registry.
  71. *
  72. *****************************************************************************/
  73. #define ctchDlgItem 256
  74. void PASCAL
  75. Network_PklToDlgItemText(HWND hdlg, UINT idc, PKL pkl)
  76. {
  77. TCHAR tsz[ctchDlgItem];
  78. GetStrPkl(tsz, cbX(tsz), pkl);
  79. SetDlgItemTextLimit(hdlg, idc, tsz, cA(tsz));
  80. }
  81. /*****************************************************************************
  82. *
  83. * Network_DlgItemTextToPkl
  84. *
  85. * Copy dialog item text to the registry.
  86. *
  87. *****************************************************************************/
  88. void PASCAL
  89. Network_DlgItemTextToPkl(HWND hdlg, UINT idc, PKL pkl)
  90. {
  91. TCHAR tsz[ctchDlgItem];
  92. GetDlgItemText(hdlg, idc, tsz, cA(tsz));
  93. if (tsz[0]) {
  94. SetStrPkl(pkl, tsz);
  95. } else {
  96. DelPkl(pkl);
  97. }
  98. }
  99. /*****************************************************************************
  100. *
  101. * Network_Reset
  102. *
  103. * Reset all controls to initial values. This also marks
  104. * the control as clean.
  105. *
  106. *****************************************************************************/
  107. BOOL PASCAL
  108. Network_Reset(HWND hdlg)
  109. {
  110. CheckDlgButton(hdlg, IDC_LOGONAUTO, GetIntPkl(0, &c_klAutoLogon));
  111. Network_PklToDlgItemText(hdlg, IDC_LOGONUSER, &c_klDefUser);
  112. if (g_fNT5) {
  113. WCHAR ubuf[ctchDlgItem];
  114. ubuf[0] = TEXT('\0');
  115. GetSecretDefaultPassword(ubuf, ctchDlgItem);
  116. SetDlgItemTextW(hdlg, IDC_LOGONPASS, ubuf);
  117. SendDlgItemMessageW(hdlg, IDC_LOGONPASS, EM_LIMITTEXT, cA(ubuf) - 1, 0);
  118. CheckDlgButton(hdlg, IDC_LOGONSHUTDOWN, GetIntPkl(0, &c_klShutdown));
  119. } else {
  120. Network_PklToDlgItemText(hdlg, IDC_LOGONPASS, &c_klDefPass);
  121. DestroyWindow(GetDlgItem(hdlg, IDC_LOGONSHUTDOWN));
  122. }
  123. Common_SetClean(hdlg);
  124. return 1;
  125. }
  126. /*****************************************************************************
  127. *
  128. * Network_Apply
  129. *
  130. * Write the changes to the registry.
  131. *
  132. *****************************************************************************/
  133. BOOL NEAR PASCAL
  134. Network_Apply(HWND hdlg)
  135. {
  136. BOOL fAuto;
  137. Network_DlgItemTextToPkl(hdlg, IDC_LOGONUSER, &c_klDefUser);
  138. if (g_fNT5) {
  139. WCHAR ubuf[ctchDlgItem];
  140. GetDlgItemTextW(hdlg, IDC_LOGONPASS, ubuf, cA(ubuf));
  141. SetSecretDefaultPassword(ubuf);
  142. DelPkl(&c_klDefPass); /* And delete the unsafe one */
  143. SetIntPkl(IsDlgButtonChecked(hdlg, IDC_LOGONSHUTDOWN), &c_klShutdown);
  144. } else {
  145. Network_DlgItemTextToPkl(hdlg, IDC_LOGONPASS, &c_klDefPass);
  146. }
  147. fAuto = IsDlgButtonChecked(hdlg, IDC_LOGONAUTO);
  148. if (fAuto) {
  149. SetIntPkl(fAuto, &c_klAutoLogon);
  150. } else {
  151. DelPkl(&c_klAutoLogon);
  152. }
  153. /*
  154. * NT does this automatically, so we need to be hacky only on Win95a.
  155. */
  156. if (!g_fNT) {
  157. if (fAuto) {
  158. SetStrPkl(&c_klRunServ, c_tszFixAutoLogon);
  159. } else {
  160. DelPkl(&c_klRunServ);
  161. }
  162. }
  163. return Network_Reset(hdlg);
  164. }
  165. /*****************************************************************************
  166. *
  167. * Network_FactoryReset
  168. *
  169. * Autologon = false
  170. * AutoUser = none
  171. * AutoPass = none
  172. *
  173. *****************************************************************************/
  174. BOOL PASCAL
  175. Network_FactoryReset(HWND hdlg)
  176. {
  177. Network_SetDirty(hdlg);
  178. CheckDlgButton(hdlg, IDC_LOGONAUTO, FALSE);
  179. SetDlgItemText(hdlg, IDC_LOGONUSER, c_tszNil);
  180. SetDlgItemText(hdlg, IDC_LOGONPASS, c_tszNil);
  181. return 1;
  182. }
  183. /*****************************************************************************
  184. *
  185. * Network_OnCommand
  186. *
  187. * Ooh, we got a command.
  188. *
  189. *****************************************************************************/
  190. BOOL PASCAL
  191. Network_OnCommand(HWND hdlg, int id, UINT codeNotify)
  192. {
  193. switch (id) {
  194. case IDC_RESET: /* Reset to factory default */
  195. if (codeNotify == BN_CLICKED) return Network_FactoryReset(hdlg);
  196. break;
  197. case IDC_LOGONAUTO:
  198. case IDC_LOGONSHUTDOWN:
  199. if (codeNotify == BN_CLICKED) Network_SetDirty(hdlg);
  200. break;
  201. case IDC_LOGONUSER:
  202. case IDC_LOGONPASS:
  203. if (codeNotify == EN_CHANGE) Network_SetDirty(hdlg);
  204. break;
  205. }
  206. return 0;
  207. }
  208. /*****************************************************************************
  209. *
  210. * Network_OnNotify
  211. *
  212. * Ooh, we got a notification.
  213. *
  214. *****************************************************************************/
  215. BOOL PASCAL
  216. Network_OnNotify(HWND hdlg, NMHDR FAR *pnm)
  217. {
  218. switch (pnm->code) {
  219. case PSN_APPLY:
  220. Network_Apply(hdlg);
  221. break;
  222. }
  223. return 0;
  224. }
  225. /*****************************************************************************
  226. *
  227. * Network_OnInitDialog
  228. *
  229. * Initialize the controls.
  230. *
  231. *****************************************************************************/
  232. BOOL INLINE
  233. Network_OnInitDialog(HWND hdlg)
  234. {
  235. if (g_fNT5) {
  236. DestroyWindow(GetDlgItem(hdlg, IDC_LOGONPASSUNSAFE));
  237. }
  238. return Network_Reset(hdlg);
  239. }
  240. /*****************************************************************************
  241. *
  242. * Our window procedure.
  243. *
  244. *****************************************************************************/
  245. /*
  246. * The HANDLE_WM_* macros weren't designed to be used from a dialog
  247. * proc, so we need to handle the messages manually. (But carefully.)
  248. */
  249. INT_PTR EXPORT
  250. Network_DlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  251. {
  252. switch (wm) {
  253. case WM_INITDIALOG: return Network_OnInitDialog(hdlg);
  254. case WM_COMMAND:
  255. return Network_OnCommand(hdlg,
  256. (int)GET_WM_COMMAND_ID(wParam, lParam),
  257. (UINT)GET_WM_COMMAND_CMD(wParam, lParam));
  258. case WM_NOTIFY:
  259. return Network_OnNotify(hdlg, (NMHDR FAR *)lParam);
  260. case WM_HELP: Common_OnHelp(lParam, &rgdwHelp[0]); break;
  261. case WM_CONTEXTMENU: Common_OnContextMenu(wParam, &rgdwHelp[0]); break;
  262. default: return 0; /* Unhandled */
  263. }
  264. return 1; /* Handled */
  265. }
  266. /*****************************************************************************
  267. *
  268. * GetClassAtom
  269. *
  270. *****************************************************************************/
  271. WORD PASCAL
  272. GetClassAtom(HWND hwnd)
  273. {
  274. return GetClassWord(hwnd, GCW_ATOM);
  275. }
  276. /*****************************************************************************
  277. *
  278. * Network_FindVictim
  279. *
  280. * Look arund to see if there is a window that meets the following
  281. * criteria:
  282. *
  283. * 1. Is a dialog box.
  284. * 2. Contains two edit controls, one of which is password-protected.
  285. *
  286. * If so, then the hwnd list is filled in with the two edit controls.
  287. *
  288. *****************************************************************************/
  289. typedef struct AUTOLOGON {
  290. TCHAR tszUser[ctchDlgItem];
  291. TCHAR tszPass[ctchDlgItem];
  292. } AUTOLOGON, *PAUTOLOGON;
  293. #define GetWindowClass(hwnd) GetClassWord(hwnd, GCW_ATOM)
  294. HWND PASCAL
  295. Network_FindVictim(HWND hwndEdit, HWND rghwnd[])
  296. {
  297. WORD atmEdit = GetClassAtom(hwndEdit);
  298. HWND hdlg;
  299. for (hdlg = GetWindow(GetDesktopWindow(), GW_CHILD); hdlg;
  300. hdlg = GetWindow(hdlg, GW_HWNDNEXT)) {
  301. /*
  302. * If we have a dialog box, study it.
  303. */
  304. if (GetClassAtom(hdlg) == 0x8002) {
  305. HWND hwnd, hwndUser = 0;
  306. for (hwnd = GetWindow(hdlg, GW_CHILD); hwnd;
  307. hwnd = GetWindow(hwnd, GW_HWNDNEXT)) {
  308. /*
  309. * We care only about visible non-read-only edit controls.
  310. */
  311. if (GetClassAtom(hwnd) == atmEdit) {
  312. LONG ws = GetWindowLong(hwnd, GWL_STYLE);
  313. if (!(ws & ES_READONLY) && (ws & WS_VISIBLE)) {
  314. /*
  315. * If we haven't found a "user name",
  316. * then the first edit we find had better
  317. * not be password-protected. If it is,
  318. * then we punt, because we're confused.
  319. *
  320. * If we have found a "user name", then the
  321. * next edit we find had better be
  322. * password-protected.
  323. */
  324. if (hwndUser == 0) {
  325. if (ws & ES_PASSWORD) goto nextdialog;
  326. hwndUser = hwnd;
  327. } else {
  328. if (!(ws & ES_PASSWORD)) goto nextdialog;
  329. rghwnd[0] = hwndUser;
  330. rghwnd[1] = hwnd;
  331. return hdlg;
  332. }
  333. }
  334. }
  335. }
  336. }
  337. nextdialog:;
  338. }
  339. return 0;
  340. }
  341. /*****************************************************************************
  342. *
  343. * Network_ForceString
  344. *
  345. * Force a string into an edit control. We cannot use SetWindowText
  346. * because that doesn't work inter-thread.
  347. *
  348. *****************************************************************************/
  349. void PASCAL
  350. Network_ForceString(HWND hwnd, LPCTSTR ptsz)
  351. {
  352. Edit_SetSel(hwnd, 0, -1);
  353. FORWARD_WM_CLEAR(hwnd, SendMessage);
  354. for (; *ptsz && IsWindow(hwnd); ptsz++) {
  355. SendMessage(hwnd, WM_CHAR, *ptsz, 0L);
  356. }
  357. }
  358. /*****************************************************************************
  359. *
  360. * Network_Snoop
  361. *
  362. * Look to see if we have a winner. The shift key suppresses autologon.
  363. *
  364. *****************************************************************************/
  365. void PASCAL
  366. Network_Snoop(HWND hwnd)
  367. {
  368. HWND rghwnd[2];
  369. HWND hdlg;
  370. hdlg = Network_FindVictim(hwnd, rghwnd);
  371. if (hdlg && GetAsyncKeyState(VK_SHIFT) >= 0) {
  372. PAUTOLOGON pal = (PAUTOLOGON)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  373. if (pal) {
  374. Network_ForceString(rghwnd[0], pal->tszUser);
  375. Network_ForceString(rghwnd[1], pal->tszPass);
  376. FORWARD_WM_COMMAND(hdlg, IDOK, GetDlgItem(hdlg, IDOK),
  377. BN_CLICKED, PostMessage);
  378. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  379. #ifdef TAMMEB_PERF
  380. Network_LogQPC(TEXT("SuccessQPC"));
  381. #endif
  382. }
  383. }
  384. }
  385. /*****************************************************************************
  386. *
  387. * Network_WndProc
  388. *
  389. * Window procedure for our "Keep an eye on the logon process".
  390. *
  391. * When the timer fires, we nuke ourselves, under the assumption that the
  392. * network dialog box ain't a-comin' so there's no point a-waitin' fer it.
  393. *
  394. *****************************************************************************/
  395. LRESULT CALLBACK
  396. Network_WndProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
  397. {
  398. switch (wm) {
  399. case WM_DESTROY:
  400. KillTimer(hwnd, 1);
  401. PostQuitMessage(0);
  402. break;
  403. case WM_TIMER:
  404. case WM_KILLFOCUS:
  405. Network_Snoop(hwnd);
  406. PostMessage(hwnd, WM_CLOSE, 0, 0L);
  407. break;
  408. }
  409. return DefWindowProc(hwnd, wm, wp, lp);
  410. }
  411. /*****************************************************************************
  412. *
  413. * TweakLogon
  414. *
  415. * Rundll entry point for automatic logon. This is run as a system service.
  416. *
  417. *****************************************************************************/
  418. #pragma BEGIN_CONST_DATA
  419. void EXPORT
  420. TweakLogon(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
  421. {
  422. AUTOLOGON al;
  423. hwnd;
  424. hinst;
  425. lpszCmdLine;
  426. nCmdShow;
  427. #ifdef TAMMEB_PERF
  428. Network_LogQPC(TEXT("StartQPC"));
  429. #endif
  430. GetStrPkl(al.tszUser, cbX(al.tszUser), &c_klDefUser);
  431. GetStrPkl(al.tszPass, cbX(al.tszPass), &c_klDefPass);
  432. /*
  433. * Null password is okay. But make sure there's a user and that
  434. * the feature has been enabled. And skip it all if the shift key
  435. * is down.
  436. */
  437. if (GetIntPkl(0, &c_klAutoLogon) && al.tszUser[0] &&
  438. GetAsyncKeyState(VK_SHIFT) >= 0) {
  439. MSG msg;
  440. /*
  441. * We create our window visible but 0 x 0.
  442. *
  443. * We use a dummy edit control because that lets us extract the
  444. * class word for edit controls.
  445. *
  446. * The GWL_USERDATA of the control points to the logon strings.
  447. *
  448. */
  449. hwnd = CreateWindow(TEXT("edit"), "dummy text", WS_POPUP | WS_VISIBLE,
  450. 0, 0, 0, 0,
  451. hwnd, 0, hinstCur, 0);
  452. SubclassWindow(hwnd, Network_WndProc);
  453. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&al);
  454. Network_Snoop(hwnd);
  455. /* Thirty seconds */
  456. SetTimer(hwnd, 1, 30000, 0);
  457. while (GetMessage(&msg, 0, 0, 0)) {
  458. TranslateMessage(&msg);
  459. DispatchMessage(&msg);
  460. }
  461. }
  462. #ifdef TAMMEB_PERF
  463. Network_LogQPC(TEXT("StopQPC"));
  464. #endif
  465. }