Leaked source code of windows server 2003
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.

1751 lines
52 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: dtbitmap.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Desktop Wallpaper Routines.
  7. *
  8. * History:
  9. * 29-Jul-1991 MikeKe From win31
  10. \***************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*
  14. * Local Constants.
  15. */
  16. #define MAXPAL 256
  17. #define MAXSTATIC 20
  18. #define TILE_XMINSIZE 2
  19. #define TILE_YMINSIZE 4
  20. /*
  21. * The version strings are stored in a contiguous-buffer. Each string
  22. * is of size MAXVERSIONSTRING.
  23. */
  24. // Size of each string buffer.
  25. #define MAXVERSIONSTRING 128
  26. // Offset into verbuffer of build-string.
  27. #define OFFSET_BLDSTRING 0
  28. // Offset into verbuffer of CSD string.
  29. #define OFFSET_CSDSTRING OFFSET_BLDSTRING + MAXVERSIONSTRING
  30. // Max size of buffer (contains all 3 strings).
  31. #define MAXVERSIONBUFFER OFFSET_CSDSTRING + MAXVERSIONSTRING
  32. WCHAR wszSafeMode[MAX_PATH + 3 * MAXVERSIONSTRING];
  33. WCHAR SafeModeStr[64];
  34. int SafeModeStrLen;
  35. WCHAR wszProductName[MAXVERSIONSTRING];
  36. WCHAR wszProductBuild[2 * MAXVERSIONSTRING];
  37. __inline PWND _GetShellWindow(
  38. PDESKTOP pdesk)
  39. {
  40. if (pdesk == NULL) {
  41. return NULL;
  42. } else {
  43. return pdesk->pDeskInfo->spwndShell;
  44. }
  45. }
  46. /***************************************************************************\
  47. * GetVersionInfo
  48. *
  49. * Outputs a string on the desktop indicating debug-version.
  50. *
  51. * History:
  52. \***************************************************************************/
  53. VOID
  54. GetVersionInfo(
  55. BOOL Verbose)
  56. {
  57. WCHAR NameBuffer[MAXVERSIONBUFFER];
  58. WCHAR Title1[MAXVERSIONSTRING];
  59. WCHAR Title2[MAXVERSIONSTRING];
  60. WCHAR wszPID[MAXVERSIONSTRING];
  61. WCHAR wszProduct[MAXVERSIONSTRING];
  62. WCHAR wszPBuild[MAXVERSIONSTRING];
  63. WCHAR wszEvaluation[MAXVERSIONSTRING];
  64. UNICODE_STRING UserBuildString;
  65. UNICODE_STRING UserCSDString;
  66. NTSTATUS Status;
  67. UINT uProductStrId;
  68. /*
  69. * Temporary code name handling. Used internally and turned off by ""
  70. * for release. The matching string in strid.mc doesn't have a space
  71. * separator between code name and the rest of the title, so this
  72. * space must be included at end of this code name string.
  73. */
  74. WCHAR wszCodeName[] = L"";
  75. RTL_QUERY_REGISTRY_TABLE BaseServerRegistryConfigurationTable[] = {
  76. {NULL,
  77. RTL_QUERY_REGISTRY_DIRECT,
  78. #ifdef PRERELEASE
  79. L"BuildLab",
  80. #else
  81. L"CurrentBuildNumber",
  82. #endif // PRERELEASE
  83. &UserBuildString,
  84. REG_NONE,
  85. NULL,
  86. 0},
  87. {NULL,
  88. RTL_QUERY_REGISTRY_DIRECT,
  89. L"CSDVersion",
  90. &UserCSDString,
  91. REG_NONE,
  92. NULL,
  93. 0},
  94. {NULL,
  95. 0,
  96. NULL,
  97. NULL,
  98. REG_NONE,
  99. NULL,
  100. 0}
  101. };
  102. UserBuildString.Buffer = &NameBuffer[OFFSET_BLDSTRING];
  103. UserBuildString.Length = 0;
  104. UserBuildString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
  105. UserCSDString.Buffer = &NameBuffer[OFFSET_CSDSTRING];
  106. UserCSDString.Length = 0;
  107. UserCSDString.MaximumLength = MAXVERSIONSTRING * sizeof(WCHAR);
  108. Status = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  109. L"",
  110. BaseServerRegistryConfigurationTable,
  111. NULL,
  112. NULL);
  113. if (!NT_SUCCESS(Status)) {
  114. RIPMSG1(RIP_WARNING, "GetVersionInfo failed with status %x", Status);
  115. return;
  116. }
  117. ServerLoadString(hModuleWin, STR_DTBS_PRODUCTID, wszPID, ARRAY_SIZE(wszPID));
  118. ServerLoadString(hModuleWin, STR_DTBS_PRODUCTBUILD, wszPBuild, ARRAY_SIZE(wszPBuild));
  119. /*
  120. * Write out Debugging Version message.
  121. */
  122. /*
  123. * Bug 280256 - joejo
  124. * Create new desktop build information strings
  125. */
  126. if (USER_SHARED_DATA->SuiteMask & (1 << EmbeddedNT)) {
  127. uProductStrId = STR_DTBS_PRODUCTEMB;
  128. } else if (USER_SHARED_DATA->NtProductType == NtProductWinNt) {
  129. #ifdef _WIN64
  130. uProductStrId = STR_DTBS_PRODUCTWKS64;
  131. #else
  132. if (USER_SHARED_DATA->SuiteMask & (1 << Personal)) {
  133. uProductStrId = STR_DTBS_PRODUCTPER;
  134. } else {
  135. uProductStrId = STR_DTBS_PRODUCTPRO;
  136. }
  137. #endif
  138. } else {
  139. #ifdef _WIN64
  140. if (USER_SHARED_DATA->SuiteMask & (1 << DataCenter)) {
  141. uProductStrId = STR_DTBS_PRODUCTDTC64;
  142. } else if (USER_SHARED_DATA->SuiteMask & (1 << Enterprise)) {
  143. uProductStrId = STR_DTBS_PRODUCTADV64;
  144. } else {
  145. uProductStrId = STR_DTBS_PRODUCTSRV64;
  146. }
  147. #else
  148. if (USER_SHARED_DATA->SuiteMask & (1 << DataCenter)) {
  149. uProductStrId = STR_DTBS_PRODUCTDTC;
  150. } else if (USER_SHARED_DATA->SuiteMask & (1 << Enterprise)) {
  151. uProductStrId = STR_DTBS_PRODUCTADV;
  152. } else if (USER_SHARED_DATA->SuiteMask & (1 << Blade)) {
  153. uProductStrId = STR_DTBS_PRODUCTBLA;
  154. } else if(USER_SHARED_DATA->SuiteMask & (1 << SmallBusinessRestricted)) {
  155. uProductStrId = STR_DTBS_PRODUCTSBS;
  156. } else {
  157. uProductStrId = STR_DTBS_PRODUCTSRV;
  158. }
  159. #endif /* _WIN64 */
  160. }
  161. ServerLoadString(hModuleWin, uProductStrId, wszProduct, ARRAY_SIZE(wszProduct));
  162. swprintf(
  163. wszProductName,
  164. wszPID,
  165. wszCodeName,
  166. wszProduct);
  167. if (gfUnsignedDrivers) {
  168. /* This takes precedence */
  169. ServerLoadString(hModuleWin, STR_TESTINGONLY, wszEvaluation, ARRAY_SIZE(wszEvaluation));
  170. } else if (USER_SHARED_DATA->SystemExpirationDate.QuadPart) {
  171. ServerLoadString(hModuleWin, STR_DTBS_EVALUATION, wszEvaluation, ARRAY_SIZE(wszEvaluation));
  172. } else {
  173. wszEvaluation[0] = '\0';
  174. }
  175. swprintf(
  176. wszProductBuild,
  177. wszPBuild,
  178. wszEvaluation,
  179. UserBuildString.Buffer
  180. );
  181. if (Verbose) {
  182. ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE1, Title1, ARRAY_SIZE(Title1));
  183. ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE2, Title2, ARRAY_SIZE(Title2));
  184. swprintf(
  185. wszSafeMode,
  186. UserCSDString.Length == 0 ? Title1 : Title2,
  187. wszCodeName,
  188. UserBuildString.Buffer,
  189. UserCSDString.Buffer,
  190. USER_SHARED_DATA->NtSystemRoot
  191. );
  192. } else {
  193. ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE3, Title1, ARRAY_SIZE(Title1));
  194. ServerLoadString(hModuleWin, STR_SAFEMODE_TITLE4, Title2, ARRAY_SIZE(Title2));
  195. swprintf(
  196. wszSafeMode,
  197. UserCSDString.Length == 0 ? Title1 : Title2,
  198. wszCodeName,
  199. UserBuildString.Buffer,
  200. UserCSDString.Buffer);
  201. }
  202. }
  203. /***************************************************************************\
  204. * GetDefaultWallpaperName
  205. *
  206. * Get initial bitmap name
  207. *
  208. * History:
  209. * 21-Feb-1995 JimA Created.
  210. * 06-Mar-1996 ChrisWil Moved to kernel to facilite ChangeDisplaySettings.
  211. \***************************************************************************/
  212. VOID
  213. GetDefaultWallpaperName(
  214. LPWSTR lpszWallpaper)
  215. {
  216. /*
  217. * Set the initial global wallpaper bitmap name for (Default)
  218. * The global name is an at most 8 character name with no
  219. * extension. It is "winnt" for workstation or "lanmannt"
  220. * for server or server upgrade. It is followed by 256 it
  221. * is for 256 color devices.
  222. */
  223. if (USER_SHARED_DATA->NtProductType == NtProductWinNt) {
  224. wcsncpycch(lpszWallpaper, L"winnt", 8);
  225. } else {
  226. wcsncpycch(lpszWallpaper, L"lanmannt", 8);
  227. }
  228. lpszWallpaper[8] = (WCHAR)0;
  229. if (gpsi->BitsPixel * gpsi->Planes > 4) {
  230. int iStart = wcslen(lpszWallpaper);
  231. iStart = min(iStart, 5);
  232. lpszWallpaper[iStart] = (WCHAR)0;
  233. wcscat(lpszWallpaper, L"256");
  234. }
  235. }
  236. /***************************************************************************\
  237. * GetDeskWallpaperName
  238. *
  239. * History:
  240. * 19-Dec-1994 JimA Created.
  241. * 29-Sep-1995 ChrisWil ReWrote to return filename.
  242. \***************************************************************************/
  243. #define GDWPN_KEYSIZE 40
  244. #define GDWPN_BITSIZE 256
  245. LPWSTR GetDeskWallpaperName(PUNICODE_STRING pProfileUserName,
  246. LPWSTR lpszFile
  247. )
  248. {
  249. WCHAR wszKey[GDWPN_KEYSIZE];
  250. WCHAR wszNone[GDWPN_KEYSIZE];
  251. LPWSTR lpszBitmap = NULL;
  252. /*
  253. * Load the none-string. This will be used for comparisons later.
  254. */
  255. ServerLoadString(hModuleWin, STR_NONE, wszNone, ARRAY_SIZE(wszNone));
  256. if ((lpszFile == NULL) ||
  257. (lpszFile == SETWALLPAPER_DEFAULT) ||
  258. (lpszFile == SETWALLPAPER_METRICS)) {
  259. /*
  260. * Allocate a buffer for the wallpaper. We will assume
  261. * a default-size in this case.
  262. */
  263. lpszBitmap = UserAllocPool(GDWPN_BITSIZE * sizeof(WCHAR), TAG_SYSTEM);
  264. if (lpszBitmap == NULL)
  265. return NULL;
  266. /*
  267. * Get the "Wallpaper" string from WIN.INI's [Desktop] section. The
  268. * section name is not localized, so hard code it. If the string
  269. * returned is Empty, then set it up for a none-wallpaper.
  270. *
  271. * Unlike the rest of per user settings that got updated in
  272. * xxxUpdatePerUserSystemParameters, wallpaper is being updated via a
  273. * direct call to SystemParametersInfo from UpdatePerUserSystemParameters.
  274. * Force remote settings check in this case.
  275. */
  276. if (!FastGetProfileStringFromIDW(pProfileUserName,
  277. PMAP_DESKTOP,
  278. STR_DTBITMAP,
  279. wszNone,
  280. lpszBitmap,
  281. GDWPN_BITSIZE,
  282. POLICY_REMOTE
  283. )) {
  284. wcscpy(lpszBitmap, wszNone);
  285. }
  286. } else {
  287. UINT uLen;
  288. uLen = wcslen(lpszFile) + 1;
  289. uLen = max(uLen, GDWPN_BITSIZE);
  290. /*
  291. * Allocate enough space to store the name passed in. Returning
  292. * NULL will allow the wallpaper to redraw. As well, if we're
  293. * out of memory, then no need to load a wallpaper anyway.
  294. */
  295. lpszBitmap = UserAllocPool(uLen * sizeof(WCHAR), TAG_SYSTEM);
  296. if (lpszBitmap == NULL)
  297. return NULL;
  298. wcscpy(lpszBitmap, lpszFile);
  299. }
  300. /*
  301. * No bitmap if NULL passed in or if (NONE) in win.ini entry. We
  302. * return NULL to force the redraw of the wallpaper in the kernel.
  303. */
  304. if ((*lpszBitmap == (WCHAR)0) || (_wcsicmp(lpszBitmap, wszNone) == 0)) {
  305. UserFreePool(lpszBitmap);
  306. return NULL;
  307. }
  308. /*
  309. * If bitmap name set to (DEFAULT) then set it to the system bitmap.
  310. */
  311. ServerLoadString(hModuleWin, STR_DEFAULT, wszKey, ARRAY_SIZE(wszKey));
  312. if (_wcsicmp(lpszBitmap, wszKey) == 0) {
  313. GetDefaultWallpaperName(lpszBitmap);
  314. }
  315. return lpszBitmap;
  316. }
  317. /***************************************************************************\
  318. * TestVGAColors
  319. *
  320. * Tests whether the log-palette is just a standard 20 palette.
  321. *
  322. * History:
  323. * 29-Sep-1995 ChrisWil Created.
  324. \***************************************************************************/
  325. BOOL TestVGAColors(
  326. LPLOGPALETTE ppal)
  327. {
  328. int i;
  329. int n;
  330. int size;
  331. COLORREF clr;
  332. static CONST DWORD StupidColors[] = {
  333. 0x00000000, // 0 Sys Black
  334. 0x00000080, // 1 Sys Dk Red
  335. 0x00008000, // 2 Sys Dk Green
  336. 0x00008080, // 3 Sys Dk Yellow
  337. 0x00800000, // 4 Sys Dk Blue
  338. 0x00800080, // 5 Sys Dk Violet
  339. 0x00808000, // 6 Sys Dk Cyan
  340. 0x00c0c0c0, // 7 Sys Lt Grey
  341. 0x00808080, // 248 Sys Lt Gray
  342. 0x000000ff, // 249 Sys Red
  343. 0x0000ff00, // 250 Sys Green
  344. 0x0000ffff, // 251 Sys Yellow
  345. 0x00ff0000, // 252 Sys Blue
  346. 0x00ff00ff, // 253 Sys Violet
  347. 0x00ffff00, // 254 Sys Cyan
  348. 0x00ffffff, // 255 Sys White
  349. 0x000000BF, // 1 Sys Dk Red again
  350. 0x0000BF00, // 2 Sys Dk Green again
  351. 0x0000BFBF, // 3 Sys Dk Yellow again
  352. 0x00BF0000, // 4 Sys Dk Blue again
  353. 0x00BF00BF, // 5 Sys Dk Violet again
  354. 0x00BFBF00, // 6 Sys Dk Cyan again
  355. 0x000000C0, // 1 Sys Dk Red again
  356. 0x0000C000, // 2 Sys Dk Green again
  357. 0x0000C0C0, // 3 Sys Dk Yellow again
  358. 0x00C00000, // 4 Sys Dk Blue again
  359. 0x00C000C0, // 5 Sys Dk Violet again
  360. 0x00C0C000, // 6 Sys Dk Cyan again
  361. };
  362. size = (sizeof(StupidColors) / sizeof(StupidColors[0]));
  363. for (i = 0; i < (int)ppal->palNumEntries; i++) {
  364. clr = ((LPDWORD)ppal->palPalEntry)[i];
  365. for (n = 0; n < size; n++) {
  366. if (StupidColors[n] == clr)
  367. break;
  368. }
  369. if (n == size)
  370. return FALSE;
  371. }
  372. return TRUE;
  373. }
  374. /***************************************************************************\
  375. * DoHTColorAdjustment
  376. *
  377. * The default HT-Gamma adjustment was 2.0 on 3.5 (internal to gdi). For
  378. * 3.51 this value was decreased to 1.0 to accomdate printing. For our
  379. * desktop-wallpaper we are going to darken it slightly to that the image
  380. * doesn't appear to light. For the Shell-Release we will provid a UI to
  381. * allow users to change this for themselves.
  382. *
  383. *
  384. * History:
  385. * 11-May-1995 ChrisWil Created.
  386. \***************************************************************************/
  387. #define FIXED_GAMMA (WORD)13000
  388. VOID DoHTColorAdjust(
  389. HDC hdc)
  390. {
  391. COLORADJUSTMENT ca;
  392. if (GreGetColorAdjustment(hdc, &ca)) {
  393. ca.caRedGamma =
  394. ca.caGreenGamma =
  395. ca.caBlueGamma = FIXED_GAMMA;
  396. GreSetColorAdjustment(hdc, &ca);
  397. }
  398. }
  399. /***************************************************************************\
  400. * ConvertToDDB
  401. *
  402. * Converts a DIBSection to a DDB. We do this to speed up drawings so that
  403. * bitmap-colors don't have to go through a palette-translation match. This
  404. * will also stretch/expand the image if the syle is set.
  405. *
  406. * If the new image requires a halftone-palette, the we will create one and
  407. * set it as the new wallpaper-palette.
  408. *
  409. * History:
  410. * 26-Oct-1995 ChrisWil Ported.
  411. * 30-Oct-1995 ChrisWil Added halftoning. Rewote the stretch/expand stuff.
  412. \***************************************************************************/
  413. HBITMAP ConvertToDDB(
  414. HDC hdc,
  415. HBITMAP hbmOld,
  416. HPALETTE hpal)
  417. {
  418. BITMAP bm;
  419. HBITMAP hbmNew;
  420. /*
  421. * This object must be a REALDIB type bitmap.
  422. */
  423. GreExtGetObjectW(hbmOld, sizeof(bm), &bm);
  424. /*
  425. * Create the new wallpaper-surface.
  426. */
  427. if (hbmNew = GreCreateCompatibleBitmap(hdc, bm.bmWidth, bm.bmHeight)) {
  428. HPALETTE hpalDst;
  429. HPALETTE hpalSrc;
  430. HBITMAP hbmDst;
  431. HBITMAP hbmSrc;
  432. UINT bpp;
  433. BOOL fHalftone = FALSE;
  434. /*
  435. * Select in the surfaces.
  436. */
  437. hbmDst = GreSelectBitmap(ghdcMem2, hbmNew);
  438. hbmSrc = GreSelectBitmap(ghdcMem, hbmOld);
  439. /*
  440. * Determine image bits/pixel.
  441. */
  442. bpp = (bm.bmPlanes * bm.bmBitsPixel);
  443. /*
  444. * Use the palette if given. If the image is of a greater
  445. * resolution than the device, then we're going to go through
  446. * a halftone-palette to get better colors.
  447. */
  448. if (hpal) {
  449. hpalDst = _SelectPalette(ghdcMem2, hpal, FALSE);
  450. hpalSrc = _SelectPalette(ghdcMem, hpal, FALSE);
  451. xxxRealizePalette(ghdcMem2);
  452. /*
  453. * Set the halftoning for the destination. This is done
  454. * for images of greater resolution than the device.
  455. */
  456. if (bpp > gpsi->BitCount) {
  457. fHalftone = TRUE;
  458. DoHTColorAdjust(ghdcMem2);
  459. }
  460. }
  461. /*
  462. * Set the stretchbltmode. This is more necessary when doing
  463. * halftoning. Since otherwise, the colors won't translate
  464. * correctly.
  465. */
  466. SetBestStretchMode(ghdcMem2, bpp, fHalftone);
  467. /*
  468. * Set the new surface bits. Use StretchBlt() so the SBMode
  469. * will be used in color-translation.
  470. */
  471. GreStretchBlt(ghdcMem2,
  472. 0,
  473. 0,
  474. bm.bmWidth,
  475. bm.bmHeight,
  476. ghdcMem,
  477. 0,
  478. 0,
  479. bm.bmWidth,
  480. bm.bmHeight,
  481. SRCCOPY,
  482. 0);
  483. /*
  484. * Restore palettes.
  485. */
  486. if (hpal) {
  487. _SelectPalette(ghdcMem2, hpalDst, FALSE);
  488. _SelectPalette(ghdcMem, hpalSrc, FALSE);
  489. }
  490. /*
  491. * Restore the surfaces.
  492. */
  493. GreSelectBitmap(ghdcMem2, hbmDst);
  494. GreSelectBitmap(ghdcMem, hbmSrc);
  495. GreDeleteObject(hbmOld);
  496. GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
  497. } else {
  498. hbmNew = hbmOld;
  499. }
  500. return hbmNew;
  501. }
  502. /***************************************************************************\
  503. * CreatePaletteFromBitmap
  504. *
  505. * Take in a REAL dib handle and create a palette from it. This will not
  506. * work for bitmaps created by any other means than CreateDIBSection or
  507. * CreateDIBitmap(CBM_CREATEDIB). This is due to the fact that these are
  508. * the only two formats who have palettes stored with their object.
  509. *
  510. * History:
  511. * 29-Sep-1995 ChrisWil Created.
  512. \***************************************************************************/
  513. HPALETTE CreatePaletteFromBitmap(
  514. HBITMAP hbm)
  515. {
  516. HPALETTE hpal;
  517. LPLOGPALETTE ppal;
  518. HBITMAP hbmT;
  519. DWORD size;
  520. int i;
  521. /*
  522. * Make room for temp logical palette of max size.
  523. */
  524. size = sizeof(LOGPALETTE) + (MAXPAL * sizeof(PALETTEENTRY));
  525. ppal = (LPLOGPALETTE)UserAllocPool(size, TAG_SYSTEM);
  526. if (!ppal)
  527. return NULL;
  528. /*
  529. * Retrieve the palette from the DIB(Section). The method of calling
  530. * GreGetDIBColorTable() can only be done on sections or REAL-Dibs.
  531. */
  532. hbmT = GreSelectBitmap(ghdcMem, hbm);
  533. ppal->palVersion = 0x300;
  534. ppal->palNumEntries = (WORD)GreGetDIBColorTable(ghdcMem,
  535. 0,
  536. MAXPAL,
  537. (LPRGBQUAD)ppal->palPalEntry);
  538. GreSelectBitmap(ghdcMem, hbmT);
  539. /*
  540. * Create a halftone-palette if their are no entries. Otherwise,
  541. * swap the RGB values to be palentry-compatible and create us a
  542. * palette.
  543. */
  544. if (ppal->palNumEntries == 0) {
  545. hpal = GreCreateHalftonePalette(gpDispInfo->hdcScreen);
  546. } else {
  547. BYTE tmpR;
  548. /*
  549. * Swap red/blue because a RGBQUAD and PALETTEENTRY dont get along.
  550. */
  551. for (i=0; i < (int)ppal->palNumEntries; i++) {
  552. tmpR = ppal->palPalEntry[i].peRed;
  553. ppal->palPalEntry[i].peRed = ppal->palPalEntry[i].peBlue;
  554. ppal->palPalEntry[i].peBlue = tmpR;
  555. ppal->palPalEntry[i].peFlags = 0;
  556. }
  557. /*
  558. * If the Bitmap only has VGA colors in it we dont want to
  559. * use a palette. It just causes unessesary palette flashes.
  560. */
  561. hpal = TestVGAColors(ppal) ? NULL : GreCreatePalette(ppal);
  562. }
  563. UserFreePool(ppal);
  564. /*
  565. * Make this palette public.
  566. */
  567. if (hpal)
  568. GreSetPaletteOwner(hpal, OBJECT_OWNER_PUBLIC);
  569. return hpal;
  570. }
  571. /***************************************************************************\
  572. * TileWallpaper
  573. *
  574. * History:
  575. * 29-Jul-1991 MikeKe From win31
  576. \***************************************************************************/
  577. BOOL
  578. TileWallpaper(HDC hdc, LPCRECT lprc, BOOL fOffset)
  579. {
  580. int xO;
  581. int yO;
  582. int x;
  583. int y;
  584. BITMAP bm;
  585. HBITMAP hbmT = NULL;
  586. POINT ptOffset;
  587. if (fOffset) {
  588. ptOffset.x = gsrcWallpaper.x;
  589. ptOffset.y = gsrcWallpaper.y;
  590. } else {
  591. ptOffset.x = 0;
  592. ptOffset.y = 0;
  593. }
  594. /*
  595. * We need to get the dimensions of the bitmap here rather than rely on
  596. * the dimensions in srcWallpaper because this function may
  597. * be called as part of ExpandBitmap, before srcWallpaper is
  598. * set.
  599. */
  600. if (GreExtGetObjectW(ghbmWallpaper, sizeof(BITMAP), (PBITMAP)&bm)) {
  601. xO = lprc->left - (lprc->left % bm.bmWidth) + (ptOffset.x % bm.bmWidth);
  602. if (xO > lprc->left) {
  603. xO -= bm.bmWidth;
  604. }
  605. yO = lprc->top - (lprc->top % bm.bmHeight) + (ptOffset.y % bm.bmHeight);
  606. if (yO > lprc->top) {
  607. yO -= bm.bmHeight;
  608. }
  609. /*
  610. * Tile the bitmap to the surface.
  611. */
  612. if (hbmT = GreSelectBitmap(ghdcMem, ghbmWallpaper)) {
  613. for (y = yO; y < lprc->bottom; y += bm.bmHeight) {
  614. for (x = xO; x < lprc->right; x += bm.bmWidth) {
  615. GreBitBlt(hdc,
  616. x,
  617. y,
  618. bm.bmWidth,
  619. bm.bmHeight,
  620. ghdcMem,
  621. 0,
  622. 0,
  623. SRCCOPY,
  624. 0);
  625. }
  626. }
  627. GreSelectBitmap(ghdcMem, hbmT);
  628. }
  629. }
  630. return (hbmT != NULL);
  631. }
  632. /***************************************************************************\
  633. * GetWallpaperCenterRect
  634. *
  635. * Returns the rect of centered wallpaper on a particular monitor.
  636. *
  637. * History:
  638. * 26-Sep-1996 adams Created.
  639. \***************************************************************************/
  640. BOOL
  641. GetWallpaperCenterRect(LPRECT lprc, LPPOINT lppt, LPCRECT lprcMonitor)
  642. {
  643. RECT rc;
  644. if (gsrcWallpaper.x != 0 || gsrcWallpaper.y != 0) {
  645. rc.left = lprcMonitor->left + gsrcWallpaper.x;
  646. rc.top = lprcMonitor->top + gsrcWallpaper.y;
  647. } else {
  648. rc.left = (lprcMonitor->left + lprcMonitor->right - gsrcWallpaper.cx) / 2;
  649. rc.top = (lprcMonitor->top + lprcMonitor->bottom - gsrcWallpaper.cy) / 2;
  650. }
  651. rc.right = rc.left + gsrcWallpaper.cx;
  652. rc.bottom = rc.top + gsrcWallpaper.cy;
  653. lppt->x = max(0, lprcMonitor->left - rc.left);
  654. lppt->y = max(0, lprcMonitor->top - rc.top);
  655. return IntersectRect(lprc, &rc, lprcMonitor);
  656. }
  657. /***************************************************************************\
  658. * CenterOrStretchWallpaper
  659. *
  660. *
  661. * History:
  662. * 29-Jul-1991 MikeKe From win31
  663. \***************************************************************************/
  664. BOOL
  665. CenterOrStretchWallpaper(HDC hdc, LPCRECT lprcMonitor)
  666. {
  667. BOOL fStretchToEachMonitor = FALSE;
  668. RECT rc;
  669. HBITMAP hbmT;
  670. BOOL f = FALSE;
  671. HRGN hrgn;
  672. POINT pt;
  673. BITMAP bm;
  674. int oldStretchMode;
  675. /*
  676. * This used to call TileWallpaper, but this really slowed up the system
  677. * for small dimension bitmaps. We really only need to blt it once for
  678. * centered bitmaps.
  679. */
  680. if (hbmT = GreSelectBitmap(ghdcMem, ghbmWallpaper)) {
  681. if (fStretchToEachMonitor && (gwWPStyle & DTF_STRETCH)) {
  682. if (GreExtGetObjectW(ghbmWallpaper, sizeof(BITMAP), (PBITMAP)&bm)) {
  683. oldStretchMode = GreSetStretchBltMode(hdc, COLORONCOLOR);
  684. f = GreStretchBlt(hdc,
  685. lprcMonitor->left,
  686. lprcMonitor->top,
  687. lprcMonitor->right - lprcMonitor->left,
  688. lprcMonitor->bottom - lprcMonitor->top,
  689. ghdcMem,
  690. 0,
  691. 0,
  692. bm.bmWidth,
  693. bm.bmHeight,
  694. SRCCOPY,
  695. 0);
  696. GreSetStretchBltMode(hdc, oldStretchMode);
  697. }
  698. } else {
  699. if (GetWallpaperCenterRect(&rc, &pt, lprcMonitor)) {
  700. f = GreBitBlt(hdc,
  701. rc.left,
  702. rc.top,
  703. rc.right - rc.left,
  704. rc.bottom - rc.top,
  705. ghdcMem,
  706. pt.x,
  707. pt.y,
  708. SRCCOPY,
  709. 0);
  710. /*
  711. * Fill the bacground (excluding the bitmap) with the desktop
  712. * brush. Save the DC with the cliprect.
  713. */
  714. if (f && NULL != (hrgn = CreateEmptyRgn())) {
  715. if (GreGetRandomRgn(hdc, hrgn, 1) != -1) {
  716. GreExcludeClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
  717. FillRect(hdc, lprcMonitor, SYSHBR(DESKTOP));
  718. GreExtSelectClipRgn(hdc, hrgn, RGN_COPY);
  719. }
  720. GreDeleteObject(hrgn);
  721. }
  722. }
  723. }
  724. GreSelectBitmap(ghdcMem, hbmT);
  725. }
  726. /*
  727. * As a last-ditch effort, if something failed, just clear the desktop.
  728. */
  729. if (!f) {
  730. FillRect(hdc, lprcMonitor, SYSHBR(DESKTOP));
  731. }
  732. return f;
  733. }
  734. /***************************************************************************\
  735. * xxxDrawWallpaper
  736. *
  737. * Performs the drawing of the wallpaper. This can be either tiled or
  738. * centered. This routine provides the common things like palette-handling.
  739. * If the (fPaint) is false, then we only to palette realization and no
  740. * drawing.
  741. *
  742. * History:
  743. * 01-Oct-1995 ChrisWil Ported.
  744. \***************************************************************************/
  745. BOOL xxxDrawWallpaper(
  746. PWND pwnd,
  747. HDC hdc,
  748. PMONITOR pMonitorPaint,
  749. LPCRECT lprc)
  750. {
  751. BOOL f;
  752. HPALETTE hpalT;
  753. int i;
  754. CheckLock(pwnd);
  755. CheckLock(pMonitorPaint);
  756. UserAssert(ghbmWallpaper != NULL);
  757. UserAssert(lprc);
  758. /*
  759. * Select in the palette if one exists. As a wallpaper, we should only
  760. * be able to do background-realizations.
  761. */
  762. if (ghpalWallpaper && pMonitorPaint->dwMONFlags & MONF_PALETTEDISPLAY) {
  763. hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE);
  764. i = xxxRealizePalette(hdc);
  765. } else {
  766. hpalT = NULL;
  767. }
  768. if (gwWPStyle & DTF_TILE) {
  769. f = TileWallpaper(hdc, lprc, pwnd != NULL);
  770. } else {
  771. f = CenterOrStretchWallpaper(hdc, &pMonitorPaint->rcMonitor);
  772. }
  773. if (hpalT) {
  774. _SelectPalette(hdc, hpalT, FALSE);
  775. }
  776. return f;
  777. }
  778. /***************************************************************************\
  779. * xxxExpandBitmap
  780. *
  781. * Expand this bitmap to fit the screen. This is used for tiled images
  782. * only.
  783. *
  784. * History:
  785. * 29-Sep-1995 ChrisWil Ported from Chicago.
  786. \***************************************************************************/
  787. HBITMAP xxxExpandBitmap(
  788. HBITMAP hbm)
  789. {
  790. int nx;
  791. int ny;
  792. BITMAP bm;
  793. HBITMAP hbmNew;
  794. HBITMAP hbmD;
  795. LPRECT lprc;
  796. RECT rc;
  797. PMONITOR pMonitor;
  798. TL tlpMonitor;
  799. /*
  800. * Get the dimensions of the screen and bitmap we'll be dealing with.
  801. * We'll adjust the xScreen/yScreen to reflect the new surface size.
  802. * The default adjustment is to stretch the image to fit the screen.
  803. */
  804. GreExtGetObjectW(hbm, sizeof(bm), (PBITMAP)&bm);
  805. pMonitor = GetPrimaryMonitor();
  806. lprc = &pMonitor->rcMonitor;
  807. nx = (lprc->right / TILE_XMINSIZE) / bm.bmWidth;
  808. ny = (lprc->bottom / TILE_YMINSIZE) / bm.bmHeight;
  809. if (nx == 0)
  810. nx++;
  811. if (ny == 0)
  812. ny++;
  813. if ((nx + ny) <= 2)
  814. return hbm;
  815. /*
  816. * Create the surface for the new-bitmap.
  817. */
  818. rc.left = rc.top = 0;
  819. rc.right = nx * bm.bmWidth;
  820. rc.bottom = ny * bm.bmHeight;
  821. hbmD = GreSelectBitmap(ghdcMem, hbm);
  822. hbmNew = GreCreateCompatibleBitmap(ghdcMem, rc.right, rc.bottom);
  823. GreSelectBitmap(ghdcMem, hbmD);
  824. if (hbmNew == NULL)
  825. return hbm;
  826. if (hbmD = GreSelectBitmap(ghdcMem2, hbmNew)) {
  827. /*
  828. * Expand the bitmap to the new surface.
  829. */
  830. ThreadLockAlways(pMonitor, &tlpMonitor);
  831. xxxDrawWallpaper(NULL, ghdcMem2, pMonitor, &rc);
  832. ThreadUnlock(&tlpMonitor);
  833. GreSelectBitmap(ghdcMem2, hbmD);
  834. }
  835. GreDeleteObject(hbm);
  836. GreSetBitmapOwner(hbmNew, OBJECT_OWNER_PUBLIC);
  837. return hbmNew;
  838. }
  839. /***************************************************************************\
  840. * xxxLoadDesktopWallpaper
  841. *
  842. * Load the dib (section) from the client-side. We make this callback to
  843. * utilize code in USER32 for loading/creating a dib or section. Since,
  844. * the wallpaper-code can be called from any-process, we can't use DIBSECTIONS
  845. * for a wallpaper. Luckily we can use Real-DIBs for this. That way we
  846. * can extract out a palette from the bitmap. We couldn't do this if the
  847. * bitmap was created "compatible".
  848. *
  849. * History:
  850. * 29-Sep-1995 ChrisWil Created.
  851. \***************************************************************************/
  852. BOOL xxxLoadDesktopWallpaper(
  853. LPWSTR lpszFile)
  854. {
  855. UINT LR_flags;
  856. int dxDesired;
  857. int dyDesired;
  858. UNICODE_STRING strName;
  859. /*
  860. * If the bitmap is somewhat large (big bpp), then we'll deal
  861. * with it as a real-dib. We'll also do this for 8bpp since it
  862. * can utilize a palette. Chicago uses DIBSECTIONS since it can
  863. * count on the one-process handling the drawing. Since, NT can
  864. * have different processes doing the drawing, we can't use sections.
  865. */
  866. LR_flags = LR_LOADFROMFILE;
  867. if (gpDispInfo->fAnyPalette || gpsi->BitCount >= 8) {
  868. LR_flags |= LR_CREATEREALDIB;
  869. }
  870. /*
  871. * If we are going to be stretching the bitmap, go ahead and pre-stretch
  872. * the bitmap to the size of the primary monitor. This makes blitting
  873. * to the primary monitor quicker (because it doesn't have to stretch),
  874. * while other monitors will be a little slower.
  875. */
  876. if (gwWPStyle & DTF_STRETCH) {
  877. PMONITOR pMonitor = GetPrimaryMonitor();
  878. dxDesired = pMonitor->rcMonitor.right - pMonitor->rcMonitor.left;
  879. dyDesired = pMonitor->rcMonitor.bottom - pMonitor->rcMonitor.top;
  880. } else {
  881. dxDesired = dyDesired = 0;
  882. }
  883. /*
  884. * Make a callback to the client to perform the loading.
  885. * Saves us some code.
  886. */
  887. RtlInitUnicodeString(&strName, lpszFile);
  888. ghbmWallpaper = xxxClientLoadImage(
  889. &strName,
  890. 0,
  891. IMAGE_BITMAP,
  892. dxDesired,
  893. dyDesired,
  894. LR_flags,
  895. TRUE);
  896. if (ghbmWallpaper == NULL)
  897. return FALSE;
  898. /*
  899. * If it's a palette-display, then we will derive the global
  900. * wallpaper palette from the bitmap.
  901. */
  902. if (gpDispInfo->fAnyPalette) {
  903. ghpalWallpaper = CreatePaletteFromBitmap(ghbmWallpaper);
  904. }
  905. /*
  906. * Always try to convert the bitmap to a DDB. On single monitor
  907. * systems this will improve performance. On multiple-monitor
  908. * systems, GDI will refuse to create the DDB and just leave it
  909. * as a DIB at the color format of the primary monitor.
  910. */
  911. ghbmWallpaper = ConvertToDDB(gpDispInfo->hdcScreen, ghbmWallpaper, ghpalWallpaper);
  912. /*
  913. * Mark the bitmap as public, so any process can party with it.
  914. */
  915. GreSetBitmapOwner(ghbmWallpaper, OBJECT_OWNER_PUBLIC);
  916. /*
  917. * Expand bitmap if we are going to tile it. This creates a larger
  918. * bitmap that contains an even multiple of the source bitmap. This
  919. * larger bitmap can then be tiled more quickly than the smaller bitmap.
  920. */
  921. if (gwWPStyle & DTF_TILE) {
  922. ghbmWallpaper = xxxExpandBitmap(ghbmWallpaper);
  923. }
  924. return TRUE;
  925. }
  926. /***************************************************************************\
  927. * xxxSetDeskWallpaper
  928. *
  929. * Sets the desktop-wallpaper. This deletes the old handles in the process.
  930. *
  931. * History:
  932. * 29-Jul-1991 MikeKe From win31.
  933. * 01-Oct-1995 ChrisWil Rewrote for LoadImage().
  934. \***************************************************************************/
  935. BOOL xxxSetDeskWallpaper(PUNICODE_STRING pProfileUserName,
  936. LPWSTR lpszFile)
  937. {
  938. BITMAP bm;
  939. UINT WallpaperStyle2;
  940. PWND pwndShell;
  941. TL tl;
  942. PTHREADINFO ptiCurrent = PtiCurrent();
  943. PDESKTOP pdesk;
  944. BOOL fRet = FALSE;
  945. HBITMAP hbmOld;
  946. PROFINTINFO apsi[] = {
  947. {PMAP_DESKTOP, (LPWSTR)STR_TILEWALL , 0, &gwWPStyle },
  948. {PMAP_DESKTOP, (LPWSTR)STR_DTSTYLE , 0, &WallpaperStyle2 },
  949. {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINX, 0, &gsrcWallpaper.x },
  950. {PMAP_DESKTOP, (LPWSTR)STR_DTORIGINY, 0, &gsrcWallpaper.y },
  951. {0, NULL, 0, NULL }
  952. };
  953. pdesk = ptiCurrent->rpdesk;
  954. hbmOld = ghbmWallpaper;
  955. if ((lpszFile == SETWALLPAPER_METRICS) && !(gwWPStyle & DTF_STRETCH)) {
  956. gsrcWallpaper.x = 0;
  957. gsrcWallpaper.y = 0;
  958. if (ghbmWallpaper)
  959. goto CreateNewWallpaper;
  960. goto Metric_Change;
  961. }
  962. CreateNewWallpaper:
  963. /*
  964. * Delete the old wallpaper and palette if the exist.
  965. */
  966. if (ghpalWallpaper) {
  967. GreDeleteObject(ghpalWallpaper);
  968. ghpalWallpaper = NULL;
  969. }
  970. if (ghbmWallpaper) {
  971. GreDeleteObject(ghbmWallpaper);
  972. ghbmWallpaper = NULL;
  973. }
  974. /*
  975. * Kill any SPBs no matter what. This works if we're switching from/to
  976. * palettized wallpaper. Fixes a lot of problems because palette doesn't
  977. * change, shell paints funny on desktop, etc.
  978. */
  979. BEGINATOMICCHECK();
  980. FreeAllSpbs();
  981. ENDATOMICCHECK();
  982. /*
  983. * If this is a metric-change (and stretched), then we need to
  984. * reload it. However, since we are called from the winlogon process
  985. * during a desktop-switch, we would be mapped to the wrong Luid
  986. * when we attempt to grab the name from GetDeskWallpaperName. This
  987. * would use the Luid from the DEFAULT user rather than the current
  988. * logged on user. In order to avoid this, we cache the wallpaer
  989. * name so that on METRIC-CHANGES we use the current-user's wallpaper.
  990. *
  991. * NOTE: we assume that prior to any METRIC change, we have already
  992. * setup the ghbmWallpaper and lpszCached. This is usually done
  993. * either on logon or during user desktop-changes through conrol-Panel.
  994. */
  995. if (lpszFile == SETWALLPAPER_METRICS) {
  996. UserAssert(gpszWall != NULL);
  997. goto LoadWallpaper;
  998. }
  999. /*
  1000. * Free the cached handle.
  1001. */
  1002. if (gpszWall) {
  1003. UserFreePool(gpszWall);
  1004. gpszWall = NULL;
  1005. }
  1006. /*
  1007. * Load the wallpaper-name. If this returns FALSE, then
  1008. * the user specified (None). We will return true to force
  1009. * the repainting of the desktop.
  1010. */
  1011. gpszWall = GetDeskWallpaperName(pProfileUserName,lpszFile);
  1012. if (!gpszWall) {
  1013. fRet = TRUE;
  1014. goto SDW_Exit;
  1015. }
  1016. /*
  1017. * Retrieve the default settings from the registry.
  1018. *
  1019. * If tile is indicated, then normalize style to not include
  1020. * FIT/STRETCH which are center-only styles. Likewise, if
  1021. * we are centered, then normalize out the TILE bit.
  1022. */
  1023. FastGetProfileIntsW(pProfileUserName, apsi, 0);
  1024. gwWPStyle &= DTF_TILE;
  1025. if (!(gwWPStyle & DTF_TILE)) {
  1026. gwWPStyle = WallpaperStyle2 & DTF_STRETCH;
  1027. }
  1028. /*
  1029. * Load the wallpaper. This makes a callback to the client to
  1030. * perform the bitmap-creation.
  1031. */
  1032. LoadWallpaper:
  1033. if (xxxLoadDesktopWallpaper(gpszWall) == FALSE) {
  1034. gwWPStyle = 0;
  1035. goto SDW_Exit;
  1036. }
  1037. /*
  1038. * If we have a palette, then we need to do the correct realization and
  1039. * notification.
  1040. */
  1041. if (ghpalWallpaper != NULL) {
  1042. PWND pwndSend;
  1043. /*
  1044. * Get the shell window. This could be NULL on system
  1045. * initialization. We will use this to do palette realization.
  1046. */
  1047. pwndShell = _GetShellWindow(pdesk);
  1048. if (pwndShell) {
  1049. pwndSend = pwndShell;
  1050. } else {
  1051. pwndSend = (pdesk ? pdesk->pDeskInfo->spwnd : NULL);
  1052. }
  1053. /*
  1054. * Update the desktop with the new bitmap. This cleans
  1055. * out the system-palette so colors can be realized.
  1056. */
  1057. GreRealizeDefaultPalette(gpDispInfo->hdcScreen, TRUE);
  1058. /*
  1059. * Don't broadcast if system initialization is occuring. Otherwise
  1060. * this gives the shell first crack at realizing its colors
  1061. * correctly.
  1062. */
  1063. if (pwndSend) {
  1064. HWND hwnd = HW(pwndSend);
  1065. ThreadLockAlways(pwndSend, &tl);
  1066. xxxSendNotifyMessage(pwndSend, WM_PALETTECHANGED, (WPARAM)hwnd, 0);
  1067. ThreadUnlock(&tl);
  1068. }
  1069. }
  1070. Metric_Change:
  1071. if (fRet = GreExtGetObjectW(ghbmWallpaper, sizeof(bm), (PBITMAP)&bm)) {
  1072. gsrcWallpaper.cx = bm.bmWidth;
  1073. gsrcWallpaper.cy = bm.bmHeight;
  1074. }
  1075. SDW_Exit:
  1076. /*
  1077. * Notify the shell-window that the wallpaper changed. We need to refresh
  1078. * our local pwndShell here because we might have called-back above.
  1079. */
  1080. pwndShell = _GetShellWindow(pdesk);
  1081. if ((pwndShell != NULL) &&
  1082. ((hbmOld && !ghbmWallpaper) || (!hbmOld && ghbmWallpaper))) {
  1083. ThreadLockAlways(pwndShell, &tl);
  1084. xxxSendNotifyMessage(pwndShell,
  1085. WM_SHELLNOTIFY,
  1086. SHELLNOTIFY_WALLPAPERCHANGED,
  1087. (LPARAM)ghbmWallpaper);
  1088. ThreadUnlock(&tl);
  1089. }
  1090. return fRet;
  1091. }
  1092. /***************************************************************************\
  1093. * DesktopBuildPaint
  1094. *
  1095. * Draw the build information onto the desktop
  1096. *
  1097. * History:
  1098. * 2/4/99 joejo - Bug 280256
  1099. \***************************************************************************/
  1100. void DesktopBuildPaint(
  1101. HDC hdc,
  1102. PMONITOR pMonitor)
  1103. {
  1104. int imode;
  1105. COLORREF oldColor;
  1106. RECT rcText = {0,0,0,0};
  1107. RECT rcBuildInfo = {0,0,0,0};
  1108. HFONT oldFont = GreGetHFONT(hdc);
  1109. SIZE sizeText;
  1110. SIZE sizeProductName;
  1111. SIZE sizeProductBuild;
  1112. SIZE sizeSystemRoot;
  1113. BOOL fDrawSolidBackground = FALSE;
  1114. int cBorder = 5;
  1115. int cMargin = fDrawSolidBackground ? 5 : 0;
  1116. /*
  1117. * Set up DC
  1118. */
  1119. imode = GreSetBkMode(hdc, TRANSPARENT);
  1120. if (fDrawSolidBackground) {
  1121. /*
  1122. * Since we are going to draw our own background, we can always set
  1123. * the pen color to black.
  1124. */
  1125. oldColor = GreSetTextColor( hdc, RGB(0,0,0) );
  1126. } else {
  1127. /*
  1128. * Since we are not going to draw our own background, we have to work
  1129. * with whatever is already there. This is an ugly hack to try and
  1130. * cover the case where our white text won't show up on a white
  1131. * background. Of course, this doesn't catch the bitmap case. Or
  1132. * the almost white case.
  1133. */
  1134. if (GreGetBrushColor(SYSHBR(BACKGROUND)) != 0x00ffffff) {
  1135. oldColor = GreSetTextColor( hdc, RGB(255,255,255) );
  1136. } else {
  1137. oldColor = GreSetTextColor( hdc, RGB(0,0,0) );
  1138. }
  1139. }
  1140. /*
  1141. * Get the width in pixels of the longest string we are going to print out.
  1142. */
  1143. if (gpsi && gpsi->hCaptionFont) {
  1144. GreSelectFont(hdc, gpsi->hCaptionFont);
  1145. }
  1146. GreGetTextExtentW(
  1147. hdc,
  1148. wszProductName,
  1149. wcslen(wszProductName),
  1150. &sizeProductName,
  1151. GGTE_WIN3_EXTENT);
  1152. if (ghMenuFont != NULL ) {
  1153. GreSelectFont(hdc, ghMenuFont);
  1154. }
  1155. GreGetTextExtentW(
  1156. hdc,
  1157. wszProductBuild,
  1158. wcslen(wszProductBuild),
  1159. &sizeProductBuild,
  1160. GGTE_WIN3_EXTENT);
  1161. if (gDrawVersionAlways) {
  1162. GreGetTextExtentW(
  1163. hdc,
  1164. USER_SHARED_DATA->NtSystemRoot,
  1165. wcslen(USER_SHARED_DATA->NtSystemRoot),
  1166. &sizeSystemRoot,
  1167. GGTE_WIN3_EXTENT);
  1168. } else {
  1169. sizeSystemRoot.cx = 0;
  1170. sizeSystemRoot.cy = 0;
  1171. }
  1172. sizeText.cx = sizeProductName.cx >= sizeProductBuild.cx ? sizeProductName.cx : sizeProductBuild.cx;
  1173. sizeText.cy = sizeProductName.cy + sizeProductBuild.cy;
  1174. if (gDrawVersionAlways) {
  1175. sizeText.cx = (sizeText.cx >= sizeSystemRoot.cx) ? sizeText.cx : sizeSystemRoot.cx;
  1176. sizeText.cy += sizeSystemRoot.cy;
  1177. }
  1178. /*
  1179. * Calculate the position for all of the build info on the desktop.
  1180. * We will draw either 2 or 3 lines of text.
  1181. */
  1182. rcBuildInfo.left = pMonitor->rcWork.right - cBorder - cMargin - sizeText.cx - cMargin;
  1183. rcBuildInfo.top = pMonitor->rcWork.bottom - cBorder - cMargin - sizeText.cy - cMargin;
  1184. rcBuildInfo.right = pMonitor->rcWork.right - cBorder;
  1185. rcBuildInfo.bottom = pMonitor->rcWork.bottom - cBorder;
  1186. /*
  1187. * Draw the background if we want it.
  1188. *
  1189. */
  1190. if (fDrawSolidBackground) {
  1191. NtGdiRoundRect(hdc, rcBuildInfo.left, rcBuildInfo.top, rcBuildInfo.right, rcBuildInfo.bottom, 10, 10);
  1192. }
  1193. /*
  1194. * Print Windows 2000 name
  1195. */
  1196. if (gpsi && gpsi->hCaptionFont) {
  1197. GreSelectFont(hdc, gpsi->hCaptionFont);
  1198. }
  1199. rcText.left = rcBuildInfo.left + cMargin;
  1200. rcText.top = rcBuildInfo.top + cMargin;
  1201. rcText.right = rcText.left + sizeText.cx;
  1202. rcText.bottom = rcText.top + sizeProductName.cy;
  1203. GreSetTextAlign(hdc, TA_RIGHT | TA_BOTTOM);
  1204. GreExtTextOutW(
  1205. hdc,
  1206. rcText.right,
  1207. rcText.bottom,
  1208. 0,
  1209. &rcText,
  1210. wszProductName,
  1211. wcslen(wszProductName),
  1212. (LPINT)NULL
  1213. );
  1214. /*
  1215. * Print Build Number
  1216. */
  1217. if (ghMenuFont != NULL ) {
  1218. GreSelectFont(hdc, ghMenuFont);
  1219. }
  1220. rcText.top = rcText.bottom + 1;
  1221. rcText.bottom = rcText.top + sizeProductBuild.cy;
  1222. GreExtTextOutW(
  1223. hdc,
  1224. rcText.right,
  1225. rcText.bottom,
  1226. 0,
  1227. &rcText,
  1228. wszProductBuild,
  1229. wcslen(wszProductBuild),
  1230. (LPINT)NULL
  1231. );
  1232. /*
  1233. * If we are in CHK mode, draw the System Dir Path
  1234. */
  1235. if (gDrawVersionAlways) {
  1236. rcText.top = rcText.bottom + 1;
  1237. rcText.bottom = rcText.top + sizeSystemRoot.cy;
  1238. GreExtTextOutW(
  1239. hdc,
  1240. rcText.right,
  1241. rcText.bottom,
  1242. 0,
  1243. &rcText,
  1244. USER_SHARED_DATA->NtSystemRoot,
  1245. wcslen(USER_SHARED_DATA->NtSystemRoot),
  1246. (LPINT)NULL
  1247. );
  1248. }
  1249. if (oldFont) {
  1250. GreSelectFont(hdc, oldFont);
  1251. }
  1252. GreSetBkMode(hdc, imode);
  1253. GreSetTextColor(hdc, oldColor);
  1254. }
  1255. /***************************************************************************\
  1256. * xxxDesktopPaintCallback
  1257. *
  1258. * Draw the wallpaper or fill with the background brush. In debug,
  1259. * also draw the build number on the top of each monitor.
  1260. *
  1261. * History:
  1262. * 20-Sep-1996 adams Created.
  1263. \***************************************************************************/
  1264. BOOL
  1265. xxxDesktopPaintCallback(
  1266. PMONITOR pMonitor,
  1267. HDC hdc,
  1268. LPRECT lprcMonitorClip,
  1269. LPARAM dwData)
  1270. {
  1271. BOOL f;
  1272. PWND pwnd;
  1273. CheckLock(pMonitor);
  1274. pwnd = (PWND)dwData;
  1275. if (SYSMET(CLEANBOOT)) {
  1276. FillRect(hdc, lprcMonitorClip, ghbrBlack );
  1277. f = TRUE;
  1278. } else {
  1279. /*
  1280. * if this is the disconnected desktop, skip the bitmap paint
  1281. */
  1282. if (gbDesktopLocked) {
  1283. f = FALSE;
  1284. } else {
  1285. /*
  1286. * Paint the desktop with a color or the wallpaper.
  1287. */
  1288. if (ghbmWallpaper) {
  1289. f = xxxDrawWallpaper(
  1290. pwnd,
  1291. hdc,
  1292. pMonitor,
  1293. lprcMonitorClip);
  1294. } else {
  1295. FillRect(hdc, lprcMonitorClip, SYSHBR(DESKTOP));
  1296. f = TRUE;
  1297. }
  1298. }
  1299. }
  1300. if (SYSMET(CLEANBOOT)
  1301. || gDrawVersionAlways
  1302. || gdwCanPaintDesktop) {
  1303. static BOOL fInit = TRUE;
  1304. SIZE size;
  1305. int imode;
  1306. COLORREF oldColor;
  1307. HFONT oldFont = NULL;
  1308. /*
  1309. * Grab the stuff from the registry
  1310. */
  1311. if (fInit) {
  1312. if (SYSMET(CLEANBOOT)) {
  1313. ServerLoadString( hModuleWin, STR_SAFEMODE, SafeModeStr, ARRAY_SIZE(SafeModeStr) );
  1314. SafeModeStrLen = wcslen(SafeModeStr);
  1315. }
  1316. GetVersionInfo(SYSMET(CLEANBOOT) == 0);
  1317. fInit = FALSE;
  1318. }
  1319. if (SYSMET(CLEANBOOT)) {
  1320. if (gpsi != NULL && gpsi->hCaptionFont != NULL) {
  1321. oldFont = GreSelectFont(hdc, gpsi->hCaptionFont);
  1322. }
  1323. GreGetTextExtentW(hdc, wszSafeMode, wcslen(wszSafeMode), &size, GGTE_WIN3_EXTENT);
  1324. imode = GreSetBkMode(hdc, TRANSPARENT);
  1325. oldColor = GreSetTextColor( hdc, RGB(255,255,255) );
  1326. GreExtTextOutW(
  1327. hdc,
  1328. (pMonitor->rcWork.left + pMonitor->rcWork.right - size.cx) / 2,
  1329. pMonitor->rcWork.top,
  1330. 0,
  1331. (LPRECT)NULL,
  1332. wszSafeMode,
  1333. wcslen(wszSafeMode),
  1334. (LPINT)NULL
  1335. );
  1336. GreGetTextExtentW(hdc, SafeModeStr, SafeModeStrLen, &size, GGTE_WIN3_EXTENT);
  1337. GreExtTextOutW(
  1338. hdc,
  1339. pMonitor->rcWork.left,
  1340. pMonitor->rcWork.top,
  1341. 0,
  1342. (LPRECT)NULL,
  1343. SafeModeStr,
  1344. SafeModeStrLen,
  1345. (LPINT)NULL
  1346. );
  1347. GreExtTextOutW(
  1348. hdc,
  1349. pMonitor->rcWork.right - size.cx,
  1350. pMonitor->rcWork.top,
  1351. 0,
  1352. (LPRECT)NULL,
  1353. SafeModeStr,
  1354. SafeModeStrLen,
  1355. (LPINT)NULL
  1356. );
  1357. GreExtTextOutW(
  1358. hdc,
  1359. pMonitor->rcWork.right - size.cx,
  1360. pMonitor->rcWork.bottom - gpsi->tmSysFont.tmHeight,
  1361. 0,
  1362. (LPRECT)NULL,
  1363. SafeModeStr,
  1364. SafeModeStrLen,
  1365. (LPINT)NULL
  1366. );
  1367. GreExtTextOutW(
  1368. hdc,
  1369. pMonitor->rcWork.left,
  1370. pMonitor->rcWork.bottom - gpsi->tmSysFont.tmHeight,
  1371. 0,
  1372. (LPRECT)NULL,
  1373. SafeModeStr,
  1374. SafeModeStrLen,
  1375. (LPINT)NULL
  1376. );
  1377. GreSetBkMode(hdc, imode);
  1378. GreSetTextColor(hdc, oldColor);
  1379. if (oldFont) {
  1380. GreSelectFont(hdc, oldFont);
  1381. }
  1382. } else {
  1383. if (!gbRemoteSession || !gdwTSExcludeDesktopVersion) {
  1384. DesktopBuildPaint(hdc, pMonitor);
  1385. }
  1386. }
  1387. }
  1388. return f;
  1389. }
  1390. /***************************************************************************\
  1391. * xxxInvalidateDesktopOnPaletteChange
  1392. *
  1393. * Invalidates the shell window and uncovered areas of the desktop
  1394. * when the palette changes.
  1395. *
  1396. * History:
  1397. * 28-Apr-1997 adams Created.
  1398. \***************************************************************************/
  1399. VOID
  1400. xxxInvalidateDesktopOnPaletteChange(
  1401. PWND pwnd)
  1402. {
  1403. PDESKTOP pdesk;
  1404. PWND pwndShell;
  1405. TL tlpwndShell;
  1406. RECT rc;
  1407. BOOL fRedrawDesktop;
  1408. CheckLock(pwnd);
  1409. /*
  1410. * Invalidate the shell window.
  1411. */
  1412. pdesk = PtiCurrent()->rpdesk;
  1413. pwndShell = _GetShellWindow(pdesk);
  1414. if (!pwndShell) {
  1415. fRedrawDesktop = TRUE;
  1416. rc = gpsi->rcScreen;
  1417. } else {
  1418. ThreadLockAlways(pwndShell, &tlpwndShell);
  1419. xxxRedrawWindow(
  1420. pwndShell,
  1421. NULL,
  1422. NULL,
  1423. RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  1424. /*
  1425. * The shell window may not cover all of the desktop.
  1426. * Invalidate the part of the desktop wallpaper it
  1427. * doesn't sit over.
  1428. */
  1429. fRedrawDesktop = SubtractRect(&rc, &pwnd->rcWindow, &pwndShell->rcWindow);
  1430. ThreadUnlock(&tlpwndShell);
  1431. }
  1432. /*
  1433. * Invalidate the desktop window.
  1434. */
  1435. if (fRedrawDesktop) {
  1436. xxxRedrawWindow(
  1437. pwnd,
  1438. &rc,
  1439. NULL,
  1440. RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);
  1441. }
  1442. }
  1443. /***************************************************************************\
  1444. * xxxInternalPaintDesktop
  1445. *
  1446. * If fPaint is TRUE, enumerate the monitors to paint the desktop.
  1447. * Otherwise, it selects the bitmap palette into the DC to select
  1448. * its colors into the hardware palette.
  1449. *
  1450. * History:
  1451. * 29-Jul-1991 MikeKe From win31
  1452. \***************************************************************************/
  1453. BOOL xxxInternalPaintDesktop(
  1454. PWND pwnd,
  1455. HDC hdc,
  1456. BOOL fPaint)
  1457. {
  1458. BOOL fRet = FALSE;
  1459. CheckLock(pwnd);
  1460. if (fPaint) {
  1461. RECT rcOrg, rcT;
  1462. POINT pt;
  1463. /*
  1464. * For compatiblity purposes the DC origin of desktop windows
  1465. * is set to the primary monitor, i.e. (0,0). Since we may get
  1466. * either desktop or non-desktop DCs here, temporarily reset
  1467. * the hdc origin to (0,0).
  1468. */
  1469. GreGetDCOrgEx(hdc, &pt, &rcOrg);
  1470. CopyRect(&rcT, &rcOrg);
  1471. OffsetRect(&rcT, -rcT.left, -rcT.top);
  1472. GreSetDCOrg(hdc, rcT.left, rcT.top, (PRECTL)&rcT);
  1473. fRet = xxxEnumDisplayMonitors(
  1474. hdc,
  1475. NULL,
  1476. (MONITORENUMPROC) xxxDesktopPaintCallback,
  1477. (LPARAM)pwnd,
  1478. TRUE);
  1479. /*
  1480. * Reset the DC origin back.
  1481. */
  1482. GreSetDCOrg(hdc, rcOrg.left, rcOrg.top, (PRECTL)&rcOrg);
  1483. } else if (ghpalWallpaper &&
  1484. GetPrimaryMonitor()->dwMONFlags & MONF_PALETTEDISPLAY) {
  1485. /*
  1486. * Select in the palette if one exists.
  1487. */
  1488. HPALETTE hpalT;
  1489. int i;
  1490. hpalT = _SelectPalette(hdc, ghpalWallpaper, FALSE);
  1491. i = xxxRealizePalette(hdc);
  1492. _SelectPalette(hdc, hpalT, FALSE);
  1493. if (i > 0) {
  1494. xxxInvalidateDesktopOnPaletteChange(pwnd);
  1495. }
  1496. fRet = TRUE;
  1497. }
  1498. return fRet;
  1499. }