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.

523 lines
13 KiB

  1. #include "setupp.h"
  2. #pragma hdrstop
  3. #include <winuserp.h>
  4. PCWSTR szWindowClass = L"$$$SetupBackground";
  5. //
  6. // Window longs for background window.
  7. //
  8. #define XWL_BITMAP (0)
  9. #define XWL_LOGO (XWL_BITMAP + sizeof(PVOID))
  10. #define XWL_BANNER (XWL_LOGO + sizeof(PVOID))
  11. #define XWL_FONT (XWL_BANNER + sizeof(PVOID))
  12. #define WL_COUNT (4 * sizeof(PVOID))
  13. #define POINTSIZE_WASHTEXT 24
  14. HANDLE SetupWindowThreadHandle = NULL;
  15. VOID
  16. SetupMakeSureFontIsAvailable()
  17. {
  18. static BOOL DoneAlready = FALSE;
  19. LONG l;
  20. HKEY hKey;
  21. DWORD i;
  22. WCHAR Name[256];
  23. WCHAR Data[256];
  24. DWORD s1;
  25. DWORD s2;
  26. DWORD Type;
  27. DWORD Result;
  28. if(DoneAlready) {
  29. return;
  30. }
  31. //
  32. // Want MS Serif but don't know which one serife.fon, seriffg.fon, etc.
  33. //
  34. l = RegOpenKeyEx(
  35. HKEY_LOCAL_MACHINE,
  36. L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
  37. 0,
  38. KEY_QUERY_VALUE,
  39. &hKey
  40. );
  41. if(l == NO_ERROR) {
  42. i = 0;
  43. s1 = 256;
  44. s2 = 256;
  45. while(RegEnumValueW(hKey,i,Name,&s1,NULL,&Type,(LPBYTE) Data,&s2)
  46. == NO_ERROR) {
  47. if(Type == REG_SZ) {
  48. CharUpper(Name);
  49. if(wcsstr(Name,L"MS SERIF")) {
  50. //
  51. // Value data is filename.
  52. //
  53. GetWindowsDirectory(Name,256);
  54. lstrcat(Name,L"\\FONTS\\");
  55. lstrcat(Name,Data);
  56. if(AddFontResource(Name)) {
  57. DoneAlready = TRUE;
  58. break;
  59. }
  60. }
  61. }
  62. i++;
  63. s1 = 256;
  64. s2 = 256;
  65. }
  66. RegCloseKey(hKey);
  67. }
  68. //
  69. // One last-ditch effort
  70. //
  71. if(!DoneAlready) {
  72. Result = GetWindowsDirectory(Name,256);
  73. if( Result == 0) {
  74. MYASSERT(FALSE);
  75. return;
  76. }
  77. lstrcat(Name,L"\\FONTS\\SERIFE.FON");
  78. if(AddFontResource(Name)) {
  79. DoneAlready = TRUE;
  80. }
  81. }
  82. }
  83. LRESULT
  84. SetupBackgroundWndProc(
  85. IN HWND hwnd,
  86. IN UINT msg,
  87. IN WPARAM wParam,
  88. IN LPARAM lParam
  89. )
  90. {
  91. LRESULT l;
  92. HBITMAP hbm;
  93. LOGFONT LogFont;
  94. HFONT hFont;
  95. HDC hdc;
  96. HDC hdcMem;
  97. PAINTSTRUCT ps;
  98. RECT rc;
  99. COLORREF crBk,crTx;
  100. BITMAP bitmap;
  101. HBITMAP hbmOld;
  102. HFONT hFontOld;
  103. WCHAR Buffer[MAX_PATH];
  104. int OldMode;
  105. int i;
  106. PWSTR p;
  107. switch(msg) {
  108. case WM_CREATE:
  109. //
  110. // Load the default background bitmap and indicate no oem logo bitmap.
  111. //
  112. #if 0
  113. hbm = LoadBitmap(
  114. MyModuleHandle,
  115. (ProductType == PRODUCT_WORKSTATION) ?
  116. MAKEINTRESOURCE(IDB_BACKGROUND_WORKSTATION) :
  117. MAKEINTRESOURCE(IDB_BACKGROUND_SERVER)
  118. );
  119. #else
  120. GetSystemDirectory( Buffer, MAX_PATH );
  121. pSetupConcatenatePaths(Buffer,TEXT("setup.bmp"),MAX_PATH,NULL);
  122. hbm = (HBITMAP)LoadImage(NULL,Buffer,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
  123. #endif
  124. SetWindowLongPtr(hwnd,XWL_BITMAP,(LONG_PTR)hbm);
  125. SetWindowLongPtr(hwnd,XWL_LOGO,0);
  126. #if 0 // Don't show any text for now.
  127. //
  128. // Load default banner text.
  129. //
  130. LoadString(MyModuleHandle,IDS_WINNT_SETUP,Buffer,sizeof(Buffer)/sizeof(WCHAR));
  131. SetWindowLongPtr(hwnd,XWL_BANNER,(LONG_PTR)pSetupDuplicateString(Buffer));
  132. #endif
  133. //
  134. // Create font used to display text in upper left corner.
  135. //
  136. hdc = GetDC(hwnd);
  137. if( hdc ) {
  138. i = GetDeviceCaps(hdc,LOGPIXELSY);
  139. ReleaseDC(hwnd,hdc);
  140. SetupMakeSureFontIsAvailable();
  141. ZeroMemory(&LogFont,sizeof(LOGFONT));
  142. LogFont.lfHeight = -1 * (i * POINTSIZE_WASHTEXT / 72);
  143. LogFont.lfWeight = FW_DONTCARE;
  144. LogFont.lfCharSet = DEFAULT_CHARSET;
  145. LogFont.lfQuality = PROOF_QUALITY;
  146. LogFont.lfPitchAndFamily = DEFAULT_PITCH | FF_ROMAN;
  147. lstrcpy(LogFont.lfFaceName,L"MS Serif");
  148. hFont = CreateFontIndirect(&LogFont);
  149. SetWindowLongPtr(hwnd,XWL_FONT,(LONG_PTR)hFont);
  150. }
  151. //
  152. // Allow window creation to continue.
  153. //
  154. l = 0;
  155. break;
  156. case WM_NEWBITMAP:
  157. //
  158. // wParam tells us which bitmap; lParam is the bitmap handle
  159. // (or pointer to a banner string).
  160. //
  161. switch(wParam) {
  162. case SetupBmBackground:
  163. if(hbmOld = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) {
  164. DeleteObject(hbmOld);
  165. }
  166. SetWindowLongPtr(hwnd,XWL_BITMAP,lParam);
  167. break;
  168. case SetupBmLogo:
  169. if(hbmOld = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) {
  170. DeleteObject(hbmOld);
  171. }
  172. SetWindowLongPtr(hwnd,XWL_LOGO,lParam);
  173. break;
  174. case SetupBmBanner:
  175. if(p = (PWSTR)GetWindowLongPtr(hwnd,XWL_BANNER)) {
  176. MyFree(p);
  177. }
  178. SetWindowLongPtr(hwnd,XWL_BANNER,lParam);
  179. break;
  180. }
  181. l = 0;
  182. break;
  183. case WM_PAINT:
  184. #define BANNER_OFFSET_X 5
  185. #define BANNER_OFFSET_Y 5
  186. //
  187. // The window class has CS_OWNDC so BeginPaint will succeed.
  188. //
  189. BeginPaint(hwnd,&ps);
  190. GetClientRect(hwnd,&rc);
  191. if(hdcMem = CreateCompatibleDC(ps.hdc)) {
  192. crBk = SetBkColor(ps.hdc,RGB(0,0,128));
  193. crTx = SetTextColor(ps.hdc,RGB(0,0,0));
  194. if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) {
  195. if(hbmOld = SelectObject(hdcMem,hbm)) {
  196. GetObject(hbm,sizeof(BITMAP),&bitmap);
  197. BitBlt(
  198. ps.hdc,
  199. rc.left + (((rc.right - rc.left) - bitmap.bmWidth) / 2),
  200. rc.top + (((rc.bottom - rc.top) - bitmap.bmHeight) / 2),
  201. bitmap.bmWidth,
  202. bitmap.bmHeight,
  203. hdcMem,
  204. 0,0,
  205. SRCCOPY
  206. );
  207. SelectObject(hdcMem,hbmOld);
  208. }
  209. }
  210. if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) {
  211. SetBkColor(ps.hdc,RGB(255,255,255));
  212. SetTextColor(ps.hdc,RGB(0,0,0));
  213. if(hbmOld = SelectObject(hdcMem,hbm)) {
  214. GetObject(hbm,sizeof(BITMAP),&bitmap);
  215. BitBlt(
  216. ps.hdc,
  217. (rc.right - bitmap.bmWidth) - BANNER_OFFSET_X,
  218. rc.top + BANNER_OFFSET_Y,
  219. bitmap.bmWidth,
  220. bitmap.bmHeight,
  221. hdcMem,
  222. 0,0,
  223. SRCCOPY
  224. );
  225. SelectObject(hdcMem,hbmOld);
  226. }
  227. }
  228. SetBkColor(ps.hdc,crBk);
  229. SetTextColor(ps.hdc,crTx);
  230. DeleteDC(hdcMem);
  231. }
  232. hFont = (HFONT)GetWindowLongPtr(hwnd,XWL_FONT);
  233. if(hFont) {
  234. hFontOld = SelectObject(ps.hdc,hFont);
  235. } else {
  236. hFontOld = NULL;
  237. }
  238. crTx = SetTextColor(ps.hdc,RGB(255,255,255));
  239. OldMode = SetBkMode(ps.hdc,TRANSPARENT);
  240. if(p = (PWSTR)GetWindowLongPtr(hwnd,XWL_BANNER)) {
  241. //
  242. // Use this API so we get CR/LF to break a line
  243. //
  244. rc.left += BANNER_OFFSET_X;
  245. rc.top += BANNER_OFFSET_Y;
  246. DrawText(ps.hdc,p,-1,&rc,DT_NOPREFIX);
  247. }
  248. SetTextColor(ps.hdc,crTx);
  249. if(OldMode) {
  250. SetBkMode(ps.hdc,OldMode);
  251. }
  252. if(hFontOld) {
  253. SelectObject(ps.hdc,hFontOld);
  254. }
  255. EndPaint(hwnd,&ps);
  256. l = 0;
  257. break;
  258. case WM_DESTROY:
  259. //
  260. // Clean up.
  261. //
  262. if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_BITMAP)) {
  263. DeleteObject(hbm);
  264. }
  265. if(hbm = (HBITMAP)GetWindowLongPtr(hwnd,XWL_LOGO)) {
  266. DeleteObject(hbm);
  267. }
  268. if(hFont = (HFONT)GetWindowLongPtr(hwnd,XWL_FONT)) {
  269. DeleteObject(hFont);
  270. }
  271. TerminateBillBoard();
  272. PostQuitMessage(0);
  273. l = 0;
  274. break;
  275. case WM_EXIT_SETUPWINDOW:
  276. DestroyWindow(hwnd);
  277. l = 0;
  278. break;
  279. case WM_HOTKEY:
  280. if (wParam == 0x6969) {
  281. //
  282. // Do this to make sure we get the correct cmd.exe, not whatever
  283. // is in our current path.
  284. //
  285. WCHAR Path[MAX_PATH];
  286. WCHAR CmdLine[MAX_PATH];
  287. ExpandEnvironmentStrings(
  288. L"%SystemRoot%\\system32\\cmd.exe",
  289. Path,
  290. MAX_PATH);
  291. wsprintf(CmdLine, L"/c start %s", Path);
  292. InvokeExternalApplication(Path,CmdLine,NULL);
  293. }
  294. else if (wParam == 0xC2C2)
  295. {
  296. // User pressed key to make the wizard visible.
  297. // does not stop the billboard.
  298. if (WizardHandle)
  299. {
  300. SendMessage(WizardHandle, WMX_BBTEXT, (WPARAM)FALSE, 0);
  301. }
  302. }
  303. l = 0;
  304. break;
  305. default:
  306. l = DefWindowProc(hwnd,msg,wParam,lParam);
  307. break;
  308. }
  309. return(l);
  310. }
  311. DWORD
  312. SetupWindowThread(
  313. PVOID ThreadParam
  314. )
  315. {
  316. WNDCLASS wc;
  317. HWND hwnd;
  318. HWND hwndBB = NULL;
  319. DWORD ThreadId;
  320. MSG msg;
  321. BOOL b;
  322. WCHAR Buffer[128];
  323. HMODULE hmodSyssetup = NULL;
  324. //
  325. // The thread param is actually the thread id of the main thread.
  326. //
  327. ThreadId = (DWORD)((DWORD_PTR)ThreadParam);
  328. hwnd = NULL;
  329. wc.style = CS_NOCLOSE | CS_OWNDC;
  330. wc.lpfnWndProc = SetupBackgroundWndProc;
  331. wc.cbClsExtra = 0;
  332. wc.cbWndExtra = WL_COUNT;
  333. wc.hInstance = MyModuleHandle;
  334. wc.hIcon = LoadIcon(MyModuleHandle,MAKEINTRESOURCE(IDI_SETUP));
  335. wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  336. //
  337. // Background will be erased to black, which is what we want.
  338. //
  339. wc.hbrBackground = GetStockObject(BLACK_BRUSH);
  340. wc.lpszMenuName = NULL;
  341. wc.lpszClassName = szWindowClass;
  342. if(RegisterClass(&wc)) {
  343. // add an extra dllref that holds syssetup.dll in process for the lifetime of the
  344. // $$$SetupBackground window.
  345. hmodSyssetup = LoadLibrary(TEXT("syssetup.dll"));
  346. LoadString(MyModuleHandle,IDS_WINNT_SETUP,Buffer,sizeof(Buffer)/sizeof(WCHAR));
  347. hwnd = CreateWindow(
  348. szWindowClass,
  349. Buffer, // L"Windows NT Setup",
  350. WS_POPUP | WS_CLIPCHILDREN,
  351. 0,0,
  352. GetSystemMetrics(SM_CXSCREEN),
  353. GetSystemMetrics(SM_CYSCREEN),
  354. NULL,
  355. NULL,
  356. MyModuleHandle,
  357. 0
  358. );
  359. SetupWindowHandle = hwnd;
  360. if(hwnd) {
  361. ShowWindow(hwnd,SW_SHOW);
  362. //
  363. // Make this window bottommost.
  364. //
  365. SetShellWindow(hwnd);
  366. RegisterHotKey(hwnd,0x6969,MOD_SHIFT,VK_F10);
  367. RegisterHotKey(hwnd,0xC2C2,MOD_SHIFT,VK_F11);
  368. }
  369. }
  370. if (!MiniSetup)
  371. {
  372. PrepareBillBoard(hwnd);
  373. // If we have a Billboard, assign hwnd the windows handle.
  374. // That way all dialogs have the billboard as the parent.
  375. // hwnd is returned by CreateSetupWindow and assinged to MainWindowHandle
  376. hwndBB = GetBBhwnd();
  377. if (hwndBB != NULL)
  378. hwnd = hwndBB;
  379. }
  380. if(ThreadId != (DWORD)(-1)) {
  381. //
  382. // Called as a thread. Need to tell the main thread
  383. // the window handle.
  384. //
  385. PostThreadMessage(ThreadId,WM_MY_STATUS,0,(LPARAM)hwnd);
  386. //
  387. // Pump the message queue for this thread.
  388. //
  389. while((b = GetMessage(&msg,NULL,0,0)) && (b != (BOOL)(-1))) {
  390. DispatchMessage(&msg);
  391. }
  392. }
  393. if (hmodSyssetup)
  394. {
  395. FreeLibraryAndExitThread(hmodSyssetup, HandleToUlong(hwnd));
  396. }
  397. return HandleToUlong(hwnd);
  398. }
  399. HWND
  400. CreateSetupWindow(
  401. VOID
  402. )
  403. {
  404. HANDLE ThreadHandle;
  405. DWORD ThreadId;
  406. HWND hwnd;
  407. MSG msg;
  408. //
  409. // Create a thread that will in turn create and own the window.
  410. // This way, the window is always responsive and redraws correctly
  411. // without special processing requirements.
  412. //
  413. SetupWindowThreadHandle = CreateThread(
  414. NULL,
  415. 0,
  416. SetupWindowThread,
  417. LongToPtr( GetCurrentThreadId() ),
  418. 0,
  419. &ThreadId
  420. );
  421. if(SetupWindowThreadHandle) {
  422. //
  423. // Wait for the thread to tell us whether it could
  424. // create the window or not.
  425. //
  426. do {
  427. WaitMessage();
  428. } while(!PeekMessage(&msg,(HWND)(-1),WM_MY_STATUS,WM_MY_STATUS,PM_REMOVE));
  429. hwnd = (HWND)msg.lParam;
  430. } else {
  431. //
  432. // Unable to create the thread. Do it the old fashioned way;
  433. // this is better than nothing and at least setup will continue.
  434. //
  435. hwnd = (HWND)LongToHandle( SetupWindowThread((PVOID)(-1)) );
  436. }
  437. return(hwnd);
  438. }