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.

604 lines
17 KiB

  1. // **************************************************************************
  2. //
  3. // rodlg.c
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1992-1993
  7. // All rights reserved
  8. //
  9. // RunOnce wrapper. This encapsulates all applications that would like
  10. // to run the first time we re-boot. It lists these apps for the user
  11. // and allows the user to launce the apps (like apple at ease).
  12. //
  13. // 5 June 1994 FelixA Started
  14. // 8 June Felix Defined registry strings and functionality.
  15. // Got small buttons displayed, but not working.
  16. // 9 June Felix Both big and small buttons. Nice UI.
  17. // Got single click app launching.
  18. //
  19. // 23 June Felix Moving it to a Chicago make thingy not Dolphin
  20. //
  21. // *************************************************************************/
  22. //
  23. #include "precomp.h"
  24. #include <shlobj.h>
  25. #include <stdlib.h>
  26. #include <regstr.h>
  27. #include <shellapi.h>
  28. #include <shlobjp.h>
  29. // #include <shsemip.h>
  30. extern int g_iState; // Command line args.
  31. extern HINSTANCE g_hInst; // current instance
  32. #define WM_FINISHED (WM_USER+0x123)
  33. #include "resource.h"
  34. int g_fCleanBoot;
  35. TCHAR c_szRunOnce[]=REGSTR_PATH_RUNONCE;
  36. TCHAR c_szSetup[]=REGSTR_PATH_SETUP;
  37. TCHAR g_szWallpaper[] = TEXT("wallpaper");
  38. TCHAR szTileWall[] = TEXT("TileWallpaper");
  39. TCHAR szFallback[] = TEXT("*DisplayFallback");
  40. const TCHAR c_szTimeChangedRunOnce[] = TEXT("WarnTimeChanged"); //kernel32 and explorer use this
  41. // Run time can be set for big or small buttons.
  42. int g_Small=0;
  43. HDC g_hdcMem=NULL;
  44. DWORD g_dwThread;
  45. //***************************************************************************
  46. //
  47. // <Function>()
  48. // <Explanation>
  49. //
  50. // ENTRY:
  51. // <Params>
  52. //
  53. // EXIT:
  54. // <Params>
  55. //
  56. //***************************************************************************
  57. //***************************************************************************
  58. //
  59. // DoAnyRandomOneTimeStuff()
  60. // Just a place to toss random stuff for RunOnce app to do.
  61. //
  62. // ENTRY:
  63. // void
  64. //
  65. // EXIT:
  66. // void
  67. //
  68. //***************************************************************************
  69. void DoAnyRandomOneTimeStuff(void)
  70. {
  71. HKEY runonce;
  72. // remove any time-changed warning added by kernel32 during boot
  73. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRunOnce, &runonce) == ERROR_SUCCESS)
  74. {
  75. RegDeleteValue(runonce, (LPCTSTR)c_szTimeChangedRunOnce);
  76. RegCloseKey(runonce);
  77. }
  78. }
  79. //***************************************************************************
  80. //
  81. // RunOnceFill()
  82. // Fills the List box in the run-once dlg.
  83. //
  84. // ENTRY:
  85. // HWND of the thing to fill.
  86. //
  87. // EXIT:
  88. // <Params>
  89. // BOOL NEAR PASCAL RunRegApps(HKEY hkeyParent, LPCSTR szSubkey, BOOL fDelete, BOOL fWait)
  90. //
  91. //***************************************************************************
  92. BOOL RunOnceFill(HWND hWnd)
  93. {
  94. HKEY hkey;
  95. // HKEY hDescKey;
  96. BOOL fShellInit = FALSE;
  97. HKEY hkeyParent = HKEY_LOCAL_MACHINE;
  98. TCHAR szSubkey[MAX_PATH];
  99. BOOL fDelete=FALSE;
  100. BOOL fWait=FALSE;
  101. // Enumerate HKLM\Runonce\Setup - *.*
  102. lstrcpy(szSubkey,c_szRunOnce);
  103. lstrcat(szSubkey,TEXT("\\Setup"));
  104. if (RegOpenKey(hkeyParent, szSubkey, &hkey) == ERROR_SUCCESS)
  105. {
  106. DWORD cbData, cchValue, dwType, i;
  107. TCHAR szValueName[MAX_PATH], szCmdLine[MAX_PATH];
  108. LRESULT lRes;
  109. DWORD dwNumSubkeys=1, dwNumValues=5;
  110. for (i = 0; ; i++)
  111. {
  112. cchValue = sizeof(szValueName) / sizeof(TCHAR);
  113. cbData = sizeof(szCmdLine);
  114. if (RegEnumValue(hkey, i, szValueName, &cchValue, NULL, &dwType, (LPBYTE) szCmdLine, &cbData) != ERROR_SUCCESS)
  115. break;
  116. if (dwType == REG_SZ)
  117. {
  118. PTASK pTask;
  119. pTask = (PTASK)LocalAlloc( LPTR ,sizeof(TASK));
  120. lstrcpyn(pTask->Text,szValueName, MAX_TEXT );
  121. lstrcpyn( pTask->Cmd, szCmdLine, MAX_PATH );
  122. lRes = SendMessage( hWnd, LB_ADDSTRING, 0, (LPARAM)pTask );
  123. if( lRes == LB_ERR || lRes == LB_ERRSPACE )
  124. {
  125. LocalFree(pTask);
  126. pTask=NULL;
  127. }
  128. }
  129. }
  130. RegCloseKey(hkey);
  131. }
  132. return(fShellInit);
  133. }
  134. //***************************************************************************
  135. //
  136. // LaunchApp()
  137. // Given an index into the list box, will spawn the task, wait for it to
  138. // finish.
  139. //
  140. // ENTRY:
  141. // Index into list.
  142. //
  143. // EXIT:
  144. // <Params>
  145. //
  146. //***************************************************************************
  147. int LaunchApp(HWND hWnd, WORD wItem )
  148. {
  149. LPTSTR lpszCmdLine;
  150. STARTUPINFO startup;
  151. #ifndef DEBUG
  152. PROCESS_INFORMATION pi;
  153. #endif
  154. PTASK pTask;
  155. RECT rWnd;
  156. GetWindowRect(hWnd, &rWnd);
  157. SendMessage(hWnd,LB_SETCURSEL,wItem,0);
  158. pTask = (PTASK)SendMessage( hWnd, LB_GETITEMDATA, wItem, 0L);
  159. if(pTask != (PTASK)LB_ERR )
  160. {
  161. lpszCmdLine = &pTask->Cmd[0];
  162. // Now exec it.
  163. startup.cb = sizeof(startup);
  164. startup.lpReserved = NULL;
  165. startup.lpDesktop = NULL;
  166. startup.lpTitle = NULL;
  167. startup.dwFlags = STARTF_USEPOSITION; // Set start position
  168. startup.dwX=rWnd.right+5;
  169. startup.dwY=rWnd.top+5;
  170. startup.cbReserved2 = 0;
  171. startup.lpReserved2 = NULL;
  172. #ifdef DEBUG
  173. MessageBox(hWnd, lpszCmdLine,TEXT("DebugRun"),MB_OK);
  174. #else
  175. if (CreateProcess(NULL, lpszCmdLine, NULL, NULL, FALSE, CREATE_NEW_PROCESS_GROUP,
  176. NULL, NULL, &startup, &pi))
  177. {
  178. WaitForSingleObjectEx(pi.hProcess, INFINITE, TRUE);
  179. CloseHandle(pi.hProcess);
  180. CloseHandle(pi.hThread);
  181. }
  182. else
  183. {
  184. MessageBeep( MB_ICONEXCLAMATION );
  185. }
  186. #endif
  187. }
  188. else
  189. {
  190. MessageBeep( MB_ICONEXCLAMATION );
  191. }
  192. // Remove any selection after the app terminates.
  193. SendMessage( hWnd, LB_SETCURSEL, (WPARAM)-1, 0);
  194. return FALSE;
  195. }
  196. //***************************************************************************
  197. //
  198. // RunAppsInList()
  199. // Enumerates all the items in the list box, spawning each in turn.
  200. //
  201. // ENTRY:
  202. // HWND of Parent.
  203. //
  204. // EXIT:
  205. // <Params>
  206. //
  207. //***************************************************************************
  208. DWORD WINAPI RunAppsInList(LPVOID lp)
  209. {
  210. HWND hWnd=(HWND)lp;
  211. WORD i,iNumItems;
  212. TCHAR szSubkey[MAX_PATH];
  213. TCHAR szWallpaper[MAX_PATH];
  214. DWORD cbSize;
  215. DWORD dwType;
  216. // Run all the applications in the list
  217. iNumItems = (WORD)SendMessage(hWnd,LB_GETCOUNT,0,0L);
  218. for(i=0;i<iNumItems;i++)
  219. {
  220. LaunchApp(hWnd,i);
  221. }
  222. // Delete the runonce subkey for setup.
  223. #ifdef DEBUG
  224. MessageBox( hWnd, szSubkey, TEXT("Delete Key - not done"), MB_OK);
  225. #else
  226. lstrcpy(szSubkey,c_szRunOnce);
  227. lstrcat(szSubkey,TEXT("\\Setup"));
  228. RegDeleteKey( HKEY_LOCAL_MACHINE, szSubkey );
  229. #endif
  230. // Now see if we should reboot/restart.
  231. if (g_iState & (CMD_DO_REBOOT|CMD_DO_RESTART))
  232. {
  233. HKEY hkey;
  234. TCHAR achTitle[80];
  235. DWORD dwSetupFlags=0;
  236. //
  237. // because we are going to reboot, remove the VGA fallback.
  238. // line from OneRunce.
  239. //
  240. if (RegOpenKey(HKEY_LOCAL_MACHINE, c_szRunOnce, &hkey) == ERROR_SUCCESS)
  241. {
  242. RegDeleteValue(hkey, szFallback);
  243. RegCloseKey(hkey);
  244. }
  245. szWallpaper[0]=0;
  246. LoadString(g_hInst, IDS_PAMPER, szWallpaper, sizeof(szWallpaper) / sizeof(TCHAR));
  247. GetWindowText(GetParent(hWnd), achTitle, sizeof(achTitle) / sizeof(TCHAR));
  248. // Get the setup flags.
  249. if(RegOpenKey(HKEY_LOCAL_MACHINE, c_szSetup, &hkey) == ERROR_SUCCESS)
  250. {
  251. cbSize=sizeof(dwSetupFlags);
  252. if(RegQueryValueEx(hkey, REGSTR_VAL_SETUPFLAGS, NULL , &dwType, (LPBYTE)&dwSetupFlags, &cbSize) != ERROR_SUCCESS )
  253. dwSetupFlags=0;
  254. RegCloseKey(hkey);
  255. }
  256. //
  257. // always reboot the system, dont give the user a choice.
  258. //
  259. // alow OEMs not to have to click OK.
  260. #ifdef DEBUG
  261. MessageBox(hWnd,dwSetupFlags & SUF_BATCHINF?TEXT("Batchfile used"):TEXT("No batch"),TEXT("Batch"),MB_OK);
  262. #endif
  263. if( !(dwSetupFlags & SUF_BATCHINF) || !GetPrivateProfileInt(TEXT("Setup"),TEXT("NoPrompt2Boot"),0,TEXT("MSBATCH.INF")))
  264. MessageBox(GetParent(hWnd),szWallpaper,achTitle,MB_OK|MB_ICONEXCLAMATION);
  265. #ifndef DEBUG
  266. ExitWindowsEx(EWX_REBOOT, 0);
  267. #endif
  268. }
  269. PostMessage(GetParent(hWnd),WM_FINISHED,0,0L);
  270. return 0;
  271. }
  272. //***************************************************************************
  273. //
  274. // <Function>()
  275. // <Explanation>
  276. //
  277. // ENTRY:
  278. // <Params>
  279. //
  280. // EXIT:
  281. // <Params>
  282. //
  283. //***************************************************************************
  284. #define CXBORDER 3
  285. LRESULT _HandleLBMeasureItem(HWND hwndLB, MEASUREITEMSTRUCT *lpmi)
  286. {
  287. RECT rWnd;
  288. int wWnd;
  289. HDC hDC;
  290. HFONT hfontOld;
  291. PTASK pTask;
  292. // Get the Height and Width of the child window
  293. GetWindowRect (hwndLB, &rWnd);
  294. wWnd = rWnd.right - rWnd.left;
  295. lpmi->itemWidth = wWnd;
  296. pTask = (PTASK)lpmi->itemData;
  297. hDC= GetDC(NULL);
  298. if( (hfontOld = SelectObject(hDC,g_hBoldFont)) != 0 )
  299. {
  300. rWnd.top = 0;
  301. rWnd.left = CXBORDER*2 + g_cxSmIcon;
  302. rWnd.right = lpmi->itemWidth - rWnd.left - CXBORDER*2 - g_cxSmIcon;
  303. rWnd.bottom = 0;
  304. DrawText(hDC,pTask->Text, lstrlen(pTask->Text),&rWnd, DT_CALCRECT | DT_WORDBREAK );
  305. SelectObject(hDC, hfontOld);
  306. }
  307. ReleaseDC(NULL,hDC);
  308. lpmi->itemHeight = rWnd.bottom + 2*CXBORDER;
  309. return TRUE;
  310. }
  311. //---------------------------------------------------------------------------
  312. //***************************************************************************
  313. //
  314. // <Function>()
  315. // <Explanation>
  316. //
  317. // ENTRY:
  318. // <Params>
  319. //
  320. // EXIT:
  321. // <Params>
  322. //
  323. //***************************************************************************
  324. LRESULT _HandleMeasureItem(HWND hwnd, MEASUREITEMSTRUCT *lpmi)
  325. {
  326. if (lpmi->CtlType == ODT_LISTBOX)
  327. return _HandleLBMeasureItem(hwnd, lpmi);
  328. return TRUE;
  329. }
  330. //---------------------------------------------------------------------------
  331. //***************************************************************************
  332. //
  333. // _HandleLBDrawItem()
  334. // Draws the Title, Text, and icon for an entry.
  335. //
  336. // ENTRY:
  337. // HWND and the Item to draw.
  338. //
  339. // EXIT:
  340. // <Params>
  341. //
  342. //***************************************************************************
  343. LRESULT _HandleLBDrawItem(HWND hwndLB, DRAWITEMSTRUCT *lpdi)
  344. {
  345. RECT rc;
  346. HFONT hfontOld;
  347. int xArrow,y;
  348. PTASK pTask;
  349. BITMAP bm;
  350. HGDIOBJ hbmArrow,hbmOld;
  351. // Don't draw anything for an empty list.
  352. if ((int)lpdi->itemID < 0)
  353. return TRUE;
  354. pTask = (PTASK)lpdi->itemData;
  355. if(pTask == (PTASK)LB_ERR || !pTask )
  356. return FALSE;
  357. if ((lpdi->itemAction & ODA_SELECT) || (lpdi->itemAction & ODA_DRAWENTIRE))
  358. {
  359. // Put in the Title text
  360. hfontOld = SelectObject(lpdi->hDC,(lpdi->itemState & ODS_SELECTED)?g_hBoldFont:g_hfont);
  361. ExtTextOut(lpdi->hDC,
  362. lpdi->rcItem.left+ CXBORDER*2 + g_cxSmIcon,
  363. lpdi->rcItem.top+CXBORDER,
  364. ETO_OPAQUE,
  365. &lpdi->rcItem,
  366. NULL, 0,
  367. NULL);
  368. rc.top = lpdi->rcItem.top + CXBORDER;
  369. rc.left = lpdi->rcItem.left + CXBORDER*2 + g_cxSmIcon;
  370. rc.right = lpdi->rcItem.right;
  371. rc.bottom = lpdi->rcItem.bottom;
  372. DrawText( lpdi->hDC,
  373. pTask->Text, lstrlen(pTask->Text),
  374. &rc,
  375. DT_WORDBREAK);
  376. SelectObject(lpdi->hDC, hfontOld);
  377. // Draw the little triangle thingies.
  378. if(lpdi->itemState & ODS_SELECTED)
  379. {
  380. if (!g_hdcMem)
  381. {
  382. g_hdcMem = CreateCompatibleDC(lpdi->hDC);
  383. }
  384. // selected SRCSTENCIL=0x00d8074a
  385. // not selected SRCAND.
  386. if (g_hdcMem)
  387. {
  388. hbmArrow = LoadBitmap(NULL, MAKEINTRESOURCE(OBM_MNARROW));
  389. GetObject(hbmArrow, sizeof(bm), &bm);
  390. hbmOld = SelectObject(g_hdcMem, hbmArrow);
  391. xArrow = lpdi->rcItem.left + CXBORDER; // - bm.bmWidth;
  392. y = ((g_SizeTextExt.cy - bm.bmHeight)/2) + CXBORDER + lpdi->rcItem.top;
  393. BitBlt(lpdi->hDC, xArrow, y, bm.bmWidth, bm.bmHeight, g_hdcMem, 0, 0, SRCAND); // dwRop);
  394. SelectObject(g_hdcMem, hbmOld);
  395. DeleteObject(hbmArrow);
  396. }
  397. }
  398. }
  399. return TRUE;
  400. }
  401. //---------------------------------------------------------------------------
  402. LRESULT _HandleCtlColorListbox(HWND hwnd, HDC hdc)
  403. {
  404. SetBkColor(hdc, GetSysColor(COLOR_BTNFACE));
  405. return (LRESULT) g_hbrBkGnd;
  406. }
  407. //---------------------------------------------------------------------------
  408. LRESULT _HandleDrawItem(HWND hwnd, DRAWITEMSTRUCT *lpdi)
  409. {
  410. if (lpdi->CtlType == ODT_LISTBOX)
  411. return _HandleLBDrawItem(hwnd, lpdi);
  412. return TRUE;
  413. }
  414. //---------------------------------------------------------------------------
  415. LRESULT _HandleDeleteItem(HWND hwnd, DELETEITEMSTRUCT *lpdi)
  416. {
  417. if(lpdi)
  418. if(lpdi->itemData)
  419. {
  420. LocalFree( (HLOCAL)lpdi->itemData );
  421. return TRUE;
  422. }
  423. return FALSE;
  424. }
  425. //***************************************************************************
  426. //
  427. // ShrinkToFit()
  428. // Makes the List box no bigger then it has to be
  429. // makes the parent window rsize to the LB size.
  430. //
  431. // ENTRY:
  432. // hwnd Parent
  433. // hwnd List box
  434. //
  435. // EXIT:
  436. //
  437. //***************************************************************************
  438. void ShrinkToFit( HWND hWnd, HWND hLb )
  439. {
  440. LONG lCount;
  441. LONG lNumItems;
  442. LONG lTotalHeight;
  443. LONG lHeight;
  444. RECT rWnd;
  445. LONG lChange;
  446. lNumItems = (LONG)SendMessage( hLb, LB_GETCOUNT, 0, 0L );
  447. lTotalHeight =0;
  448. for( lCount=0;lCount<lNumItems; lCount++ )
  449. {
  450. lHeight = (LONG)SendMessage( hLb, LB_GETITEMHEIGHT, lCount, 0L );
  451. lTotalHeight+=lHeight;
  452. }
  453. // Set the height of the ListBox to the number of items in it.
  454. GetWindowRect (hLb, &rWnd);
  455. SetWindowPos( hLb, hWnd, 0,0,
  456. rWnd.right - rWnd.left - (CXBORDER*2 + g_cxSmIcon) ,
  457. lTotalHeight,
  458. SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER );
  459. // Work out how much it changed in height
  460. lChange = lTotalHeight - (rWnd.bottom-rWnd.top);
  461. // Size the parent to fit around the child.
  462. GetWindowRect(hWnd, &rWnd);
  463. SetWindowPos( hWnd,0, 0,0,
  464. rWnd.right - rWnd.left,
  465. rWnd.bottom-rWnd.top + lChange,
  466. SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOZORDER );
  467. }
  468. //***************************************************************************
  469. //
  470. // <Function>()
  471. // <Explanation>
  472. //
  473. // ENTRY:
  474. // <Params>
  475. //
  476. // EXIT:
  477. // <Params>
  478. //
  479. //***************************************************************************
  480. LRESULT CALLBACK dlgProcRunOnce(
  481. HWND hWnd, // window handle
  482. UINT message, // type of message
  483. WPARAM uParam, // additional information
  484. LPARAM lParam) // additional information
  485. {
  486. int wmId, wmEvent;
  487. HANDLE hThread;
  488. switch (message)
  489. {
  490. case WM_DELETEITEM:
  491. return _HandleDeleteItem( hWnd, (LPDELETEITEMSTRUCT)lParam );
  492. case WM_MEASUREITEM:
  493. return _HandleMeasureItem(hWnd, (MEASUREITEMSTRUCT *) lParam);
  494. case WM_DRAWITEM:
  495. return _HandleDrawItem(hWnd, (DRAWITEMSTRUCT *) lParam);
  496. case WM_INITDIALOG:
  497. CreateGlobals( hWnd );
  498. DoAnyRandomOneTimeStuff();
  499. g_fCleanBoot = GetSystemMetrics(SM_CLEANBOOT);
  500. TopLeftWindow( hWnd, GetParent(hWnd) );
  501. RunOnceFill( GetDlgItem(hWnd,IDC_LIST2) );
  502. // Now calculate the size needed for the LB and resize LB and parent.
  503. ShrinkToFit( hWnd, GetDlgItem(hWnd,IDC_LIST2));
  504. hThread = CreateThread(NULL, 0, RunAppsInList, (LPVOID)GetDlgItem(hWnd,IDC_LIST2),0, &g_dwThread );
  505. CloseHandle(hThread);
  506. break;
  507. case WM_FINISHED:
  508. EndDialog(hWnd,0);
  509. // DestroyWindow(hWnd);
  510. break;
  511. case WM_CTLCOLORLISTBOX:
  512. return _HandleCtlColorListbox((HWND)lParam, (HDC)uParam);
  513. case WM_COMMAND: // message: command from application menu
  514. wmId = LOWORD(uParam);
  515. wmEvent = HIWORD(uParam);
  516. if( wmEvent==LBN_SELCHANGE )
  517. {
  518. // LaunchApp( (HWND) lParam, LOWORD(uParam) );
  519. // De-select the item now.
  520. break;
  521. }
  522. else
  523. switch (wmId)
  524. {
  525. case IDOK:
  526. EndDialog( hWnd, wmId);
  527. break;
  528. default:
  529. // return (DefWindowProc(hWnd, message, uParam, lParam));
  530. break;
  531. }
  532. break;
  533. default: // Passes it on if unproccessed
  534. // return (DefWindowProc(hWnd, message, uParam, lParam));
  535. return FALSE;
  536. }
  537. return TRUE;
  538. }