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.

5059 lines
152 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: clres.c
  3. *
  4. * Copyright (c) 1985 - 1999, Microsoft Corporation
  5. *
  6. * Resource Loading/Creation Routines
  7. *
  8. * History:
  9. * 24-Sep-1990 MikeKe From win30
  10. * 19-Sep-1995 ChrisWil Win95/NT merge.
  11. \***************************************************************************/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. /*
  15. * Constants.
  16. */
  17. #define BPP01_MAXCOLORS 2
  18. #define BPP04_MAXCOLORS 16
  19. #define BPP08_MAXCOLORS 256
  20. #define ICON_DEFAULTDEPTH 8
  21. #define ICON_MAXWIDTH 256
  22. #define ICON_MAXHEIGHT 256
  23. #define RESCLR_BLACK 0x00000000
  24. #define RESCLR_WHITE 0x00FFFFFF
  25. typedef struct {
  26. ACCEL accel;
  27. WORD padding;
  28. } RESOURCE_ACCEL, *PRESOURCE_ACCEL;
  29. /*
  30. * Bitmap resource IDs
  31. */
  32. #define BMR_ICON 1
  33. #define BMR_BITMAP 2
  34. #define BMR_CURSOR 3
  35. typedef struct _OLDCURSOR {
  36. BYTE bType;
  37. BYTE bFormat;
  38. WORD xHotSpot; // 0 for icons
  39. WORD yHotSpot; // 0 for icons
  40. WORD cx;
  41. WORD cy;
  42. WORD cxBytes;
  43. WORD wReserved2;
  44. BYTE abBitmap[1];
  45. } OLDCURSOR, *POLDCURSOR;
  46. typedef OLDCURSOR UNALIGNED *UPOLDCURSOR;
  47. /*
  48. * Local Macros.
  49. */
  50. #define GETINITDC() \
  51. (gfSystemInitialized ? NtUserGetDC(NULL) : CreateDCW(L"DISPLAY", L"", NULL, NULL))
  52. #define RELEASEINITDC(hdc) \
  53. (gfSystemInitialized ? ReleaseDC(NULL, hdc) : DeleteDC(hdc))
  54. #define ISRIFFFORMAT(p) \
  55. (((UNALIGNED RTAG *)(p))->ckID == FOURCC_RIFF)
  56. #define MR_FAILFOR40 0x01
  57. #define MR_MONOCHROME 0x02
  58. typedef struct tagMAPRES {
  59. WORD idDisp; // display driver ID
  60. WORD idUser; // USER ID
  61. BYTE bFlags; // Flags
  62. BYTE bReserved; // unused
  63. } MAPRES, *LPMAPRES, *PMAPRES;
  64. HBITMAP CopyBmp(HBITMAP hbmpOrg, int cxNew, int cyNew, UINT LR_flags);
  65. /***************************************************************************\
  66. * SplFindResource
  67. *
  68. * Check whether the hInstance passed is that of the present display driver;
  69. * if so, it will call the GetDriverResourceId() in the display to allow
  70. * it to map the given id/name to a new id/name. Then it will call
  71. * FindResource9) in KERNEL.
  72. *
  73. * 13-Nov-1995 SanfordS Added mapping for DEFAULT constants.
  74. \***************************************************************************/
  75. HANDLE SplFindResource(
  76. HINSTANCE hmod,
  77. LPCWSTR lpName,
  78. LPCWSTR lpType)
  79. {
  80. return FINDRESOURCEW(hmod, lpName, lpType);
  81. }
  82. /***************************************************************************\
  83. * SplFreeResource
  84. *
  85. * Really frees a resource that is shared (won't be touched again unless
  86. * LR_COPYFROMRESOURCE is used) or system.
  87. *
  88. * 13-Nov-1995 SanfordS Added mapping for DEFAULT constants.
  89. \***************************************************************************/
  90. VOID SplFreeResource(
  91. HANDLE hRes,
  92. HINSTANCE hmod,
  93. UINT lrFlags)
  94. {
  95. if (!FREERESOURCE(hRes, hmod) &&
  96. ((hmod == hmodUser) || (lrFlags & LR_SHARED))) {
  97. FREERESOURCE(hRes, hmod);
  98. }
  99. }
  100. /***********************************************************************\
  101. * WowGetModuleFileName
  102. *
  103. * This converts a WOW or non-WOW module handle to a string form that
  104. * can be restored even for WOW handles.
  105. *
  106. * Returns: fSuccess
  107. *
  108. * 29-Nov-1995 SanfordS Created.
  109. \***********************************************************************/
  110. BOOL WowGetModuleFileName(
  111. HMODULE hModule,
  112. LPWSTR pwsz,
  113. DWORD cchMax)
  114. {
  115. if (!GetModuleFileName(hModule, pwsz, cchMax)) {
  116. if (cchMax < 10) {
  117. RIPMSG0(RIP_WARNING, "WowGetModuleFileName: exceeded Char-Max");
  118. return FALSE;
  119. }
  120. wsprintf(pwsz, TEXT("\001%08lx"), hModule);
  121. }
  122. return TRUE;
  123. }
  124. /***********************************************************************\
  125. * WowGetModuleHandle
  126. *
  127. * This restores the string form of a module handle created by
  128. * WowGetModuleFileName to the original handle.
  129. *
  130. * Returns: fSuccess
  131. *
  132. * 29-Nov-1995 Created SanfordS
  133. \***********************************************************************/
  134. HMODULE WowGetModuleHandle(
  135. LPCWSTR pwsz)
  136. {
  137. HMODULE hMod = NULL;
  138. DWORD digit;
  139. if (pwsz[0] == TEXT('\001')) {
  140. /*
  141. * Cant seem to link to swscanf without CRT0 problems so just
  142. * do it by hand.
  143. */
  144. while (*(++pwsz)) {
  145. if (*pwsz == TEXT(' '))
  146. continue;
  147. digit = *pwsz - TEXT('0');
  148. if (digit > 9)
  149. digit += (DWORD)(TEXT('0') - TEXT('a') + 10);
  150. (ULONG_PTR)hMod <<= 4;
  151. (ULONG_PTR)hMod += digit;
  152. }
  153. } else {
  154. hMod = GetModuleHandle(pwsz);
  155. }
  156. return hMod;
  157. }
  158. /***************************************************************************\
  159. * CreateAcceleratorTableA (API)
  160. *
  161. * Creates an accel table, returns handle to accel table.
  162. *
  163. * 02-May-1991 ScottLu Created.
  164. \***************************************************************************/
  165. FUNCLOG2(LOG_GENERAL, HACCEL, WINAPI, CreateAcceleratorTableA, LPACCEL, paccel, int, cAccel)
  166. HACCEL WINAPI CreateAcceleratorTableA(
  167. LPACCEL paccel,
  168. int cAccel)
  169. {
  170. int nAccel = cAccel;
  171. LPACCEL pAccelT = paccel;
  172. /*
  173. * Convert any character keys from ANSI to Unicode.
  174. */
  175. while (nAccel--) {
  176. if ((pAccelT->fVirt & FVIRTKEY) == 0) {
  177. if (!NT_SUCCESS(RtlMultiByteToUnicodeN((LPWSTR)&(pAccelT->key),
  178. sizeof(WCHAR),
  179. NULL,
  180. (LPSTR)&(pAccelT->key),
  181. sizeof(CHAR)))) {
  182. pAccelT->key = 0xFFFF;
  183. }
  184. }
  185. pAccelT++;
  186. }
  187. return NtUserCreateAcceleratorTable(paccel, cAccel);
  188. }
  189. /***************************************************************************\
  190. * CopyAcceleratorTableA (API)
  191. *
  192. * Copies an accel table
  193. *
  194. * 02-May-1991 ScottLu Created.
  195. \***************************************************************************/
  196. FUNCLOG3(LOG_GENERAL, int, DUMMYCALLINGTYPE, CopyAcceleratorTableA, HACCEL, hacc, LPACCEL, paccel, int, length)
  197. int CopyAcceleratorTableA(
  198. HACCEL hacc,
  199. LPACCEL paccel,
  200. int length)
  201. {
  202. int retval;
  203. retval = NtUserCopyAcceleratorTable(hacc, paccel, length);
  204. /*
  205. * If we are doing a copy and we succeeded then convert the accelerator
  206. */
  207. if ((paccel != NULL) && (retval > 0)) {
  208. /*
  209. * Translate UNICODE character keys to ANSI
  210. */
  211. int nAccel = retval;
  212. LPACCEL pAccelT = paccel;
  213. while (nAccel--) {
  214. if ((pAccelT->fVirt & FVIRTKEY) == 0) {
  215. if (!NT_SUCCESS(RtlUnicodeToMultiByteN((PCHAR)&(pAccelT->key),
  216. sizeof(WCHAR),
  217. NULL,
  218. (PWSTR)&(pAccelT->key),
  219. sizeof(pAccelT->key)))) {
  220. pAccelT->key = 0;
  221. }
  222. }
  223. pAccelT++;
  224. }
  225. }
  226. return retval;
  227. }
  228. /***************************************************************************\
  229. * FindAccResource
  230. *
  231. * Resource accelerator tables are to be loaded only once to be compatible
  232. * with Win95. So we keep track of the addresses we've loaded tables from
  233. * and the corresponding handle.
  234. *
  235. * This function finds an entry in the table. It returns the address
  236. * of the pacNext pointer that contains the requested entry.
  237. *
  238. * 01/31/97 GerardoB Created.
  239. \***************************************************************************/
  240. PACCELCACHE * FindAccResource (HACCEL hAccel, PVOID pRes)
  241. {
  242. /************************************
  243. * The caller must own gcsAccelCache *
  244. *************************************/
  245. PACCELCACHE * ppacNext = &gpac;
  246. PACCELCACHE pac;
  247. /*
  248. * This is meant to search by handle or by pointer, not both
  249. * So at least one of the parameters must be NULL.
  250. */
  251. UserAssert(!(hAccel && pRes));
  252. /*
  253. * Walk the table
  254. */
  255. while (*ppacNext != NULL) {
  256. pac = *ppacNext;
  257. if ((pac->pRes == pRes) || (pac->hAccel == hAccel)) {
  258. /*
  259. * Found it. Validate this entry before returning.
  260. */
  261. UserAssert(pac->dwLockCount != 0);
  262. UserAssert(HMValidateHandleNoDesktop(pac->hAccel, TYPE_ACCELTABLE));
  263. break;
  264. }
  265. ppacNext = &(pac->pacNext);
  266. }
  267. return ppacNext;
  268. }
  269. /***************************************************************************\
  270. * AddAccResource
  271. *
  272. * This is called everytime LoadAcc loads a new table. It adds an entry
  273. * (handle and resource address) to the global list and sets the lock count
  274. * to 1.
  275. *
  276. * 01/31/97 GerardoB Created.
  277. \***************************************************************************/
  278. VOID AddAccResource(
  279. HACCEL hAccel,
  280. PVOID pRes)
  281. {
  282. PACCELCACHE pac;
  283. UserAssert(HMValidateHandleNoDesktop(hAccel, TYPE_ACCELTABLE));
  284. UserAssert(pRes != NULL);
  285. /*
  286. * Allocate and initialize a new entry.
  287. */
  288. pac = (PACCELCACHE)UserLocalAlloc(HEAP_ZERO_MEMORY, sizeof(ACCELCACHE));
  289. if (pac != NULL) {
  290. pac->dwLockCount = 1;
  291. pac->hAccel = hAccel;
  292. pac->pRes = pRes;
  293. /*
  294. * Make it the new head of the list
  295. */
  296. RtlEnterCriticalSection(&gcsAccelCache);
  297. pac->pacNext = gpac;
  298. gpac = pac;
  299. RtlLeaveCriticalSection(&gcsAccelCache);
  300. }
  301. }
  302. /***************************************************************************\
  303. * DestroyAcceleratorTable
  304. *
  305. * 01/31/97 GerardoB Created.
  306. \***************************************************************************/
  307. BOOL DestroyAcceleratorTable (HACCEL hAccel)
  308. {
  309. BOOL fUnlocked = TRUE;
  310. PACCELCACHE *ppacNext, pac;
  311. /*
  312. * If we added this table to our list, decrement the lock count
  313. */
  314. RtlEnterCriticalSection(&gcsAccelCache);
  315. ppacNext = FindAccResource(hAccel, NULL);
  316. if (*ppacNext != NULL) {
  317. pac = *ppacNext;
  318. /*
  319. * Found it. Decrement lock count.
  320. */
  321. UserAssert(pac->dwLockCount != 0);
  322. fUnlocked = (--pac->dwLockCount == 0);
  323. /*
  324. * If noboby else wants this around, unlink it and nuke it.
  325. */
  326. if (fUnlocked) {
  327. *ppacNext = pac->pacNext;
  328. UserLocalFree(pac);
  329. }
  330. }
  331. RtlLeaveCriticalSection(&gcsAccelCache);
  332. /*
  333. * If not totally deref'ed, return FALSE (win95 compat).
  334. */
  335. if (fUnlocked) {
  336. return NtUserDestroyAcceleratorTable(hAccel);
  337. } else {
  338. return FALSE;
  339. }
  340. }
  341. /***************************************************************************\
  342. * LoadAcc (Worker)
  343. *
  344. * This is the worker-routine for loading accelerator tables.
  345. *
  346. \***************************************************************************/
  347. #define FACCEL_VALID (FALT | FCONTROL | FNOINVERT | FSHIFT | FVIRTKEY | FLASTKEY)
  348. HANDLE LoadAcc(
  349. HINSTANCE hmod,
  350. HANDLE hrl)
  351. {
  352. PACCELCACHE * ppacNext;
  353. HANDLE handle = NULL;
  354. if (hrl != NULL) {
  355. if (hrl = LOADRESOURCE(hmod, hrl)) {
  356. PRESOURCE_ACCEL paccel;
  357. if ((paccel = (PRESOURCE_ACCEL)LOCKRESOURCE(hrl, hmod)) != NULL) {
  358. int nAccel = 0;
  359. int i;
  360. LPACCEL paccelT;
  361. /*
  362. * Check if we've already loaded accelerators from this
  363. * same address
  364. */
  365. RtlEnterCriticalSection(&gcsAccelCache);
  366. ppacNext = FindAccResource(NULL, paccel);
  367. if (*ppacNext != NULL) {
  368. (*ppacNext)->dwLockCount++;
  369. handle = (*ppacNext)->hAccel;
  370. }
  371. RtlLeaveCriticalSection(&gcsAccelCache);
  372. /*
  373. * If we found this table on the global list,
  374. * return the same handle (Win95 compat)
  375. */
  376. if (handle != NULL) {
  377. goto UnlockAndFree;
  378. }
  379. while (!((paccel[nAccel].accel.fVirt) & FLASTKEY)) {
  380. if (paccel[nAccel].accel.fVirt & ~FACCEL_VALID) {
  381. RIPMSG0(RIP_WARNING, "LoadAcc: Invalid Parameter");
  382. goto UnlockAndFree;
  383. }
  384. nAccel++;
  385. }
  386. if (paccel[nAccel].accel.fVirt & ~FACCEL_VALID) {
  387. RIPMSG0(RIP_WARNING, "LoadAcc: Invalid Parameter");
  388. goto UnlockAndFree;
  389. }
  390. /*
  391. * Since the accelerator table is coming from a resource, each
  392. * element has an extra WORD of padding which we strip here
  393. * to conform with the public (and internal) ACCEL structure.
  394. */
  395. paccelT = UserLocalAlloc(0, sizeof(ACCEL) * (nAccel + 1));
  396. if (paccelT == NULL) {
  397. goto UnlockAndFree;
  398. }
  399. for (i = 0; i < nAccel + 1; i++) {
  400. paccelT[i] = paccel[i].accel;
  401. }
  402. handle = NtUserCreateAcceleratorTable(paccelT,
  403. nAccel + 1);
  404. UserLocalFree(paccelT);
  405. /*
  406. * Add this handle/address to the global table so
  407. * we won't load it twice.
  408. */
  409. if (handle != NULL) {
  410. AddAccResource(handle, paccel);
  411. }
  412. UnlockAndFree:
  413. UNLOCKRESOURCE(hrl, hmod);
  414. }
  415. FREERESOURCE(hrl, hmod);
  416. }
  417. }
  418. return handle;
  419. }
  420. /***************************************************************************\
  421. * LoadAcceleratorsA (API)
  422. * LoadAcceleratorsW (API)
  423. *
  424. *
  425. * 24-Sep-1990 MikeKe From Win30
  426. \***************************************************************************/
  427. FUNCLOG2(LOG_GENERAL, HACCEL, WINAPI, LoadAcceleratorsA, HINSTANCE, hmod, LPCSTR, lpAccName)
  428. HACCEL WINAPI LoadAcceleratorsA(
  429. HINSTANCE hmod,
  430. LPCSTR lpAccName)
  431. {
  432. HANDLE hRes;
  433. hRes = FINDRESOURCEA((HANDLE)hmod, lpAccName, (LPSTR)RT_ACCELERATOR);
  434. return (HACCEL)LoadAcc(hmod, hRes);
  435. }
  436. FUNCLOG2(LOG_GENERAL, HACCEL, WINAPI, LoadAcceleratorsW, HINSTANCE, hmod, LPCWSTR, lpAccName)
  437. HACCEL WINAPI LoadAcceleratorsW(
  438. HINSTANCE hmod,
  439. LPCWSTR lpAccName)
  440. {
  441. HANDLE hRes;
  442. hRes = FINDRESOURCEW((HANDLE)hmod, lpAccName, RT_ACCELERATOR);
  443. return (HACCEL)LoadAcc(hmod, hRes);
  444. }
  445. /***************************************************************************\
  446. * LoadStringA (API)
  447. * LoadStringW (API)
  448. *
  449. *
  450. * 05-Apr-1991 ScottLu Fixed to work with client/server.
  451. \***************************************************************************/
  452. FUNCLOG4(LOG_GENERAL, int, WINAPI, LoadStringA, HINSTANCE, hmod, UINT, wID, LPSTR, lpAnsiBuffer, int, cchBufferMax)
  453. int WINAPI LoadStringA(
  454. HINSTANCE hmod,
  455. UINT wID,
  456. LPSTR lpAnsiBuffer,
  457. int cchBufferMax)
  458. {
  459. LPWSTR lpUniBuffer;
  460. INT cchUnicode;
  461. INT cbAnsi = 0;
  462. /*
  463. * LoadStringOrError appends a NULL but does not include it in the
  464. * return count-of-bytes
  465. */
  466. cchUnicode = LoadStringOrError((HANDLE)hmod,
  467. wID,
  468. (LPWSTR)&lpUniBuffer,
  469. 0,
  470. 0);
  471. if (cchUnicode) {
  472. cbAnsi = WCSToMB(lpUniBuffer,
  473. cchUnicode,
  474. &lpAnsiBuffer,
  475. cchBufferMax - 1,
  476. FALSE);
  477. cbAnsi = min(cbAnsi, cchBufferMax - 1);
  478. }
  479. /*
  480. * Append a NULL but do not include it in the count returned
  481. */
  482. lpAnsiBuffer[cbAnsi] = 0;
  483. return cbAnsi;
  484. }
  485. FUNCLOG4(LOG_GENERAL, int, WINAPI, LoadStringW, HINSTANCE, hmod, UINT, wID, LPWSTR, lpBuffer, int, cchBufferMax)
  486. int WINAPI LoadStringW(
  487. HINSTANCE hmod,
  488. UINT wID,
  489. LPWSTR lpBuffer,
  490. int cchBufferMax)
  491. {
  492. return LoadStringOrError((HANDLE)hmod,
  493. wID,
  494. lpBuffer,
  495. cchBufferMax,
  496. 0);
  497. }
  498. /***************************************************************************\
  499. * SkipIDorString
  500. *
  501. * Skips string (or ID) and returns the next aligned WORD.
  502. *
  503. \***************************************************************************/
  504. PBYTE SkipIDorString(
  505. LPBYTE pb)
  506. {
  507. if (*((LPWORD)pb) == 0xFFFF)
  508. return (pb + 4);
  509. while (*((PWCHAR)pb)++ != 0);
  510. return pb;
  511. }
  512. /***************************************************************************\
  513. * GetSizeDialogTemplate
  514. *
  515. * This gets called by thank produced stubs. It returns the size of a
  516. * dialog template.
  517. *
  518. * 07-Apr-1991 ScottLu Created.
  519. \***************************************************************************/
  520. DWORD GetSizeDialogTemplate(
  521. HINSTANCE hmod,
  522. LPCDLGTEMPLATE pdt)
  523. {
  524. UINT cdit;
  525. LPBYTE pb;
  526. BOOL fChicago;
  527. LPDLGTEMPLATE2 pdt2;
  528. if (HIWORD(pdt->style) == 0xFFFF) {
  529. pdt2 = (LPDLGTEMPLATE2)pdt;
  530. fChicago = TRUE;
  531. /*
  532. * Fail if the app is passing invalid style bits.
  533. */
  534. if (pdt2->style & ~(DS_VALID40 | 0xffff0000)) {
  535. RIPMSG0(RIP_WARNING, "Bad dialog style bits - please remove");
  536. return 0;
  537. }
  538. pb = (LPBYTE)(((LPDLGTEMPLATE2)pdt) + 1);
  539. } else {
  540. fChicago = FALSE;
  541. /*
  542. * Check if invalid style bits are being passed. Fail if the app
  543. * is a new app ( >= VER40).
  544. * This is to ensure that we are compatible with Chicago.
  545. */
  546. if ((pdt->style & ~(DS_VALID40 | 0xffff0000)) &&
  547. (GETEXPWINVER(hmod) >= VER40)) {
  548. /*
  549. * It's a new app with invalid style bits - fail.
  550. */
  551. RIPMSG0(RIP_WARNING, "Bad dialog style bits - please remove");
  552. return 0;
  553. }
  554. pb = (LPBYTE)(pdt + 1);
  555. }
  556. /*
  557. * If there is a menu ordinal, add 4 bytes skip it. Otherwise it is a
  558. * string or just a 0.
  559. */
  560. pb = SkipIDorString(pb);
  561. /*
  562. * Skip window class and window text, adjust to next word boundary.
  563. */
  564. pb = SkipIDorString(pb);
  565. pb = SkipIDorString(pb);
  566. /*
  567. * Skip font type, size and name, adjust to next dword boundary.
  568. */
  569. if ((fChicago ? pdt2->style : pdt->style) & DS_SETFONT) {
  570. pb += fChicago ? sizeof(DWORD) + sizeof(WORD): sizeof(WORD);
  571. pb = SkipIDorString(pb);
  572. }
  573. pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3);
  574. /*
  575. * Loop through dialog items now...
  576. */
  577. cdit = fChicago ? pdt2->cDlgItems : pdt->cdit;
  578. while (cdit-- != 0) {
  579. UINT cbCreateParams;
  580. pb += fChicago ? sizeof(DLGITEMTEMPLATE2) : sizeof(DLGITEMTEMPLATE);
  581. /*
  582. * Skip the dialog control class name.
  583. */
  584. pb = SkipIDorString(pb);
  585. /*
  586. * Look at window text now.
  587. */
  588. pb = SkipIDorString(pb);
  589. cbCreateParams = *((LPWORD)pb);
  590. /*
  591. * skip any CreateParams which include the generated size WORD.
  592. */
  593. if (cbCreateParams)
  594. pb += cbCreateParams;
  595. pb += sizeof(WORD);
  596. /*
  597. * Point at the next dialog item. (DWORD aligned)
  598. */
  599. pb = (LPBYTE)(((ULONG_PTR)pb + 3) & ~3);
  600. }
  601. /*
  602. * Return template size.
  603. */
  604. return (DWORD)(pb - (LPBYTE)pdt);
  605. }
  606. /***************************************************************************\
  607. * DialogBoxIndirectParamA (API)
  608. * DialogBoxIndirectParamW (API)
  609. *
  610. * Creates the dialog and goes into a modal loop processing input for it.
  611. *
  612. * 05-Apr-1991 ScottLu Created.
  613. \***************************************************************************/
  614. FUNCLOG5(LOG_GENERAL, INT_PTR, WINAPI, DialogBoxIndirectParamA, HINSTANCE, hmod, LPCDLGTEMPLATEA, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  615. INT_PTR WINAPI DialogBoxIndirectParamA(
  616. HINSTANCE hmod,
  617. LPCDLGTEMPLATEA lpDlgTemplate,
  618. HWND hwndOwner,
  619. DLGPROC lpDialogFunc,
  620. LPARAM dwInitParam)
  621. {
  622. return DialogBoxIndirectParamAorW(hmod,
  623. (LPCDLGTEMPLATEW)lpDlgTemplate,
  624. hwndOwner,
  625. lpDialogFunc,
  626. dwInitParam,
  627. SCDLG_ANSI);
  628. }
  629. FUNCLOG5(LOG_GENERAL, INT_PTR, WINAPI, DialogBoxIndirectParamW, HINSTANCE, hmod, LPCDLGTEMPLATEW, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  630. INT_PTR WINAPI DialogBoxIndirectParamW(
  631. HINSTANCE hmod,
  632. LPCDLGTEMPLATEW lpDlgTemplate,
  633. HWND hwndOwner,
  634. DLGPROC lpDialogFunc,
  635. LPARAM dwInitParam)
  636. {
  637. return DialogBoxIndirectParamAorW(hmod,
  638. lpDlgTemplate,
  639. hwndOwner,
  640. lpDialogFunc,
  641. dwInitParam,
  642. 0);
  643. }
  644. FUNCLOG6(LOG_GENERAL, INT_PTR, WINAPI, DialogBoxIndirectParamAorW, HINSTANCE, hmod, LPCDLGTEMPLATEW, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam, UINT, fAnsiFlags)
  645. INT_PTR WINAPI DialogBoxIndirectParamAorW(
  646. HINSTANCE hmod,
  647. LPCDLGTEMPLATEW lpDlgTemplate,
  648. HWND hwndOwner,
  649. DLGPROC lpDialogFunc,
  650. LPARAM dwInitParam,
  651. UINT fAnsiFlags)
  652. {
  653. DWORD cb;
  654. /*
  655. * The server routine destroys the menu if it fails.
  656. */
  657. cb = GetSizeDialogTemplate(hmod, lpDlgTemplate);
  658. if (!cb) {
  659. RIPMSG0(RIP_WARNING, "DialogBoxIndirectParam: Invalid Paramter");
  660. return -1;
  661. }
  662. return InternalDialogBox(hmod,
  663. (LPDLGTEMPLATE)lpDlgTemplate,
  664. hwndOwner,
  665. lpDialogFunc,
  666. dwInitParam,
  667. SCDLG_CLIENT | (fAnsiFlags & (SCDLG_ANSI | SCDLG_16BIT)));
  668. }
  669. /***************************************************************************\
  670. * CreateDialogIndirectParamA (API)
  671. * CreateDialogIndirectParamW (API)
  672. *
  673. * Creates a dialog given a template and return s the window handle.
  674. * fAnsi determines if the dialog has an ANSI or UNICODE lpDialogFunc
  675. *
  676. * 05-Apr-1991 ScottLu Created.
  677. \***************************************************************************/
  678. FUNCLOG5(LOG_GENERAL, HWND, WINAPI, CreateDialogIndirectParamA, HINSTANCE, hmod, LPCDLGTEMPLATEA, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  679. HWND WINAPI CreateDialogIndirectParamA(
  680. HINSTANCE hmod,
  681. LPCDLGTEMPLATEA lpDlgTemplate,
  682. HWND hwndOwner,
  683. DLGPROC lpDialogFunc,
  684. LPARAM dwInitParam)
  685. {
  686. return CreateDialogIndirectParamAorW(hmod,
  687. (LPCDLGTEMPLATE)lpDlgTemplate,
  688. hwndOwner,
  689. lpDialogFunc,
  690. dwInitParam,
  691. SCDLG_ANSI);
  692. }
  693. FUNCLOG5(LOG_GENERAL, HWND, WINAPI, CreateDialogIndirectParamW, HINSTANCE, hmod, LPCDLGTEMPLATEW, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  694. HWND WINAPI CreateDialogIndirectParamW(
  695. HINSTANCE hmod,
  696. LPCDLGTEMPLATEW lpDlgTemplate,
  697. HWND hwndOwner,
  698. DLGPROC lpDialogFunc,
  699. LPARAM dwInitParam)
  700. {
  701. return CreateDialogIndirectParamAorW(hmod,
  702. (LPCDLGTEMPLATE)lpDlgTemplate,
  703. hwndOwner,
  704. lpDialogFunc,
  705. dwInitParam,
  706. 0);
  707. }
  708. FUNCLOG6(LOG_GENERAL, HWND, WINAPI, CreateDialogIndirectParamAorW, HANDLE, hmod, LPCDLGTEMPLATE, lpDlgTemplate, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam, UINT, fAnsi)
  709. HWND WINAPI CreateDialogIndirectParamAorW(
  710. HANDLE hmod,
  711. LPCDLGTEMPLATE lpDlgTemplate,
  712. HWND hwndOwner,
  713. DLGPROC lpDialogFunc,
  714. LPARAM dwInitParam,
  715. UINT fAnsi)
  716. {
  717. DWORD cb;
  718. HWND hwndRet;
  719. /*
  720. * The server routine destroys the menu if it fails.
  721. */
  722. cb = GetSizeDialogTemplate(hmod, lpDlgTemplate);
  723. if (!cb) {
  724. RIPMSG0(RIP_WARNING, "CreateDialogIndirect: Invalid Parameter");
  725. return NULL;
  726. }
  727. hwndRet = InternalCreateDialog(hmod,
  728. (LPDLGTEMPLATE)lpDlgTemplate,
  729. cb,
  730. hwndOwner,
  731. lpDialogFunc,
  732. dwInitParam,
  733. SCDLG_CLIENT | (fAnsi & (SCDLG_ANSI|SCDLG_16BIT)));
  734. return hwndRet;
  735. }
  736. /***************************************************************************\
  737. * DialogBoxParamA (API)
  738. * DialogBoxParamW (API)
  739. *
  740. * Loads the resource, creates the dialog and goes into a modal loop processing
  741. * input for it.
  742. *
  743. * 05-Apr-1991 ScottLu Created.
  744. \***************************************************************************/
  745. FUNCLOG5(LOG_GENERAL, INT_PTR, WINAPI, DialogBoxParamA, HINSTANCE, hmod, LPCSTR, lpName, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  746. INT_PTR WINAPI DialogBoxParamA(
  747. HINSTANCE hmod,
  748. LPCSTR lpName,
  749. HWND hwndOwner,
  750. DLGPROC lpDialogFunc,
  751. LPARAM dwInitParam)
  752. {
  753. HANDLE h;
  754. PVOID p;
  755. INT_PTR i = -1;
  756. if (h = FINDRESOURCEA(hmod, (LPSTR)lpName, (LPSTR)RT_DIALOG)) {
  757. if (h = LOADRESOURCE(hmod, h)) {
  758. if (p = LOCKRESOURCE(h, hmod)) {
  759. i = DialogBoxIndirectParamAorW(hmod,
  760. p,
  761. hwndOwner,
  762. lpDialogFunc,
  763. dwInitParam,
  764. SCDLG_ANSI);
  765. UNLOCKRESOURCE(h, hmod);
  766. }
  767. FREERESOURCE(h, hmod);
  768. }
  769. }
  770. return i;
  771. }
  772. FUNCLOG5(LOG_GENERAL, INT_PTR, WINAPI, DialogBoxParamW, HINSTANCE, hmod, LPCWSTR, lpName, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  773. INT_PTR WINAPI DialogBoxParamW(
  774. HINSTANCE hmod,
  775. LPCWSTR lpName,
  776. HWND hwndOwner,
  777. DLGPROC lpDialogFunc,
  778. LPARAM dwInitParam)
  779. {
  780. HANDLE h;
  781. PVOID p;
  782. INT_PTR i = -1;
  783. if (h = FINDRESOURCEW(hmod, lpName, RT_DIALOG)) {
  784. if (p = LoadResource(hmod, h)) {
  785. i = DialogBoxIndirectParamAorW(hmod,
  786. p,
  787. hwndOwner,
  788. lpDialogFunc,
  789. dwInitParam,
  790. 0);
  791. }
  792. }
  793. return i;
  794. }
  795. /***************************************************************************\
  796. * CreateDialogParamA (API)
  797. * CreateDialogParamW (API)
  798. *
  799. * Loads the resource, creates a dialog from that template, return s the
  800. * window handle.
  801. *
  802. * 05-Apr-1991 ScottLu Created.
  803. \***************************************************************************/
  804. FUNCLOG5(LOG_GENERAL, HWND, WINAPI, CreateDialogParamA, HINSTANCE, hmod, LPCSTR, lpName, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  805. HWND WINAPI CreateDialogParamA(
  806. HINSTANCE hmod,
  807. LPCSTR lpName,
  808. HWND hwndOwner,
  809. DLGPROC lpDialogFunc,
  810. LPARAM dwInitParam)
  811. {
  812. HANDLE h;
  813. LPDLGTEMPLATEA p;
  814. HWND hwnd = NULL;
  815. if (h = FINDRESOURCEA(hmod, lpName, (LPSTR)RT_DIALOG)) {
  816. if (h = LOADRESOURCE(hmod, h)) {
  817. if (p = (LPDLGTEMPLATEA)LOCKRESOURCE(h, hmod)) {
  818. hwnd = CreateDialogIndirectParamAorW(hmod,
  819. (LPCDLGTEMPLATE)p,
  820. hwndOwner,
  821. lpDialogFunc,
  822. dwInitParam,
  823. SCDLG_ANSI);
  824. UNLOCKRESOURCE(h, hmod);
  825. }
  826. FREERESOURCE(h, hmod);
  827. }
  828. }
  829. return hwnd;
  830. }
  831. FUNCLOG5(LOG_GENERAL, HWND, WINAPI, CreateDialogParamW, HINSTANCE, hmod, LPCWSTR, lpName, HWND, hwndOwner, DLGPROC, lpDialogFunc, LPARAM, dwInitParam)
  832. HWND WINAPI CreateDialogParamW(
  833. HINSTANCE hmod,
  834. LPCWSTR lpName,
  835. HWND hwndOwner,
  836. DLGPROC lpDialogFunc,
  837. LPARAM dwInitParam)
  838. {
  839. HANDLE h;
  840. PVOID p;
  841. HWND hwnd = NULL;
  842. if (h = FINDRESOURCEW(hmod, lpName, RT_DIALOG)) {
  843. if (h = LOADRESOURCE(hmod, h)) {
  844. if (p = LOCKRESOURCE(h, hmod)) {
  845. hwnd = CreateDialogIndirectParamAorW(hmod,
  846. p,
  847. hwndOwner,
  848. lpDialogFunc,
  849. dwInitParam,
  850. 0);
  851. UNLOCKRESOURCE(h, hmod);
  852. }
  853. FREERESOURCE(h, hmod);
  854. }
  855. }
  856. return hwnd;
  857. }
  858. /***************************************************************************\
  859. * DestroyCursor (API)
  860. *
  861. * Client wrapper for NtUserDestroyCursor.
  862. *
  863. * 28-Nov-1994 JimA Created.
  864. \***************************************************************************/
  865. FUNCLOG1(LOG_GENERAL, BOOL, WINAPI, DestroyCursor, HCURSOR, hcur)
  866. BOOL WINAPI DestroyCursor(
  867. HCURSOR hcur)
  868. {
  869. return NtUserDestroyCursor(hcur, CURSOR_CALLFROMCLIENT);
  870. }
  871. /***************************************************************************\
  872. * CreateIcoCur
  873. *
  874. *
  875. \***************************************************************************/
  876. HICON CreateIcoCur(
  877. PCURSORDATA lpi)
  878. {
  879. HCURSOR hcur;
  880. UserAssert(lpi->hbmColor || lpi->hbmMask);
  881. hcur = (HCURSOR)NtUserCallOneParam((lpi->CURSORF_flags & CURSORF_GLOBAL),
  882. SFI__CREATEEMPTYCURSOROBJECT);
  883. if (hcur == NULL)
  884. return NULL;
  885. #if DBG
  886. {
  887. BITMAP bmMask;
  888. BITMAP bmColor;
  889. UserAssert(GetObject(KHBITMAP_TO_HBITMAP(lpi->hbmMask), sizeof(BITMAP), &bmMask));
  890. /* Bug 252902 - joejo
  891. * Since the width and height of the mask bitmap is set below
  892. * we really don't need to assert on the width/height check. Throwing
  893. * a warning should be good enough.
  894. */
  895. if (bmMask.bmWidth != (LONG)lpi->cx) {
  896. RIPMSG1(RIP_WARNING, "Mask width not equal to requested width: lpi %#p", lpi);
  897. }
  898. if (bmMask.bmHeight != (LONG)lpi->cy) {
  899. RIPMSG1(RIP_WARNING, "Mask height not equal to requested height: lpi %#p", lpi);
  900. }
  901. if (lpi->hbmColor) {
  902. UserAssert(GetObject(KHBITMAP_TO_HBITMAP(lpi->hbmColor), sizeof(BITMAP), &bmColor));
  903. UserAssert(bmMask.bmHeight == bmColor.bmHeight * 2);
  904. UserAssert(bmMask.bmWidth == bmColor.bmWidth);
  905. }
  906. }
  907. #endif
  908. if (_SetCursorIconData(hcur, lpi))
  909. return hcur;
  910. NtUserDestroyCursor(hcur, CURSOR_ALWAYSDESTROY);
  911. return NULL;
  912. }
  913. /***************************************************************************\
  914. * CreateIcoCurIndirect
  915. *
  916. *
  917. \***************************************************************************/
  918. HCURSOR CreateIcoCurIndirect(
  919. PCURSORDATA pcurCreate,
  920. UINT cPlanes,
  921. UINT cBitsPixel,
  922. CONST BYTE *lpANDbits,
  923. CONST BYTE *lpXORbits)
  924. {
  925. int cbBits;
  926. HCURSOR hcurNew;
  927. BOOL bColor;
  928. UINT cx;
  929. UINT cy;
  930. LPBYTE pBits = NULL;
  931. /*
  932. * Allocate CURSOR structure.
  933. */
  934. hcurNew = (HCURSOR)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT);
  935. if (hcurNew == NULL) {
  936. return NULL;
  937. }
  938. /*
  939. * If there is no Color bitmap, create a single buffer that contains both
  940. * the AND and XOR bits. The AND bitmap is always MonoChrome
  941. */
  942. bColor = (cPlanes | cBitsPixel) > 1;
  943. if (!bColor) {
  944. cbBits = (((pcurCreate->cx + 0x0F) & ~0x0F) >> 3) * pcurCreate->cy;
  945. pBits = (LPBYTE)UserLocalAlloc(HEAP_ZERO_MEMORY, cbBits * 2);
  946. if (pBits == NULL) {
  947. NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY);
  948. return NULL;
  949. }
  950. RtlCopyMemory(pBits, lpANDbits, cbBits);
  951. RtlCopyMemory(pBits + cbBits, lpXORbits, cbBits);
  952. lpANDbits = pBits;
  953. }
  954. /*
  955. * Create hbmMask (it's always MonoChrome).
  956. */
  957. cx = pcurCreate->cx;
  958. cy = pcurCreate->cy * 2;
  959. pcurCreate->hbmMask = CreateBitmap(cx, cy, 1, 1, lpANDbits);
  960. if (pcurCreate->hbmMask == NULL) {
  961. /*
  962. * If this is a COLOR icon/cursor, lpANDBits doesn't need to be
  963. * pcurCreate->cy * 2; indeed, we don't use this double height at all.
  964. * This is a bug that will be fixed post 4.0.
  965. * For now, let's try to handle the case where the CreateBitmap call
  966. * failed because the caller didn't pass in a double height AND mask
  967. * (Win95 doesn't have this bug)
  968. */
  969. if (bColor) {
  970. RIPMSG0(RIP_WARNING,
  971. "CreateIcoCurIndirect: Retrying hbmMask creation.");
  972. cbBits = (((pcurCreate->cx + 0x0F) & ~0x0F) >> 3) * pcurCreate->cy;
  973. pBits = (LPBYTE)UserLocalAlloc(HEAP_ZERO_MEMORY, cbBits*2);
  974. if (pBits == NULL) {
  975. NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY);
  976. return NULL;
  977. }
  978. RtlCopyMemory(pBits, lpANDbits, cbBits);
  979. pcurCreate->hbmMask = CreateBitmap(cx, cy, 1, 1, pBits);
  980. UserLocalFree(pBits);
  981. pBits = NULL;
  982. }
  983. if (pcurCreate->hbmMask == NULL) {
  984. /*
  985. * CreateBitmap() failed. Clean-up and get out of here.
  986. */
  987. NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY);
  988. if (pBits != NULL) {
  989. UserLocalFree(pBits);
  990. }
  991. return NULL;
  992. }
  993. }
  994. /*
  995. * Create hbmColor or NULL it so that CallOEMCursor doesn't think we are
  996. * color.
  997. */
  998. if (bColor) {
  999. pcurCreate->hbmColor = CreateBitmap(cx,
  1000. cy / 2,
  1001. cPlanes,
  1002. cBitsPixel,
  1003. lpXORbits);
  1004. if (pcurCreate->hbmColor == NULL) {
  1005. /*
  1006. * CreateBitmap() failed. Clean-up and get out of here.
  1007. */
  1008. DeleteObject(KHBITMAP_TO_HBITMAP(pcurCreate->hbmMask));
  1009. NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY);
  1010. return NULL;
  1011. }
  1012. pcurCreate->bpp = (cPlanes * cBitsPixel);
  1013. } else {
  1014. pcurCreate->hbmColor = NULL;
  1015. pcurCreate->bpp = 1;
  1016. }
  1017. /*
  1018. * Load contents into the cursor/icon object
  1019. */
  1020. pcurCreate->cy = cy;
  1021. pcurCreate->lpModName = NULL;
  1022. pcurCreate->lpName = NULL;
  1023. pcurCreate->rt = 0;
  1024. pcurCreate->CURSORF_flags = 0;
  1025. if (_SetCursorIconData(hcurNew, pcurCreate)) {
  1026. if (pBits != NULL) {
  1027. UserLocalFree(pBits);
  1028. }
  1029. return hcurNew;
  1030. }
  1031. /*
  1032. * Could not set up cursor/icon, so free resources.
  1033. */
  1034. NtUserDestroyCursor(hcurNew, CURSOR_ALWAYSDESTROY);
  1035. DeleteObject(KHBITMAP_TO_HBITMAP(pcurCreate->hbmMask));
  1036. if (pcurCreate->hbmColor) {
  1037. DeleteObject(KHBITMAP_TO_HBITMAP(pcurCreate->hbmColor));
  1038. }
  1039. if (pBits != NULL) {
  1040. UserLocalFree(pBits);
  1041. }
  1042. return NULL;
  1043. }
  1044. /***************************************************************************\
  1045. * CreateCursor (API)
  1046. *
  1047. * History:
  1048. * 26-Feb-1991 MikeKe Created.
  1049. * 01-Aug-1991 IanJa Init cur.pszModname or DestroyCursor will work
  1050. \***************************************************************************/
  1051. HCURSOR WINAPI CreateCursor(
  1052. HINSTANCE hModule,
  1053. int iXhotspot,
  1054. int iYhotspot,
  1055. int iWidth,
  1056. int iHeight,
  1057. LPBYTE lpANDplane,
  1058. LPBYTE lpXORplane)
  1059. {
  1060. CURSORDATA cur;
  1061. UNREFERENCED_PARAMETER(hModule);
  1062. if ((iXhotspot < 0) || (iXhotspot > iWidth) ||
  1063. (iYhotspot < 0) || (iYhotspot > iHeight)) {
  1064. return 0;
  1065. }
  1066. RtlZeroMemory(&cur, sizeof(cur));
  1067. cur.xHotspot = (SHORT)iXhotspot;
  1068. cur.yHotspot = (SHORT)iYhotspot;
  1069. cur.cx = (DWORD)iWidth;
  1070. cur.cy = (DWORD)iHeight;
  1071. return CreateIcoCurIndirect(&cur, 1, 1, lpANDplane, lpXORplane);
  1072. }
  1073. /***************************************************************************\
  1074. * CreateIcon (API)
  1075. *
  1076. * History:
  1077. * 26-Feb-1991 MikeKe Created.
  1078. * 01-Aug-1991 IanJa Init cur.pszModname so DestroyIcon will work
  1079. \***************************************************************************/
  1080. HICON WINAPI CreateIcon(
  1081. HINSTANCE hModule,
  1082. int iWidth,
  1083. int iHeight,
  1084. BYTE planes,
  1085. BYTE bpp,
  1086. CONST BYTE *lpANDplane,
  1087. CONST BYTE *lpXORplane)
  1088. {
  1089. CURSORDATA cur;
  1090. UNREFERENCED_PARAMETER(hModule);
  1091. RtlZeroMemory(&cur, sizeof(cur));
  1092. cur.xHotspot = (SHORT)(iWidth / 2);
  1093. cur.yHotspot = (SHORT)(iHeight / 2);
  1094. cur.cx = (DWORD)iWidth;
  1095. cur.cy = (DWORD)iHeight;
  1096. return CreateIcoCurIndirect(&cur, planes, bpp, lpANDplane, lpXORplane);
  1097. }
  1098. /***************************************************************************\
  1099. * CreateIconIndirect (API)
  1100. *
  1101. * Creates an icon or cursor from an ICONINFO structure. Does not destroy
  1102. * cursor/icon bitmaps.
  1103. *
  1104. * 24-Jul-1991 ScottLu Created.
  1105. \***************************************************************************/
  1106. FUNCLOG1(LOG_GENERAL, HICON, WINAPI, CreateIconIndirect, PICONINFO, piconinfo)
  1107. HICON WINAPI CreateIconIndirect(
  1108. PICONINFO piconinfo)
  1109. {
  1110. HCURSOR hcur;
  1111. CURSORDATA cur;
  1112. BITMAP bmMask;
  1113. BITMAP bmColor;
  1114. HBITMAP hbmpBits2, hbmpMem;
  1115. HDC hdcMem;
  1116. UINT LR_flags = LR_DEFAULTCOLOR;
  1117. /*
  1118. * Make sure the bitmaps are real, and get their dimensions.
  1119. */
  1120. if (!GetObjectW(piconinfo->hbmMask, sizeof(BITMAP), &bmMask))
  1121. return NULL;
  1122. if (piconinfo->hbmColor != NULL) {
  1123. if (GetObjectW(piconinfo->hbmColor, sizeof(BITMAP), &bmColor)) {
  1124. if (bmColor.bmPlanes == 1 && bmColor.bmBitsPixel == 32) {
  1125. /*
  1126. * The color bitmap is a single plane, 32bpp image. As such,
  1127. * it might contain an alpha channel, so we have to preserve
  1128. * it as a DIB.
  1129. */
  1130. LR_flags |= LR_CREATEREALDIB;
  1131. }
  1132. } else {
  1133. return NULL;
  1134. }
  1135. }
  1136. /*
  1137. * Allocate CURSOR structure.
  1138. */
  1139. hcur = (HCURSOR)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT);
  1140. if (hcur == NULL)
  1141. return NULL;
  1142. /*
  1143. * Internally, USER stores the height as 2 icons high - because when
  1144. * loading bits from a resource, in both b/w and color icons, the
  1145. * bits are stored on top of one another (AND/XOR mask, AND/COLOR bitmap).
  1146. * When bitmaps are passed in to CreateIconIndirect(), they are passed
  1147. * as two bitmaps in the color case, and one bitmap (with the stacked
  1148. * masks) in the black and white case. Adjust cur.cy so it is 2 icons
  1149. * high in both cases.
  1150. */
  1151. RtlZeroMemory(&cur, sizeof(cur));
  1152. cur.cx = bmMask.bmWidth;
  1153. if (piconinfo->hbmColor == NULL) {
  1154. cur.cy = bmMask.bmHeight;
  1155. cur.bpp = 1;
  1156. } else {
  1157. cur.cy = bmMask.bmHeight * 2;
  1158. cur.bpp = (DWORD)(bmColor.bmBitsPixel * bmColor.bmPlanes);
  1159. cur.hbmColor = CopyBmp(piconinfo->hbmColor, 0, 0, LR_flags);
  1160. if (cur.hbmColor == NULL) {
  1161. RIPMSG0(RIP_WARNING, "CreateIconIndirect: Failed to copy piconinfo->hbmColor");
  1162. goto CleanUp;
  1163. }
  1164. }
  1165. /*
  1166. * hbmMask must always be double height, even for color icons.
  1167. * So cy might be equal to bmMask.bmHeight * 2 at this point.
  1168. * If this is the case, the second half of hbmMask won't be initilized;
  1169. * nobody is supposed to use it but GDI expects it there when checking the
  1170. * bitmap dimensions (for cursors)
  1171. */
  1172. cur.hbmMask = CreateBitmap(cur.cx, cur.cy, 1, 1, NULL);
  1173. if (cur.hbmMask == NULL) {
  1174. RIPMSG0(RIP_WARNING, "CreateIconIndirect: Failed to create cur.hbmMask");
  1175. goto CleanUp;
  1176. }
  1177. RtlEnterCriticalSection(&gcsHdc);
  1178. if (hdcMem = CreateCompatibleDC (ghdcBits2)) {
  1179. hbmpMem = SelectObject(hdcMem, KHBITMAP_TO_HBITMAP(cur.hbmMask));
  1180. hbmpBits2 = SelectObject(ghdcBits2, piconinfo->hbmMask);
  1181. BitBlt(hdcMem,
  1182. 0,
  1183. 0,
  1184. bmMask.bmWidth,
  1185. bmMask.bmHeight,
  1186. ghdcBits2,
  1187. 0,
  1188. 0,
  1189. SRCCOPY);
  1190. SelectObject(hdcMem, hbmpMem);
  1191. SelectObject(ghdcBits2, hbmpBits2);
  1192. DeleteDC (hdcMem);
  1193. } else {
  1194. RtlLeaveCriticalSection(&gcsHdc);
  1195. RIPMSG0(RIP_WARNING, "CreateIconIndirect: CreateCompatibleDC failed");
  1196. goto CleanUp;
  1197. }
  1198. RtlLeaveCriticalSection(&gcsHdc);
  1199. /*
  1200. * rt and Hotspot
  1201. */
  1202. if (piconinfo->fIcon) {
  1203. cur.rt = PTR_TO_ID(RT_ICON);
  1204. cur.xHotspot = (SHORT)(cur.cx / 2);
  1205. cur.yHotspot = (SHORT)(cur.cy / 4);
  1206. } else {
  1207. cur.rt = PTR_TO_ID(RT_CURSOR);
  1208. cur.xHotspot = ((SHORT)piconinfo->xHotspot);
  1209. cur.yHotspot = ((SHORT)piconinfo->yHotspot);
  1210. }
  1211. if (_SetCursorIconData(hcur, &cur)) {
  1212. return hcur;
  1213. }
  1214. CleanUp:
  1215. /*
  1216. * Note that if this fails, the bitmaps have NOT been made public.
  1217. */
  1218. if (cur.hbmMask != NULL) {
  1219. DeleteObject(KHBITMAP_TO_HBITMAP(cur.hbmMask));
  1220. }
  1221. if (cur.hbmColor != NULL) {
  1222. DeleteObject(KHBITMAP_TO_HBITMAP(cur.hbmColor));
  1223. }
  1224. NtUserDestroyCursor(hcur, CURSOR_ALWAYSDESTROY);
  1225. return NULL;
  1226. }
  1227. /***************************************************************************\
  1228. * GetIconInfo (API)
  1229. *
  1230. * Returns icon information, including bitmaps.
  1231. *
  1232. * 24-Jul-1991 ScottLu Created.
  1233. \***************************************************************************/
  1234. FUNCLOG2(LOG_GENERAL, BOOL, WINAPI, GetIconInfo, HICON, hicon, PICONINFO, piconinfo)
  1235. BOOL WINAPI GetIconInfo(
  1236. HICON hicon,
  1237. PICONINFO piconinfo)
  1238. {
  1239. return NtUserGetIconInfo(hicon, piconinfo, NULL, NULL, NULL, FALSE);
  1240. }
  1241. /***************************************************************************\
  1242. * GetCursorFrameInfo (API)
  1243. *
  1244. * Returns cursor information.
  1245. *
  1246. * 24-Jul-1991 ScottLu Created.
  1247. \***************************************************************************/
  1248. FUNCLOG5(LOG_GENERAL, HCURSOR, WINAPI, GetCursorFrameInfo, HCURSOR, hcur, LPWSTR, lpName, int, iFrame, LPDWORD, pjifRate, LPINT, pccur)
  1249. HCURSOR WINAPI GetCursorFrameInfo(
  1250. HCURSOR hcur,
  1251. LPWSTR lpName,
  1252. int iFrame,
  1253. LPDWORD pjifRate,
  1254. LPINT pccur)
  1255. {
  1256. /*
  1257. * Caller wants us to return the version of this cursor that is stored
  1258. * in the display driver.
  1259. */
  1260. if (hcur == NULL) {
  1261. return LoadIcoCur(NULL,
  1262. lpName,
  1263. RT_CURSOR,
  1264. 0,
  1265. 0,
  1266. LR_DEFAULTSIZE);
  1267. }
  1268. return NtUserGetCursorFrameInfo(hcur, iFrame, pjifRate, pccur);
  1269. }
  1270. /***************************************************************************\
  1271. * _FreeResource (API)
  1272. * _LockResource (API)
  1273. * _UnlockResource (API)
  1274. *
  1275. * These are dummy routines that need to exist for the apfnResCallNative
  1276. * array, which is used when calling the run-time libraries.
  1277. *
  1278. \***************************************************************************/
  1279. BOOL WINAPI _FreeResource(
  1280. HANDLE hResData,
  1281. HINSTANCE hModule)
  1282. {
  1283. UNREFERENCED_PARAMETER(hResData);
  1284. UNREFERENCED_PARAMETER(hModule);
  1285. return FALSE;
  1286. }
  1287. LPSTR WINAPI _LockResource(
  1288. HANDLE hResData,
  1289. HINSTANCE hModule)
  1290. {
  1291. UNREFERENCED_PARAMETER(hModule);
  1292. return (LPSTR)(hResData);
  1293. }
  1294. BOOL WINAPI _UnlockResource(
  1295. HANDLE hResData,
  1296. HINSTANCE hModule)
  1297. {
  1298. UNREFERENCED_PARAMETER(hResData);
  1299. UNREFERENCED_PARAMETER(hModule);
  1300. return TRUE;
  1301. }
  1302. /***************************************************************************\
  1303. * LookupIconIdFromDirectory (API)
  1304. *
  1305. * This searches through an icon directory for the icon that best fits the
  1306. * current display device.
  1307. *
  1308. * 24-07-1991 ScottLu Created.
  1309. \***************************************************************************/
  1310. FUNCLOG2(LOG_GENERAL, int, WINAPI, LookupIconIdFromDirectory, PBYTE, presbits, BOOL, fIcon)
  1311. int WINAPI LookupIconIdFromDirectory(
  1312. PBYTE presbits,
  1313. BOOL fIcon)
  1314. {
  1315. return LookupIconIdFromDirectoryEx(presbits, fIcon, 0, 0, 0);
  1316. }
  1317. /***************************************************************************\
  1318. * LookupIconIdFromDirectoryEx (API)
  1319. *
  1320. *
  1321. \***************************************************************************/
  1322. FUNCLOG5(LOG_GENERAL, int, WINAPI, LookupIconIdFromDirectoryEx, PBYTE, presbits, BOOL, fIcon, int, cxDesired, int, cyDesired, UINT, LR_flags)
  1323. int WINAPI LookupIconIdFromDirectoryEx(
  1324. PBYTE presbits,
  1325. BOOL fIcon,
  1326. int cxDesired,
  1327. int cyDesired,
  1328. UINT LR_flags)
  1329. {
  1330. ConnectIfNecessary(0);
  1331. return RtlGetIdFromDirectory(presbits,
  1332. fIcon,
  1333. cxDesired,
  1334. cyDesired,
  1335. LR_flags,
  1336. NULL);
  1337. }
  1338. /***************************************************************************\
  1339. * LoadCursorIconFromResource (API)
  1340. *
  1341. * Loads animated icon/cursor from a pointer to a resource
  1342. *
  1343. * 02-20-1996 GerardoB Created.
  1344. \***************************************************************************/
  1345. HANDLE LoadCursorIconFromResource(
  1346. PBYTE presbits,
  1347. LPCWSTR lpName,
  1348. int cxDesired,
  1349. int cyDesired,
  1350. UINT LR_flags)
  1351. {
  1352. BOOL fAni;
  1353. FILEINFO fi;
  1354. LPWSTR lpwszRT;
  1355. fi.pFileMap = presbits;
  1356. fi.pFilePtr = fi.pFileMap;
  1357. fi.pFileEnd = fi.pFileMap + sizeof (RTAG) + ((RTAG *)presbits)->ckSize;
  1358. fi.pszName = lpName;
  1359. return LoadCursorIconFromFileMap(&fi,
  1360. &lpwszRT,
  1361. cxDesired,
  1362. cyDesired,
  1363. LR_flags,
  1364. &fAni);
  1365. }
  1366. /***************************************************************************\
  1367. * CreateIconFromResource (API)
  1368. *
  1369. * Takes resource bits and creates either an icon or cursor.
  1370. *
  1371. * 24-07-1991 ScottLu Created.
  1372. \***************************************************************************/
  1373. FUNCLOG4(LOG_GENERAL, HICON, WINAPI, CreateIconFromResource, PBYTE, presbits, DWORD, dwResSize, BOOL, fIcon, DWORD, dwVer)
  1374. HICON WINAPI CreateIconFromResource(
  1375. PBYTE presbits,
  1376. DWORD dwResSize,
  1377. BOOL fIcon,
  1378. DWORD dwVer)
  1379. {
  1380. return CreateIconFromResourceEx(presbits,
  1381. dwResSize,
  1382. fIcon,
  1383. dwVer,
  1384. 0,
  1385. 0,
  1386. LR_DEFAULTSIZE | LR_SHARED);
  1387. }
  1388. /***************************************************************************\
  1389. * CreateIconFromResourceEx (API)
  1390. *
  1391. * Takes resource bits and creates either an icon or cursor.
  1392. *
  1393. * 30-Aug-1994 FritzS Created
  1394. \***************************************************************************/
  1395. FUNCLOG7(LOG_GENERAL, HICON, WINAPI, CreateIconFromResourceEx, PBYTE, presbits, DWORD, dwResSize, BOOL, fIcon, DWORD, dwVer, int, cxDesired, int, cyDesired, UINT, LR_flags)
  1396. HICON WINAPI CreateIconFromResourceEx(
  1397. PBYTE presbits,
  1398. DWORD dwResSize,
  1399. BOOL fIcon,
  1400. DWORD dwVer,
  1401. int cxDesired,
  1402. int cyDesired,
  1403. UINT LR_flags)
  1404. {
  1405. UNREFERENCED_PARAMETER(dwResSize);
  1406. /*
  1407. * NT Specific code to validate the version.
  1408. */
  1409. if ((dwVer < 0x00020000) || (dwVer > 0x00030000)) {
  1410. RIPMSG0(RIP_WARNING, "CreateIconFromResourceEx: Invalid Paramter");
  1411. return NULL;
  1412. }
  1413. /*
  1414. * Set desired size of resource based on flags and/or true
  1415. * dimensions passed in.
  1416. */
  1417. cxDesired = GetIcoCurWidth(cxDesired , fIcon, LR_flags, 0);
  1418. cyDesired = GetIcoCurHeight(cyDesired, fIcon, LR_flags, 0);
  1419. if (ISRIFFFORMAT(presbits)) {
  1420. return LoadCursorIconFromResource (presbits, NULL, cxDesired, cyDesired, LR_flags);
  1421. } else {
  1422. return ConvertDIBIcon((LPBITMAPINFOHEADER)presbits,
  1423. NULL,
  1424. NULL,
  1425. fIcon,
  1426. cxDesired,
  1427. cyDesired,
  1428. LR_flags);
  1429. }
  1430. }
  1431. /***************************************************************************\
  1432. * Convert1BppToMonoBitmap
  1433. *
  1434. * This routine converts a 1bpp bitmap to a true monochrome surface. This
  1435. * is done for bitmaps which need to do foreground/background color matching
  1436. * at output time. Otherwise, a 1bpp will just match to its palette.
  1437. *
  1438. * NOTE: This routine deletes the original bitmap if successful. If failure
  1439. * we'll return the original bitmap.
  1440. *
  1441. * History:
  1442. * 17-Apr-1996 ChrisWil Created
  1443. \***************************************************************************/
  1444. HBITMAP Convert1BppToMonoBitmap(
  1445. HDC hdcSrc,
  1446. HBITMAP hbm1Bpp)
  1447. {
  1448. HBITMAP hbmMono = hbm1Bpp;
  1449. HBITMAP hbmDst;
  1450. HBITMAP hbmS;
  1451. HBITMAP hbmD;
  1452. HDC hdcDst;
  1453. BITMAP bm;
  1454. if (hdcDst = CreateCompatibleDC(hdcSrc)) {
  1455. GetObject(hbm1Bpp, sizeof(BITMAP), &bm);
  1456. if (hbmDst = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL)) {
  1457. hbmS = SelectBitmap(hdcSrc, hbm1Bpp);
  1458. hbmD = SelectBitmap(hdcDst, hbmDst);
  1459. BitBlt(hdcDst,
  1460. 0,
  1461. 0,
  1462. bm.bmWidth,
  1463. bm.bmHeight,
  1464. hdcSrc,
  1465. 0,
  1466. 0,
  1467. SRCCOPY);
  1468. SelectBitmap(hdcSrc, hbmS);
  1469. SelectBitmap(hdcDst, hbmD);
  1470. hbmMono = hbmDst;
  1471. DeleteObject(hbm1Bpp);
  1472. }
  1473. DeleteDC(hdcDst);
  1474. }
  1475. return hbmMono;
  1476. }
  1477. /***************************************************************************\
  1478. * CreateScreenBitmap
  1479. *
  1480. * This routine creates a screen bitmap. We use the CreateDIBitmap call
  1481. * to do compatible color-matching with Win95. Also, note that this
  1482. * routine takes in WORD aligned bits.
  1483. *
  1484. \***************************************************************************/
  1485. HBITMAP CreateScreenBitmap(
  1486. int cx,
  1487. int cy,
  1488. UINT planes,
  1489. UINT bpp,
  1490. LPSTR lpBits,
  1491. LPBOOL pf1Bpp)
  1492. {
  1493. HDC hdcScreen;
  1494. HBITMAP hbm = NULL;
  1495. DWORD dwCount;
  1496. static struct {
  1497. BITMAPINFOHEADER bi;
  1498. DWORD ct[16];
  1499. } dib4Vga = {{sizeof(BITMAPINFOHEADER),
  1500. 0,
  1501. 0,
  1502. 1,
  1503. 4,
  1504. BI_RGB,
  1505. 0,
  1506. 0,
  1507. 0,
  1508. 16,
  1509. 0
  1510. },
  1511. {0x00000000,
  1512. 0x00800000,
  1513. 0x00008000,
  1514. 0x00808000,
  1515. 0x00000080,
  1516. 0x00800080,
  1517. 0x00008080,
  1518. 0x00C0C0C0,
  1519. 0x00808080,
  1520. 0x00FF0000,
  1521. 0x0000FF00,
  1522. 0x00FFFF00,
  1523. 0x000000FF,
  1524. 0x00FF00FF,
  1525. 0x0000FFFF,
  1526. 0x00FFFFFF
  1527. }
  1528. };
  1529. static struct {
  1530. BITMAPINFOHEADER bi;
  1531. DWORD ct[2];
  1532. } dib1Vga = {{sizeof(BITMAPINFOHEADER),
  1533. 0,
  1534. 0,
  1535. 1,
  1536. 1,
  1537. BI_RGB,
  1538. 0,
  1539. 0,
  1540. 0,
  1541. 2,
  1542. 0
  1543. },
  1544. {0x00000000,
  1545. 0x00FFFFFF
  1546. }
  1547. };
  1548. /*
  1549. * Create the surface.
  1550. */
  1551. if (hdcScreen = GETINITDC()) {
  1552. /*
  1553. * This appears to mess up color to mono conversion by losing all
  1554. * the data and forcing all non-forground colors to black.
  1555. * (try copyimage with IDC_WARNING_DEFAULT)
  1556. * This is what win95 does but their system works. The scary thing
  1557. * (according to marke) is that win95 may have changed GDI to make
  1558. * this work.
  1559. *
  1560. * In order to get nearest-color-matching compatible with Win95,
  1561. * we're going to need to use the CreateDIBitmap() for mono-surfaces.
  1562. * This code-path will do nearest-color, rather than color-matching.
  1563. */
  1564. if ((bpp == 1) && (planes == 1)) {
  1565. dib1Vga.bi.biWidth = cx;
  1566. dib1Vga.bi.biHeight = cy;
  1567. hbm = CreateDIBitmap(hdcScreen,
  1568. (LPBITMAPINFOHEADER)&dib1Vga,
  1569. CBM_CREATEDIB,
  1570. NULL,
  1571. (LPBITMAPINFO)&dib1Vga,
  1572. DIB_RGB_COLORS);
  1573. *pf1Bpp = TRUE;
  1574. } else {
  1575. if (((planes == 0) || (planes == gpsi->Planes)) &&
  1576. ((bpp == 0) || (bpp == gpsi->BitsPixel))) {
  1577. hbm = CreateCompatibleBitmap(hdcScreen, cx, cy);
  1578. } else {
  1579. dib4Vga.bi.biBitCount = planes * bpp ? planes * bpp : gpsi->BitCount;
  1580. #if 0 // We use to do the dib-section create, but this breaks icons
  1581. // when they are made public (can't make a dibsection public). So
  1582. // we now wil create this as a real-dib.
  1583. //
  1584. {
  1585. DWORD dwDummy;
  1586. dib4Vga.bi.biWidth = cx;
  1587. dib4Vga.bi.biHeight = -cy; // top-down DIB (like a DDB)
  1588. hbm = CreateDIBSection(hdcScreen,
  1589. (LPBITMAPINFO)&dib4Vga,
  1590. DIB_RGB_COLORS,
  1591. (LPVOID)&dwDummy,
  1592. 0,
  1593. 0);
  1594. }
  1595. #else
  1596. dib4Vga.bi.biWidth = cx;
  1597. dib4Vga.bi.biHeight = cy;
  1598. hbm = CreateDIBitmap(hdcScreen,
  1599. (LPBITMAPINFOHEADER)&dib4Vga,
  1600. CBM_CREATEDIB,
  1601. NULL,
  1602. (LPBITMAPINFO)&dib4Vga,
  1603. DIB_RGB_COLORS);
  1604. #endif
  1605. }
  1606. }
  1607. RELEASEINITDC(hdcScreen);
  1608. }
  1609. if (hbm && lpBits) {
  1610. BITMAP bm;
  1611. GetObject(hbm, sizeof(BITMAP), &bm);
  1612. dwCount = (DWORD)(UINT)(bm.bmWidthBytes * bm.bmPlanes) * (DWORD)(UINT)cy;
  1613. SetBitmapBits(hbm, dwCount, lpBits);
  1614. }
  1615. return hbm;
  1616. }
  1617. /***************************************************************************\
  1618. * LoadBmp (Worker)
  1619. *
  1620. * This routine decides whether the bitmap to be loaded is in old or new (DIB)
  1621. * format and calls appropriate handlers.
  1622. *
  1623. * History:
  1624. * 24-Sep-1990 MikeKe From Win30.
  1625. * 18-Jun-1991 ChuckWh Added local bitmap handle support.
  1626. * 05-Sep-1995 ChrisWil Port/Change for Chicago functionality.
  1627. \***************************************************************************/
  1628. HBITMAP LoadBmp(
  1629. HINSTANCE hmod,
  1630. LPCWSTR lpName,
  1631. int cxDesired,
  1632. int cyDesired,
  1633. UINT flags)
  1634. {
  1635. HBITMAP hbmp = NULL;
  1636. BOOL fFree = FALSE, f1Bpp = FALSE;
  1637. /***************************************************************************\
  1638. * Bitmap Resource Table
  1639. *
  1640. * As of WIN4.0, most system bitmaps are rendered instead of grabbed from the
  1641. * display driver. However, a lot of apps, especially those that fake their
  1642. * own MDI, do LoadBitmap(NULL, OBM_...) to grab a system bitmap. So we
  1643. * hook those requests here and copy our rendered bitmaps into a newly-
  1644. * created bitmap. Note that this is actually faster than loading from a
  1645. * resource table!
  1646. *
  1647. * BOGUS -- give 'em old close buttons, not new cool X's
  1648. *
  1649. \***************************************************************************/
  1650. #define MAX_BMPMAP 32
  1651. CONST static MAPRES MapOemBmp[MAX_BMPMAP] = {
  1652. {OBM_BTNCORNERS , OBI_RADIOMASK , },
  1653. {OBM_BTSIZE , OBI_NCGRIP , },
  1654. {OBM_CHECK , OBI_MENUCHECK , MR_MONOCHROME },
  1655. {OBM_CHECKBOXES , OBI_CHECK , },
  1656. {OBM_COMBO , OBI_DNARROW , },
  1657. {OBM_DNARROW , OBI_DNARROW , },
  1658. {OBM_DNARROWD , OBI_DNARROW_D , },
  1659. {OBM_DNARROWI , OBI_DNARROW_I , },
  1660. {OBM_LFARROW , OBI_LFARROW , },
  1661. {OBM_LFARROWD , OBI_LFARROW_D , },
  1662. {OBM_LFARROWI , OBI_LFARROW_I , },
  1663. /*
  1664. * Use MONO bitmaps in future once flat/mono controls are worked out.
  1665. */
  1666. {OBM_OLD_DNARROW, OBI_DNARROW , MR_FAILFOR40 },
  1667. {OBM_OLD_LFARROW, OBI_LFARROW , MR_FAILFOR40 },
  1668. {OBM_OLD_REDUCE , OBI_REDUCE_MBAR , MR_FAILFOR40 },
  1669. {OBM_OLD_RESTORE, OBI_RESTORE_MBAR , MR_FAILFOR40 },
  1670. {OBM_OLD_RGARROW, OBI_RGARROW , MR_FAILFOR40 },
  1671. {OBM_OLD_UPARROW, OBI_UPARROW , MR_FAILFOR40 },
  1672. {OBM_OLD_ZOOM , OBI_ZOOM , MR_FAILFOR40 },
  1673. {OBM_MNARROW , OBI_MENUARROW , MR_MONOCHROME },
  1674. {OBM_REDUCE , OBI_REDUCE_MBAR , },
  1675. {OBM_REDUCED , OBI_REDUCE_MBAR_D , },
  1676. {OBM_RESTORE , OBI_RESTORE_MBAR , },
  1677. {OBM_RESTORED , OBI_RESTORE_MBAR_D , },
  1678. {OBM_RGARROW , OBI_RGARROW , },
  1679. {OBM_RGARROWD , OBI_RGARROW_D , },
  1680. {OBM_RGARROWI , OBI_RGARROW_I , },
  1681. {OBM_SIZE , OBI_NCGRIP , },
  1682. {OBM_UPARROW , OBI_UPARROW , },
  1683. {OBM_UPARROWD , OBI_UPARROW_D , },
  1684. {OBM_UPARROWI , OBI_UPARROW_I , },
  1685. {OBM_ZOOM , OBI_ZOOM , },
  1686. {OBM_ZOOMD , OBI_ZOOM_D , }
  1687. };
  1688. /*
  1689. * If hmod is valid, load the client-side bits.
  1690. */
  1691. if (hmod == NULL) {
  1692. HBITMAP hOldBmp;
  1693. WORD bm;
  1694. WORD wID;
  1695. BOOL fCombo;
  1696. BOOL fCheckBoxes;
  1697. int i;
  1698. RECT rc;
  1699. BOOL fSysMenu = FALSE;
  1700. BOOL fMenu = FALSE;
  1701. BOOL fMono = FALSE;
  1702. hmod = hmodUser;
  1703. /*
  1704. * Since the resource is coming from USER32, we only
  1705. * deal with ID types.
  1706. */
  1707. wID = PTR_TO_ID(lpName);
  1708. switch(wID) {
  1709. case OBM_OLD_CLOSE:
  1710. if (GETAPPVER() >= VER40) {
  1711. goto FailOldLoad;
  1712. }
  1713. /*
  1714. * fall through to the Close case.
  1715. */
  1716. case OBM_CLOSE:
  1717. /* the new look for the system menu is to use the window's
  1718. * class icon -- but since here we don't know which window
  1719. * they'll be using this for, fall back on the good ole'
  1720. * windows logo icon
  1721. */
  1722. cxDesired = (SYSMET(CXMENUSIZE) + SYSMET(CXEDGE)) * 2;
  1723. cyDesired = SYSMET(CYMENUSIZE) + (2 * SYSMET(CYEDGE));
  1724. fSysMenu = TRUE;
  1725. break;
  1726. case OBM_TRUETYPE: {
  1727. PVOID p;
  1728. HANDLE h;
  1729. int nOffset;
  1730. /*
  1731. * Offset into resource.
  1732. */
  1733. if (gpsi->dmLogPixels == 120) {
  1734. nOffset = OFFSET_120_DPI;
  1735. } else {
  1736. nOffset = OFFSET_96_DPI;
  1737. }
  1738. lpName = (LPWSTR)(MAX_RESOURCE_INDEX -
  1739. ((ULONG_PTR)lpName) + nOffset);
  1740. if (h = FINDRESOURCEW(hmod, (LPWSTR)lpName, RT_BITMAP)) {
  1741. if (h = LOADRESOURCE(hmod, h)) {
  1742. if (p = LOCKRESOURCE(h, hmod)) {
  1743. hbmp = (HBITMAP)ObjectFromDIBResource(hmod,
  1744. lpName,
  1745. RT_BITMAP,
  1746. cxDesired,
  1747. cyDesired,
  1748. flags);
  1749. UNLOCKRESOURCE(h, hmod);
  1750. }
  1751. FREERESOURCE(h, hmod);
  1752. }
  1753. }
  1754. goto LoadBmpDone;
  1755. }
  1756. break;
  1757. default:
  1758. fCombo = (wID == OBM_COMBO);
  1759. fCheckBoxes = (wID == OBM_CHECKBOXES);
  1760. /*
  1761. * hard loop to check for mapping.
  1762. */
  1763. for (i=0; (i < MAX_BMPMAP) && (MapOemBmp[i].idDisp != wID); i++);
  1764. if (i == MAX_BMPMAP)
  1765. goto LoadForReal;
  1766. if ((MapOemBmp[i].bFlags & MR_FAILFOR40) &&
  1767. (GETAPPVER() >= VER40)) {
  1768. FailOldLoad:
  1769. RIPMSG0(RIP_WARNING, "LoadBitmap: old IDs not allowed for 4.0 apps");
  1770. return NULL;
  1771. }
  1772. if (MapOemBmp[i].bFlags & MR_MONOCHROME)
  1773. fMono = TRUE;
  1774. bm = MapOemBmp[i].idUser;
  1775. if ((bm == OBI_REDUCE_MBAR) || (bm == OBI_RESTORE_MBAR))
  1776. fMenu = TRUE;
  1777. cxDesired = gpsi->oembmi[bm].cx;
  1778. cyDesired = gpsi->oembmi[bm].cy;
  1779. if (fMenu)
  1780. cyDesired += (2 * SYSMET(CYEDGE));
  1781. if (fCheckBoxes) {
  1782. cxDesired *= NUM_BUTTON_STATES;
  1783. cyDesired *= NUM_BUTTON_TYPES;
  1784. } else if (fCombo) {
  1785. cxDesired -= (2 * SYSMET(CXEDGE));
  1786. cyDesired -= (2 * SYSMET(CYEDGE));
  1787. }
  1788. break;
  1789. }
  1790. /*
  1791. * Creates DIB section or color compatible.
  1792. */
  1793. if (fMono) {
  1794. /*
  1795. * Create mono-bitmaps as DIBs on NT. On Win95 this is
  1796. * called as:
  1797. *
  1798. * hbmp = CreateBitmap(cxDesired, cyDesired, 1, 1, NULL);
  1799. *
  1800. * However, due to color-matching differences, we need to
  1801. * use dibs to get the nearest-color-matching. At the
  1802. * end of this routine we will convert to a true-mono so that
  1803. * foreground/background matching can be performed normally.
  1804. */
  1805. hbmp = CreateScreenBitmap(cxDesired, cyDesired, 1, 1, NULL, &f1Bpp);
  1806. } else {
  1807. hbmp = CreateScreenBitmap(cxDesired, cyDesired, 0, 0, NULL, &f1Bpp);
  1808. }
  1809. if (hbmp == NULL)
  1810. goto LoadBmpDone;
  1811. RtlEnterCriticalSection(&gcsHdc);
  1812. hOldBmp = SelectBitmap(ghdcBits2, hbmp);
  1813. UserAssert(GetBkColor(ghdcBits2) == RGB(255,255,255));
  1814. UserAssert(GetTextColor(ghdcBits2) == RGB(0, 0, 0));
  1815. rc.top = 0;
  1816. rc.left = 0;
  1817. rc.bottom = cyDesired;
  1818. rc.right = cxDesired;
  1819. if (fMono) {
  1820. PatBlt(ghdcBits2, 0, 0, cxDesired, cyDesired, WHITENESS);
  1821. } else {
  1822. FillRect(ghdcBits2,
  1823. &rc,
  1824. ((fMenu | fSysMenu) ? SYSHBR(MENU) : SYSHBR(WINDOW)));
  1825. }
  1826. if (fSysMenu) {
  1827. int x = SYSMET(CXEDGE);
  1828. cxDesired /= 2;
  1829. for (i = 0; i < 2; i++) {
  1830. DrawIconEx(ghdcBits2,
  1831. x,
  1832. SYSMET(CYEDGE),
  1833. KHICON_TO_HICON(gpsi->hIconSmWindows),
  1834. cxDesired - 2 * SYSMET(CXEDGE),
  1835. SYSMET(CYMENUSIZE) - SYSMET(CYEDGE),
  1836. 0,
  1837. NULL,
  1838. DI_NORMAL);
  1839. x += cxDesired;
  1840. }
  1841. } else if (fCombo) {
  1842. /*
  1843. * Revisit when we start using TTF -- that'll take care of this
  1844. * hack.
  1845. */
  1846. rc.top = -SYSMET(CYEDGE);
  1847. rc.bottom += SYSMET(CYEDGE);
  1848. rc.left = -SYSMET(CXEDGE);
  1849. rc.right += SYSMET(CXEDGE);
  1850. DrawFrameControl(ghdcBits2,
  1851. &rc,
  1852. DFC_SCROLL,
  1853. DFCS_SCROLLDOWN);
  1854. } else if (fCheckBoxes) {
  1855. int wType, wState, x;
  1856. DWORD clrTextSave, clrBkSave;
  1857. int y = 0;
  1858. for (wType = 0; wType < NUM_BUTTON_TYPES; wType++) {
  1859. x = 0;
  1860. cxDesired = gpsi->oembmi[bm].cx;
  1861. cyDesired = gpsi->oembmi[bm].cy;
  1862. if (wType == 1) {
  1863. /*
  1864. * BOGUS UGLINESS -- will be fixed once the Graphics dudes
  1865. * get me the icon TTF -- I'll revisit this then and make
  1866. * REAL
  1867. */
  1868. clrTextSave = SetTextColor(ghdcBits2, RESCLR_BLACK);
  1869. clrBkSave = SetBkColor (ghdcBits2, RESCLR_WHITE);
  1870. for (wState = 0; wState < NUM_BUTTON_STATES; wState++) {
  1871. NtUserBitBltSysBmp(ghdcBits2,
  1872. x,
  1873. y,
  1874. cxDesired,
  1875. cyDesired,
  1876. gpsi->oembmi[OBI_RADIOMASK].x,
  1877. gpsi->oembmi[OBI_RADIOMASK].y,
  1878. SRCAND);
  1879. NtUserBitBltSysBmp(ghdcBits2,
  1880. x,
  1881. y,
  1882. cxDesired,
  1883. cyDesired,
  1884. gpsi->oembmi[bm].x,
  1885. gpsi->oembmi[bm].y,
  1886. SRCINVERT);
  1887. x += cxDesired;
  1888. bm++;
  1889. }
  1890. SetTextColor(ghdcBits2, clrTextSave);
  1891. SetBkColor(ghdcBits2, clrBkSave);
  1892. } else {
  1893. for (wState = 0; wState < NUM_BUTTON_STATES; wState++) {
  1894. BitBltSysBmp(ghdcBits2, x, y, bm);
  1895. x += cxDesired;
  1896. bm++;
  1897. }
  1898. /*
  1899. * Skip OBI_*_CDI.
  1900. */
  1901. bm++;
  1902. }
  1903. y += cyDesired;
  1904. }
  1905. } else {
  1906. BitBltSysBmp(ghdcBits2, 0, fMenu ? SYSMET(CYEDGE) : 0, bm);
  1907. }
  1908. SelectBitmap(ghdcBits2, hOldBmp);
  1909. /*
  1910. * If the bitmap was created as a 1bpp, we need to convert to a
  1911. * true mono-bitmap. GDI performs different color-matching depending
  1912. * upon this case.
  1913. */
  1914. if (f1Bpp && hbmp)
  1915. hbmp = Convert1BppToMonoBitmap(ghdcBits2, hbmp);
  1916. RtlLeaveCriticalSection(&gcsHdc);
  1917. } else {
  1918. LoadForReal:
  1919. hbmp = (HBITMAP)ObjectFromDIBResource(hmod,
  1920. lpName,
  1921. RT_BITMAP,
  1922. cxDesired,
  1923. cyDesired,
  1924. flags);
  1925. }
  1926. LoadBmpDone:
  1927. return hbmp;
  1928. }
  1929. /***************************************************************************\
  1930. * LoadBitmapA (API)
  1931. * LoadBitmapW (API)
  1932. *
  1933. * Loads a bitmap from client. If hmod == NULL, loads a bitmap from the
  1934. * system.
  1935. *
  1936. \***************************************************************************/
  1937. FUNCLOG2(LOG_GENERAL, HBITMAP, WINAPI, LoadBitmapA, HINSTANCE, hmod, LPCSTR, lpName)
  1938. HBITMAP WINAPI LoadBitmapA(
  1939. HINSTANCE hmod,
  1940. LPCSTR lpName)
  1941. {
  1942. LPWSTR lpUniName;
  1943. HBITMAP hRet;
  1944. if (ID(lpName))
  1945. return LoadBmp(hmod, (LPCWSTR)lpName, 0, 0, 0);
  1946. if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE))
  1947. return NULL;
  1948. hRet = LoadBmp(hmod, lpUniName, 0, 0, 0);
  1949. UserLocalFree(lpUniName);
  1950. return hRet;
  1951. }
  1952. FUNCLOG2(LOG_GENERAL, HBITMAP, WINAPI, LoadBitmapW, HINSTANCE, hmod, LPCWSTR, lpName)
  1953. HBITMAP WINAPI LoadBitmapW(
  1954. HINSTANCE hmod,
  1955. LPCWSTR lpName)
  1956. {
  1957. return LoadBmp(hmod, lpName, 0, 0, 0);
  1958. }
  1959. /***************************************************************************\
  1960. * LoadCursorA (API)
  1961. * LoadCursorW (API)
  1962. *
  1963. * Loads a cursor from client. If hmod == NULL, loads a cursor from the
  1964. * system.
  1965. *
  1966. * 05-Apr-1991 ScottLu Rewrote to work with client server.
  1967. \***************************************************************************/
  1968. FUNCLOG2(LOG_GENERAL, HCURSOR, WINAPI, LoadCursorA, HINSTANCE, hmod, LPCSTR, lpName)
  1969. HCURSOR WINAPI LoadCursorA(
  1970. HINSTANCE hmod,
  1971. LPCSTR lpName)
  1972. {
  1973. HCURSOR hRet;
  1974. LPWSTR lpUniName;
  1975. if (ID(lpName))
  1976. return LoadCursorW(hmod, (LPWSTR)lpName);
  1977. if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE))
  1978. return NULL;
  1979. hRet = LoadCursorW(hmod, lpUniName);
  1980. UserLocalFree(lpUniName);
  1981. return hRet;
  1982. }
  1983. FUNCLOG2(LOG_GENERAL, HCURSOR, WINAPI, LoadCursorW, HINSTANCE, hmod, LPCWSTR, lpName)
  1984. HCURSOR WINAPI LoadCursorW(
  1985. HINSTANCE hmod,
  1986. LPCWSTR lpName)
  1987. {
  1988. return LoadIcoCur(hmod,
  1989. lpName,
  1990. RT_CURSOR,
  1991. 0,
  1992. 0,
  1993. LR_DEFAULTSIZE | LR_SHARED);
  1994. }
  1995. /***************************************************************************\
  1996. * LoadIconA (API)
  1997. * LoadIconW (API)
  1998. *
  1999. * Loads an icon from client. If hmod == NULL, loads an icon from the
  2000. * system.
  2001. *
  2002. * 05-Apr-1991 ScottLu Rewrote to work with client server.
  2003. \***************************************************************************/
  2004. FUNCLOG2(LOG_GENERAL, HICON, WINAPI, LoadIconA, HINSTANCE, hmod, LPCSTR, lpName)
  2005. HICON WINAPI LoadIconA(
  2006. HINSTANCE hmod,
  2007. LPCSTR lpName)
  2008. {
  2009. HICON hRet;
  2010. LPWSTR lpUniName;
  2011. if (ID(lpName))
  2012. return LoadIconW(hmod, (LPWSTR)lpName);
  2013. if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE))
  2014. return NULL;
  2015. hRet = LoadIconW(hmod, lpUniName);
  2016. UserLocalFree(lpUniName);
  2017. return hRet;
  2018. }
  2019. FUNCLOG2(LOG_GENERAL, HICON, WINAPI, LoadIconW, HINSTANCE, hmod, LPCWSTR, lpName)
  2020. HICON WINAPI LoadIconW(
  2021. HINSTANCE hmod,
  2022. LPCWSTR lpName)
  2023. {
  2024. return LoadIcoCur(hmod,
  2025. lpName,
  2026. RT_ICON,
  2027. 0,
  2028. 0,
  2029. LR_DEFAULTSIZE | LR_SHARED);
  2030. }
  2031. /***************************************************************************\
  2032. * LoadImageA (API)
  2033. * LoadImageW (API)
  2034. *
  2035. * Loads a bitmap, icon or cursor resource from client. If hmod == NULL,
  2036. * then it will load from system-resources.
  2037. *
  2038. \***************************************************************************/
  2039. FUNCLOG6(LOG_GENERAL, HANDLE, WINAPI, LoadImageA, HINSTANCE, hmod, LPCSTR, lpName, UINT, type, int, cxDesired, int, cyDesired, UINT, flags)
  2040. HANDLE WINAPI LoadImageA(
  2041. HINSTANCE hmod,
  2042. LPCSTR lpName,
  2043. UINT type,
  2044. int cxDesired,
  2045. int cyDesired,
  2046. UINT flags)
  2047. {
  2048. LPWSTR lpUniName;
  2049. HANDLE hRet;
  2050. if (ID(lpName))
  2051. return LoadImageW(hmod,
  2052. (LPCWSTR)lpName,
  2053. type,
  2054. cxDesired,
  2055. cyDesired,
  2056. flags);
  2057. if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE))
  2058. return NULL;
  2059. hRet = LoadImageW(hmod, lpUniName, type, cxDesired, cyDesired, flags);
  2060. UserLocalFree(lpUniName);
  2061. return hRet;
  2062. }
  2063. FUNCLOG6(LOG_GENERAL, HANDLE, WINAPI, LoadImageW, HINSTANCE, hmod, LPCWSTR, lpName, UINT, IMAGE_code, int, cxDesired, int, cyDesired, UINT, flags)
  2064. HANDLE WINAPI LoadImageW(
  2065. HINSTANCE hmod,
  2066. LPCWSTR lpName,
  2067. UINT IMAGE_code,
  2068. int cxDesired,
  2069. int cyDesired,
  2070. UINT flags)
  2071. {
  2072. /*
  2073. * If we specified LR_LOADFROMFILE, then we can tweak the
  2074. * flags to turn off LR_SHARED.
  2075. */
  2076. if (flags & LR_LOADFROMFILE)
  2077. flags &= ~LR_SHARED;
  2078. switch (IMAGE_code) {
  2079. case IMAGE_BITMAP:
  2080. return (HANDLE)LoadBmp(hmod, lpName, cxDesired, cyDesired, flags);
  2081. case IMAGE_CURSOR:
  2082. #if 0 //CHRISWIL : oemInfo.fColorCursors doesn't exist on NT.
  2083. if (!oemInfo.fColorCursors)
  2084. flags |= LR_MONOCHROME;
  2085. #endif
  2086. case IMAGE_ICON:
  2087. /*
  2088. * On WinNT 3.51, an app can successfully load a
  2089. * USER icon without specifying LR_SHARED. We enable
  2090. * these apps to succeed, but make 4.0 apps conform to
  2091. * Windows95 behavior.
  2092. */
  2093. if (!hmod && GETEXPWINVER(NULL) < VER40) {
  2094. flags |= LR_SHARED;
  2095. }
  2096. return (HANDLE)LoadIcoCur(hmod,
  2097. lpName,
  2098. ((IMAGE_code == IMAGE_ICON) ? RT_ICON : RT_CURSOR),
  2099. cxDesired,
  2100. cyDesired,
  2101. flags);
  2102. default:
  2103. RIPMSG0(RIP_WARNING, "LoadImage: invalid IMAGE_code");
  2104. return NULL;
  2105. }
  2106. }
  2107. /***************************************************************************\
  2108. * GetIconIdEx
  2109. *
  2110. * This one accepts width, height, and other flags. Just not exported right
  2111. * now.
  2112. *
  2113. \***************************************************************************/
  2114. UINT GetIconIdEx(
  2115. HINSTANCE hmod,
  2116. HANDLE hrsd,
  2117. LPCWSTR lpszType,
  2118. DWORD cxDesired,
  2119. DWORD cyDesired,
  2120. UINT LR_flags)
  2121. {
  2122. int idIcon = 0;
  2123. LPNEWHEADER lpnh;
  2124. if (lpnh = (LPNEWHEADER)LOCKRESOURCE(hrsd, hmod)) {
  2125. /*
  2126. * Do a sanity check on this data structure. Otherwise we'll GP FAULT
  2127. * when extracting an icon from a corrupted area. Fix for B#9290.
  2128. * SANKAR, 08/13/91
  2129. */
  2130. if ((lpnh->Reserved == 0) &&
  2131. ((lpnh->ResType == IMAGE_ICON) || (lpnh->ResType == IMAGE_CURSOR))) {
  2132. idIcon = LookupIconIdFromDirectoryEx((PBYTE)lpnh,
  2133. (lpszType == RT_ICON),
  2134. cxDesired,
  2135. cyDesired,
  2136. LR_flags);
  2137. }
  2138. UNLOCKRESOURCE(hrsd, hmod);
  2139. }
  2140. return idIcon;
  2141. }
  2142. /***************************************************************************\
  2143. * LoadDib (Worker)
  2144. *
  2145. * This is the worker-routine for loading a resource and returning a handle
  2146. * to the object as a dib.
  2147. *
  2148. \***************************************************************************/
  2149. HANDLE LoadDIB(
  2150. HINSTANCE hmod,
  2151. LPCWSTR lpName,
  2152. LPWSTR type,
  2153. DWORD cxDesired,
  2154. DWORD cyDesired,
  2155. UINT LR_flags)
  2156. {
  2157. HANDLE hDir;
  2158. UINT idIcon;
  2159. LPWSTR lpszGroupType;
  2160. HANDLE hRes = NULL;
  2161. switch (PTR_TO_ID(type)) {
  2162. case PTR_TO_ID(RT_ICON):
  2163. case PTR_TO_ID(RT_CURSOR):
  2164. lpszGroupType = RT_GROUP_CURSOR + (type - RT_CURSOR);
  2165. /*
  2166. * For WOW support, OIC_ICON and OIC_SIZE need to be supported.
  2167. * Since these resources match other existing resources, we map
  2168. * them here so we produce results that emulates
  2169. * behavor as if we had the actual resources in USER.
  2170. *
  2171. * Note that obsolete mapping of lpName in LoadIcoCur prevents
  2172. * win4.0 apps from getting here.
  2173. */
  2174. if (hmod == hmodUser) {
  2175. switch ((ULONG_PTR)lpName) {
  2176. case OCR_SIZE:
  2177. lpName = (LPCWSTR)OCR_SIZEALL_DEFAULT;
  2178. break;
  2179. case OCR_ICON:
  2180. lpName = (LPCWSTR)OCR_ICON_DEFAULT;
  2181. break;
  2182. }
  2183. }
  2184. /*
  2185. * The resource is actually a directory which contains multiple
  2186. * individual image resources we must choose from.
  2187. * Locate the directory
  2188. */
  2189. if (hDir = SplFindResource(hmod, lpName, (LPCWSTR)lpszGroupType)) {
  2190. /*
  2191. * Load the directory.
  2192. */
  2193. if (hDir = LOADRESOURCE(hmod, hDir)) {
  2194. /*
  2195. * Get the name of the best individual image.
  2196. */
  2197. if (idIcon = GetIconIdEx(hmod,
  2198. hDir,
  2199. type,
  2200. cxDesired,
  2201. cyDesired,
  2202. LR_flags)) {
  2203. /*
  2204. * NOTE: Don't free the directory resource!!! - ChipA.
  2205. * We can't call SplFindResource here, because idIcon
  2206. * is internal to us and GetDriverResourceId()
  2207. * doesn't know how to map it.
  2208. */
  2209. hRes = FINDRESOURCEW(hmod, MAKEINTRESOURCE(idIcon), type);
  2210. }
  2211. /*
  2212. * BOGUS:
  2213. * It would be very cool if we could loop through all the
  2214. * items in the directory and free 'em too. Free the ones
  2215. * except for the one we're about to load, that is.
  2216. *
  2217. * Free directory resources TWICE so they get really freed.
  2218. */
  2219. SplFreeResource(hDir, hmod, LR_flags);
  2220. }
  2221. } else {
  2222. /*
  2223. * Failed to load a regular icon\cursor.
  2224. * Try to load an animated icon/cursor with the same name
  2225. */
  2226. hRes = SplFindResource(hmod, lpName,
  2227. PTR_TO_ID(type) == PTR_TO_ID(RT_CURSOR) ? RT_ANICURSOR : RT_ANIICON);
  2228. }
  2229. break;
  2230. case PTR_TO_ID(RT_BITMAP):
  2231. hRes = SplFindResource(hmod, lpName, RT_BITMAP);
  2232. break;
  2233. default:
  2234. RIPMSG0(RIP_WARNING, "LoadDIB: Invalid resource type");
  2235. break;
  2236. }
  2237. if (hRes)
  2238. hRes = LOADRESOURCE(hmod, hRes);
  2239. return hRes;
  2240. }
  2241. /***************************************************************************\
  2242. * LoadIcoCur (Worker)
  2243. *
  2244. *
  2245. \***************************************************************************/
  2246. HICON LoadIcoCur(
  2247. HINSTANCE hmod,
  2248. LPCWSTR pszResName,
  2249. LPWSTR type,
  2250. DWORD cxDesired,
  2251. DWORD cyDesired,
  2252. UINT LR_flags)
  2253. {
  2254. HICON hico;
  2255. LPWSTR pszModName;
  2256. WCHAR achModName[MAX_PATH];
  2257. ConnectIfNecessary(0);
  2258. /*
  2259. * Setup module name and handles for lookup.
  2260. */
  2261. if (hmod == NULL) {
  2262. hmod = hmodUser;
  2263. pszModName = szUSER32;
  2264. } else {
  2265. WowGetModuleFileName(hmod,
  2266. achModName,
  2267. sizeof(achModName) / sizeof(WCHAR));
  2268. pszModName = achModName;
  2269. }
  2270. if (LR_flags & LR_CREATEDIBSECTION)
  2271. LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB;
  2272. /*
  2273. * Setup defaults.
  2274. */
  2275. if ((hmod == hmodUser) && !IS_PTR(pszResName)) {
  2276. int imapMax;
  2277. LPMAPRES lpMapRes;
  2278. /*
  2279. * Map some old OEM IDs for people.
  2280. */
  2281. if (type == RT_ICON) {
  2282. static MAPRES MapOemOic[] = {
  2283. {OCR_ICOCUR, OIC_WINLOGO, MR_FAILFOR40}
  2284. };
  2285. lpMapRes = MapOemOic;
  2286. imapMax = 1;
  2287. } else {
  2288. static MAPRES MapOemOcr[] = {
  2289. {OCR_ICON, OCR_ICON, MR_FAILFOR40},
  2290. {OCR_SIZE, OCR_SIZE, MR_FAILFOR40}
  2291. };
  2292. lpMapRes = MapOemOcr;
  2293. imapMax = 2;
  2294. }
  2295. while (--imapMax >= 0) {
  2296. if (lpMapRes->idDisp == PTR_TO_ID(pszResName)) {
  2297. if ((lpMapRes->bFlags & MR_FAILFOR40) &&
  2298. GETAPPVER() >= VER40) {
  2299. RIPMSG1(RIP_WARNING,
  2300. "LoadIcoCur: Old ID 0x%x not allowed for 4.0 apps",
  2301. PTR_TO_ID(pszResName));
  2302. return NULL;
  2303. }
  2304. pszResName = MAKEINTRESOURCE(lpMapRes->idUser);
  2305. break;
  2306. }
  2307. ++lpMapRes;
  2308. }
  2309. }
  2310. /*
  2311. * Determine size of requested object.
  2312. */
  2313. cxDesired = GetIcoCurWidth(cxDesired , (type == RT_ICON), LR_flags, 0);
  2314. cyDesired = GetIcoCurHeight(cyDesired, (type == RT_ICON), LR_flags, 0);
  2315. /*
  2316. * See if this is a cached icon/cursor, and grab it if we have one
  2317. * already.
  2318. */
  2319. if (LR_flags & LR_SHARED) {
  2320. CURSORFIND cfSearch;
  2321. /*
  2322. * Note that win95 fails to load any USER resources unless
  2323. * LR_SHARED is specified - so we do too. Also, win95 will
  2324. * ignore your cx, cy and LR_flag parameters and just give
  2325. * you whats in the cache so we do too.
  2326. * A shame but thats life...
  2327. *
  2328. * Setup search criteria. Since this is a load, we will have
  2329. * no source-cursor to lookup. Find something respectable.
  2330. */
  2331. cfSearch.hcur = (HCURSOR)NULL;
  2332. cfSearch.rt = PtrToUlong(type);
  2333. if (hmod == hmodUser) {
  2334. cfSearch.cx = 0;
  2335. cfSearch.cy = 0;
  2336. cfSearch.bpp = 0;
  2337. } else {
  2338. cfSearch.cx = cxDesired;
  2339. cfSearch.cy = cyDesired;
  2340. /*
  2341. * On NT we have a more strict cache-lookup. By passing in (zero), we
  2342. * will tell the cache-lookup to ignore the bpp. This fixes a problem
  2343. * in Crayola Art Studio where the coloring-book cursor was being created
  2344. * as an invisible cursor. This lookup is compatible with Win95.
  2345. */
  2346. #if 0
  2347. cfSearch.bpp = GetIcoCurBpp(LR_flags);
  2348. #else
  2349. cfSearch.bpp = 0;
  2350. #endif
  2351. }
  2352. hico = FindExistingCursorIcon(pszModName, pszResName, &cfSearch);
  2353. if (hico != NULL)
  2354. goto IcoCurFound;
  2355. }
  2356. #ifdef LATER // SanfordS
  2357. /*
  2358. * We need to handle the case where a configurable icon has been
  2359. * loaded from some arbitrary module or file and someone now wants
  2360. * to load the same thing in a different size or color content.
  2361. *
  2362. * A cheezier alternative is to just call CopyImage on what we
  2363. * found.
  2364. */
  2365. if (hmod == hmodUser) {
  2366. hico = FindExistingCursorIcon(NULL,
  2367. szUSER,
  2368. type,
  2369. pszResName,
  2370. 0,
  2371. 0,
  2372. 0);
  2373. if (hico != NULL) {
  2374. /*
  2375. * Find out where the original came from and load it.
  2376. * This may require some redesign to remember the
  2377. * filename that LR_LOADFROMFILE images came from.
  2378. */
  2379. _GetIconInfo(....);
  2380. return LoadIcoCur(....);
  2381. }
  2382. }
  2383. #endif
  2384. hico = (HICON)ObjectFromDIBResource(hmod,
  2385. pszResName,
  2386. type,
  2387. cxDesired,
  2388. cyDesired,
  2389. LR_flags);
  2390. IcoCurFound:
  2391. return hico;
  2392. }
  2393. /***************************************************************************\
  2394. * ObjectFromDIBResource
  2395. *
  2396. *
  2397. \***************************************************************************/
  2398. HANDLE ObjectFromDIBResource(
  2399. HINSTANCE hmod,
  2400. LPCWSTR lpName,
  2401. LPWSTR type,
  2402. DWORD cxDesired,
  2403. DWORD cyDesired,
  2404. UINT LR_flags)
  2405. {
  2406. HANDLE hObj = NULL;
  2407. if (LR_flags & LR_LOADFROMFILE) {
  2408. hObj = RtlLoadObjectFromDIBFile(lpName,
  2409. type,
  2410. cxDesired,
  2411. cyDesired,
  2412. LR_flags);
  2413. } else {
  2414. HANDLE hdib;
  2415. hdib = LoadDIB(hmod, lpName, type, cxDesired, cyDesired, LR_flags);
  2416. if (hdib != NULL) {
  2417. LPBITMAPINFOHEADER lpbih;
  2418. /*
  2419. * We cast the resource-bits to a BITMAPINFOHEADER. If the
  2420. * resource is a CURSOR type, then there are actually two
  2421. * WORDs preceeding the BITMAPINFOHDEADER indicating the
  2422. * hot-spot. Be careful in assuming you have a real
  2423. * dib in this case.
  2424. */
  2425. if(lpbih = (LPBITMAPINFOHEADER)LOCKRESOURCE(hdib, hmod)) {
  2426. switch (PTR_TO_ID(type)) {
  2427. case PTR_TO_ID(RT_BITMAP):
  2428. /*
  2429. * Create a physical bitmap from the DIB.
  2430. */
  2431. hObj = ConvertDIBBitmap(lpbih,
  2432. cxDesired,
  2433. cyDesired,
  2434. LR_flags,
  2435. NULL,
  2436. NULL);
  2437. break;
  2438. case PTR_TO_ID(RT_ICON):
  2439. case PTR_TO_ID(RT_CURSOR):
  2440. case PTR_TO_ID(RT_ANICURSOR):
  2441. case PTR_TO_ID(RT_ANIICON):
  2442. /*
  2443. * Animated icon\cursors resources use the RIFF format
  2444. */
  2445. if (ISRIFFFORMAT(lpbih)) {
  2446. hObj = LoadCursorIconFromResource ((PBYTE)lpbih, lpName, cxDesired, cyDesired, LR_flags);
  2447. } else {
  2448. /*
  2449. * Create the object from the DIB.
  2450. */
  2451. hObj = ConvertDIBIcon(lpbih,
  2452. hmod,
  2453. lpName,
  2454. (type == RT_ICON),
  2455. cxDesired,
  2456. cyDesired,
  2457. LR_flags);
  2458. }
  2459. break;
  2460. }
  2461. UNLOCKRESOURCE(hdib, hmod);
  2462. }
  2463. /*
  2464. * DO THIS TWICE! The resource compiler always makes icon images
  2465. * (RT_ICON) in a group icon discardable, whether the group dude
  2466. * is or not! So the first free won't really free the thing;
  2467. * it'll just set the ref count to 0 and let the discard logic
  2468. * go on its merry way.
  2469. *
  2470. * We take care of shared guys, so we don't need this dib no more.
  2471. * Don't need this DIB no more no more, no more no more no more
  2472. * don't need this DIB no more.
  2473. */
  2474. SplFreeResource(hdib, hmod, LR_flags);
  2475. }
  2476. }
  2477. return hObj;
  2478. }
  2479. /***************************************************************************\
  2480. * BitmapFromDIB
  2481. *
  2482. * Creates a bitmap-handle from a DIB-Spec. This function supports the
  2483. * LR_CREATEDIBSECTION flag, sets proper color depth, and stretches the
  2484. * DIBs as requested.
  2485. *
  2486. \***************************************************************************/
  2487. HBITMAP BitmapFromDIB(
  2488. int cxNew,
  2489. int cyNew,
  2490. WORD bPlanesNew,
  2491. WORD bBitsPixelNew,
  2492. UINT LR_flags,
  2493. int cxOld,
  2494. int cyOld,
  2495. LPSTR lpBits,
  2496. LPBITMAPINFO lpbi,
  2497. HPALETTE hpal)
  2498. {
  2499. HBITMAP hbmpNew = NULL;
  2500. BOOL fStretch;
  2501. BOOL f1Bpp = FALSE;
  2502. RtlEnterCriticalSection(&gcsHdc);
  2503. if (cxNew == 0)
  2504. cxNew = cxOld;
  2505. if (cyNew == 0)
  2506. cyNew = cyOld;
  2507. fStretch = ((cxNew != cxOld) || (cyNew != cyOld));
  2508. /*
  2509. * If LR_flags indicate DIB-Section, then return that as the
  2510. * bitmap handle.
  2511. */
  2512. if (LR_flags & (LR_CREATEDIBSECTION | LR_CREATEREALDIB)) {
  2513. int cxTemp;
  2514. int cyTemp;
  2515. BOOL fOldFormat;
  2516. LPVOID dwDummy;
  2517. DWORD dwTemp;
  2518. #define lpbch ((LPBITMAPCOREHEADER)lpbi)
  2519. fOldFormat = ((WORD)lpbi->bmiHeader.biSize == sizeof(BITMAPCOREHEADER));
  2520. if (fOldFormat) {
  2521. cxTemp = lpbch->bcWidth;
  2522. cyTemp = lpbch->bcHeight;
  2523. lpbch->bcWidth = (WORD)cxNew;
  2524. lpbch->bcHeight = (WORD)cyNew;
  2525. } else {
  2526. cxTemp = lpbi->bmiHeader.biWidth;
  2527. cyTemp = lpbi->bmiHeader.biHeight;
  2528. dwTemp = lpbi->bmiHeader.biCompression;
  2529. lpbi->bmiHeader.biWidth = cxNew;
  2530. lpbi->bmiHeader.biHeight = cyNew;
  2531. if (dwTemp != BI_BITFIELDS)
  2532. lpbi->bmiHeader.biCompression = BI_RGB;
  2533. }
  2534. if (LR_flags & LR_CREATEREALDIB) {
  2535. hbmpNew = CreateDIBitmap(ghdcBits2,
  2536. (LPBITMAPINFOHEADER)lpbi,
  2537. CBM_CREATEDIB,
  2538. NULL,
  2539. lpbi,
  2540. DIB_RGB_COLORS);
  2541. } else {
  2542. hbmpNew = CreateDIBSection(ghdcBits2,
  2543. lpbi,
  2544. DIB_RGB_COLORS,
  2545. &dwDummy,
  2546. 0,
  2547. 0);
  2548. }
  2549. if (fOldFormat) {
  2550. lpbch->bcWidth = (WORD)cxTemp;
  2551. lpbch->bcHeight = (WORD)cyTemp;
  2552. } else {
  2553. lpbi->bmiHeader.biWidth = cxTemp;
  2554. lpbi->bmiHeader.biHeight = cyTemp;
  2555. lpbi->bmiHeader.biCompression = dwTemp;
  2556. }
  2557. #undef lpbch
  2558. }
  2559. if (hbmpNew == NULL) {
  2560. hbmpNew = CreateScreenBitmap(cxNew,
  2561. cyNew,
  2562. bPlanesNew,
  2563. bBitsPixelNew,
  2564. NULL,
  2565. &f1Bpp);
  2566. }
  2567. if (hbmpNew) {
  2568. int nStretchMode;
  2569. DWORD rgbBk;
  2570. DWORD rgbText;
  2571. HBITMAP hbmpT;
  2572. BOOL fFail;
  2573. /*
  2574. * We need to select in appropriate bitmap immediately! That way,
  2575. * if we need to handle palette realization, the color matching
  2576. * will work properly.
  2577. */
  2578. hbmpT = SelectBitmap(ghdcBits2, hbmpNew);
  2579. /*
  2580. * Setup for stretching
  2581. */
  2582. if (fStretch) {
  2583. nStretchMode = SetBestStretchMode(ghdcBits2,
  2584. bPlanesNew,
  2585. bBitsPixelNew);
  2586. }
  2587. rgbBk = SetBkColor(ghdcBits2, RESCLR_WHITE);
  2588. rgbText = SetTextColor(ghdcBits2, RESCLR_BLACK);
  2589. /*
  2590. * Realize the palette.
  2591. */
  2592. if (hpal) {
  2593. #if DBG
  2594. UserAssert(TEST_PUSIF(PUSIF_PALETTEDISPLAY));
  2595. #endif // DBG
  2596. hpal = SelectPalette(ghdcBits2, hpal, FALSE);
  2597. RealizePalette(ghdcBits2);
  2598. }
  2599. if (fStretch) {
  2600. fFail = SmartStretchDIBits(ghdcBits2,
  2601. 0,
  2602. 0,
  2603. cxNew,
  2604. cyNew,
  2605. 0,
  2606. 0,
  2607. cxOld,
  2608. cyOld,
  2609. lpBits,
  2610. lpbi,
  2611. DIB_RGB_COLORS,
  2612. SRCCOPY) <= 0;
  2613. } else {
  2614. fFail = SetDIBits(ghdcBits2,
  2615. hbmpNew,
  2616. 0,
  2617. cyNew,
  2618. lpBits,
  2619. lpbi,
  2620. DIB_RGB_COLORS) <= 0;
  2621. }
  2622. /*
  2623. * Unrealize the palette
  2624. */
  2625. if (hpal) {
  2626. SelectPalette(ghdcBits2, hpal, TRUE);
  2627. RealizePalette(ghdcBits2);
  2628. }
  2629. /*
  2630. * Cleanup after stretching
  2631. */
  2632. SetTextColor(ghdcBits2, rgbText);
  2633. SetBkColor(ghdcBits2, rgbBk);
  2634. if (fStretch)
  2635. SetStretchBltMode(ghdcBits2, nStretchMode);
  2636. SelectBitmap(ghdcBits2, hbmpT);
  2637. /*
  2638. * If the SetDIBits() of StretchDIBits() failed, it is probably because
  2639. * GDI or the driver did not like the DIB format. This may happen if
  2640. * the file is truncated and we are using a memory mapped file to read
  2641. * the DIB in. In this case, an exception gets thrown in GDI, that it
  2642. * traps and will return failure from the GDI call.
  2643. */
  2644. if (fFail) {
  2645. DeleteObject(hbmpNew);
  2646. hbmpNew = NULL;
  2647. }
  2648. }
  2649. /*
  2650. * If the bitmap was created as a 1bpp, we need to convert to a
  2651. * true mono-bitmap. GDI performs different color-matching depending
  2652. * upon this case.
  2653. */
  2654. if (f1Bpp && hbmpNew)
  2655. hbmpNew = Convert1BppToMonoBitmap(ghdcBits2, hbmpNew);
  2656. RtlLeaveCriticalSection(&gcsHdc);
  2657. return hbmpNew;
  2658. }
  2659. /***************************************************************************\
  2660. * HowManyColors
  2661. *
  2662. * Aug-01-2000 DwayneN - Fixed high color support
  2663. \***************************************************************************/
  2664. DWORD HowManyColors(
  2665. IN UPBITMAPINFOHEADER upbih,
  2666. IN BOOL fOldFormat,
  2667. OUT OPTIONAL LPBYTE *ppColorTable)
  2668. {
  2669. #define upbch ((UPBITMAPCOREHEADER)upbih)
  2670. if (fOldFormat) {
  2671. if (ppColorTable != NULL) {
  2672. *ppColorTable = (LPBYTE)(upbch + 1);
  2673. }
  2674. if (upbch->bcBitCount <= 8)
  2675. return (1 << upbch->bcBitCount);
  2676. } else {
  2677. if (ppColorTable != NULL) {
  2678. *ppColorTable = (LPBYTE)(upbih + 1);
  2679. }
  2680. if (upbih->biClrUsed) {
  2681. /*
  2682. * If the bitmap header explicitly provides the number of colors
  2683. * in the color table, use it.
  2684. */
  2685. return (DWORD)upbih->biClrUsed;
  2686. } else if (upbih->biBitCount <= 8) {
  2687. /*
  2688. * If the bitmap header describes a pallete-bassed bitmap
  2689. * (8bpp or less) then the color table must be big enough
  2690. * to hold all palette indecies.
  2691. */
  2692. return (1 << upbih->biBitCount);
  2693. } else {
  2694. /*
  2695. * Finally, if the bitmap header describes a highcolor+ bitmap
  2696. * (anything over 8bpp, but typically 16bpp, 24bpp, or 32bpp)
  2697. * there isn't a need for a color table. However, 16bpp and
  2698. * 32bpp bitmaps are special cases since it is not obvious how
  2699. * they should be split into triplets (Red, Green, and Blue). For
  2700. * instance, 16bpp bitmaps can have 6 red bits, 5 green bits, and
  2701. * 5 blue bits. Or some other combination. To specify this, the
  2702. * 16bpp and 32bpp bitmaps provide BI_BITFIELDS in the
  2703. * biCompression field. This indicates that the color table will
  2704. * have 3 DWORDS that describe the masks for the red, green, and
  2705. * blue components of entry in the bitmap. If this isn't
  2706. * specified, then GDI assumes "555" for 16bpp and "XBGR" for
  2707. * 32bpp. 24bpp bitmaps are always "XBGR" and consume a 32-bit
  2708. * entry in the form of an RGBQUAD.
  2709. */
  2710. if (upbih->biCompression == BI_BITFIELDS) {
  2711. if ((upbih->biBitCount != 16) && (upbih->biBitCount != 32)) {
  2712. RIPMSG1(RIP_WARNING, "HowManyColors: biCompression==BI_BITFIELDS on a %dbpp bitmap!", upbih->biBitCount);
  2713. }
  2714. return 3;
  2715. }
  2716. }
  2717. }
  2718. /*
  2719. * Evidently, there is no color table.
  2720. */
  2721. return 0;
  2722. #undef upbch
  2723. }
  2724. /***************************************************************************\
  2725. * ChangeDibColors
  2726. *
  2727. * Given a DIB, processes LR_MONOCHROME, LR_LOADTRANSPARENT and
  2728. * LR_LOADMAP3DCOLORS flags on the given header and colortable.
  2729. *
  2730. *
  2731. \***************************************************************************/
  2732. VOID ChangeDibColors(
  2733. IN LPBITMAPINFOHEADER lpbih,
  2734. IN UINT LR_flags)
  2735. {
  2736. LPDWORD lpColorTable;
  2737. DWORD rgb;
  2738. UINT iColor;
  2739. UINT cColors;
  2740. cColors = HowManyColors(lpbih, FALSE, &(LPBYTE)lpColorTable);
  2741. /*
  2742. * NT Bug 366661: Don't check the color count here b/c we will do different
  2743. * things depending on what type of change we are performing. For example,
  2744. * when loading hi-color/true-color icons, we always need to do the
  2745. * monochrome conversion in order to properly get an icon-mask.
  2746. */
  2747. /*
  2748. * LR_MONOCHROME is the only option that handles PM dibs.
  2749. */
  2750. if (LR_flags & LR_MONOCHROME) {
  2751. /*
  2752. * LR_MONOCHROME is the only option that handles PM dibs.
  2753. *
  2754. * DO THIS NO MATTER WHETHER WE HAVE A COLOR TABLE! We need
  2755. * to do this for mono conversion and for > 8 BPP
  2756. * icons/cursors. In CopyDibHdr, we already made a copy of
  2757. * the header big enough to hold 2 colors even on high-color+
  2758. * bpp images.
  2759. */
  2760. lpbih->biBitCount = lpbih->biPlanes = 1;
  2761. lpbih->biCompression = 0;
  2762. lpColorTable[0] = RESCLR_BLACK;
  2763. lpColorTable[1] = RESCLR_WHITE;
  2764. } else if (LR_flags & LR_LOADTRANSPARENT) {
  2765. LPBYTE pb;
  2766. /*
  2767. * No color table! Do nothing.
  2768. */
  2769. if (cColors == 0) {
  2770. RIPMSG0(RIP_WARNING, "ChangeDibColors: DIB doesn't have a color table");
  2771. return;
  2772. }
  2773. pb = (LPBYTE)(lpColorTable + cColors);
  2774. /*
  2775. * Change the first pixel's color table entry to RGB_WINDOW
  2776. * Gosh, I love small-endian
  2777. */
  2778. if (lpbih->biCompression == 0)
  2779. iColor = (UINT)pb[0];
  2780. else
  2781. /*
  2782. * RLE bitmap, will start with cnt,clr or 0,cnt,clr
  2783. */
  2784. iColor = (UINT)(pb[0] == 0 ? pb[2] : pb[1]);
  2785. switch (cColors) {
  2786. case BPP01_MAXCOLORS:
  2787. iColor &= 0x01;
  2788. break;
  2789. case BPP04_MAXCOLORS:
  2790. iColor &= 0x0F;
  2791. break;
  2792. case BPP08_MAXCOLORS:
  2793. iColor &= 0xFF;
  2794. break;
  2795. }
  2796. rgb = (LR_flags & LR_LOADMAP3DCOLORS ? SYSRGB(3DFACE) : SYSRGB(WINDOW));
  2797. lpColorTable[iColor] = RGBX(rgb);
  2798. } else if (LR_flags & LR_LOADMAP3DCOLORS) {
  2799. /*
  2800. * Fix up the color table, mapping shades of grey to the current
  2801. * 3D colors.
  2802. */
  2803. for (iColor = 0; iColor < cColors; iColor++) {
  2804. switch (*lpColorTable & 0x00FFFFFF) {
  2805. case RGBX(RGB(223, 223, 223)):
  2806. rgb = SYSRGB(3DLIGHT);
  2807. goto ChangeColor;
  2808. case RGBX(RGB(192, 192, 192)):
  2809. rgb = SYSRGB(3DFACE);
  2810. goto ChangeColor;
  2811. case RGBX(RGB(128, 128, 128)):
  2812. rgb = SYSRGB(3DSHADOW);
  2813. /*
  2814. * NOTE: byte-order is different in DIBs than in RGBs
  2815. */
  2816. ChangeColor:
  2817. *lpColorTable = RGBX(rgb);
  2818. break;
  2819. }
  2820. lpColorTable++;
  2821. }
  2822. }
  2823. }
  2824. /***************************************************************************\
  2825. * ConvertDIBIcon
  2826. *
  2827. * Called when a cursor/icon in DIB format is loaded. This converts the
  2828. * cursor/icon into the old format and returns the resource handle. IE,
  2829. * grabs the DIB bits and transforms them into physical bitmap bits.
  2830. *
  2831. *
  2832. * DIB Formats for icons/cursors 101
  2833. *
  2834. * Old Win 3.0 format icons/cursors start with an OLDICON/OLDCURSOR header
  2835. * followed by a double high monochrome DIB. The height refered to in the
  2836. * header is the icon/cursor height, not the DIB height which is twice as
  2837. * high. The XOR mask is in the first-half of the DIB bits.
  2838. *
  2839. * Old PM format icons/cursors start with a BITMAPCOREHEADER and
  2840. * are identical to the current win 3.1/NT format thereafter.
  2841. *
  2842. * Current NT/Chicago/Win 3.1 format icons/cursors start with
  2843. * a BITAMPINFOHEADER. The height of this header refers to the height
  2844. * of the first bitmap which may either be color or truely monochrome.
  2845. * If its color, it is followed by the monochrome AND mask bits imediately
  2846. * after the color bits. If it is truely monochrome, the AND and XOR
  2847. * masks are totally contained in the first DIB bits and no more bits
  2848. * follow.
  2849. *
  2850. * 5-Oct-1994 SanfordS Recreated
  2851. \***************************************************************************/
  2852. HICON ConvertDIBIcon(
  2853. LPBITMAPINFOHEADER lpbih,
  2854. HINSTANCE hmod,
  2855. LPCWSTR lpName,
  2856. BOOL fIcon,
  2857. DWORD cxNew,
  2858. DWORD cyNew,
  2859. UINT LR_flags)
  2860. {
  2861. LPBITMAPINFOHEADER lpbihNew = NULL;
  2862. LPSTR lpBitsNextMask = NULL;
  2863. HICON hicoNew = NULL;
  2864. BOOL fOldFormat = FALSE;
  2865. CURSORDATA cur;
  2866. WCHAR achModName[MAX_PATH];
  2867. /*
  2868. * Because Icons/Cursors always get public bitmaps, we cannot use
  2869. * LR_CREATEDIBSECTION on them.
  2870. */
  2871. if (LR_flags & LR_CREATEDIBSECTION) {
  2872. LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB;
  2873. }
  2874. RtlZeroMemory(&cur, sizeof(cur));
  2875. if (!fIcon) {
  2876. /*
  2877. * Cursors have an extra two words preceeding the BITMAPINFOHEADER
  2878. * indicating the hot-spot. After doing the increments, the
  2879. * pointer should be at the dib-header.
  2880. */
  2881. cur.xHotspot = (short)(int)*(((LPWORD)lpbih)++);
  2882. cur.yHotspot = (short)(int)*(((LPWORD)lpbih)++);
  2883. }
  2884. /*
  2885. * If the color bitmap is a single plane, 32bpp image, it might
  2886. * contain an alpha channel, so we have to preserve it as a DIB.
  2887. */
  2888. if (lpbih->biPlanes == 1 && lpbih->biBitCount == 32) {
  2889. LR_flags |= LR_CREATEREALDIB;
  2890. }
  2891. /*
  2892. * Get the XOR/Color mask.
  2893. * The XOR bits are first in the DIB because the header info
  2894. * pertains to them.
  2895. * The AND mask is always monochrome.
  2896. */
  2897. lpBitsNextMask = NULL; // not passing lpBits in.
  2898. cur.hbmColor = ConvertDIBBitmap(lpbih,
  2899. cxNew,
  2900. cyNew,
  2901. LR_flags,
  2902. &lpbihNew,
  2903. &lpBitsNextMask);
  2904. if (cur.hbmColor == NULL)
  2905. return NULL;
  2906. if (hmod == NULL) {
  2907. cur.lpModName = NULL;
  2908. } else {
  2909. cur.CURSORF_flags = CURSORF_FROMRESOURCE;
  2910. if (hmod == hmodUser) {
  2911. cur.lpModName = szUSER32;
  2912. } else {
  2913. WowGetModuleFileName(hmod,
  2914. achModName,
  2915. sizeof(achModName) / sizeof(WCHAR));
  2916. cur.lpModName = achModName;
  2917. }
  2918. }
  2919. cur.rt = (fIcon ? PTR_TO_ID(RT_ICON) : PTR_TO_ID(RT_CURSOR));
  2920. cur.lpName = (LPWSTR)lpName;
  2921. cur.bpp = lpbihNew->biBitCount * lpbihNew->biPlanes;
  2922. if (cxNew == 0)
  2923. cxNew = lpbihNew->biWidth;
  2924. if (cyNew == 0)
  2925. cyNew = lpbihNew->biHeight / 2;
  2926. if (!fIcon) {
  2927. cur.xHotspot = MultDiv(cur.xHotspot,
  2928. cxNew,
  2929. lpbihNew->biWidth);
  2930. cur.yHotspot = MultDiv(cur.yHotspot,
  2931. cyNew,
  2932. lpbihNew->biHeight / 2);
  2933. } else {
  2934. /*
  2935. * For an icon the hot spot is the center of the icon
  2936. */
  2937. cur.xHotspot = (INT)(cxNew) / 2;
  2938. cur.yHotspot = (INT)(cyNew) / 2;
  2939. }
  2940. /*
  2941. * Setup header for monochrome DIB. Note that we use the COPY.
  2942. */
  2943. ChangeDibColors(lpbihNew, LR_MONOCHROME);
  2944. if (lpBitsNextMask != NULL) {
  2945. cur.hbmMask = BitmapFromDIB(cxNew,
  2946. cyNew * 2,
  2947. 1,
  2948. 1,
  2949. 0,
  2950. lpbihNew->biWidth,
  2951. lpbihNew->biHeight,
  2952. lpBitsNextMask,
  2953. (LPBITMAPINFO)lpbihNew,
  2954. NULL);
  2955. if (cur.hbmMask == NULL) {
  2956. DeleteObject(KHBITMAP_TO_HBITMAP(cur.hbmColor));
  2957. UserLocalFree(lpbihNew);
  2958. return NULL;
  2959. }
  2960. } else {
  2961. cur.hbmMask = cur.hbmColor;
  2962. cur.hbmColor = NULL;
  2963. }
  2964. cur.cx = cxNew;
  2965. cur.cy = cyNew * 2;
  2966. /*
  2967. * Free our dib header copy allocated by ConvertDIBBitmap
  2968. */
  2969. UserLocalFree(lpbihNew);
  2970. if (LR_flags & LR_SHARED)
  2971. cur.CURSORF_flags |= CURSORF_LRSHARED;
  2972. if (LR_flags & LR_GLOBAL)
  2973. cur.CURSORF_flags |= CURSORF_GLOBAL;
  2974. if (LR_flags & LR_ACONFRAME)
  2975. cur.CURSORF_flags |= CURSORF_ACONFRAME;
  2976. return CreateIcoCur(&cur);
  2977. }
  2978. /***************************************************************************\
  2979. * TrulyMonochrome
  2980. *
  2981. * Checks to see if a DIB colro table is truly monochrome. ie: the color
  2982. * table has black & white entries only.
  2983. *
  2984. \***************************************************************************/
  2985. BOOL TrulyMonochrome(
  2986. LPVOID lpColorTable,
  2987. BOOL fOldFormat)
  2988. {
  2989. #define lpRGB ((UNALIGNED LONG *)lpColorTable)
  2990. #define lpRGBw ((UNALIGNED WORD *)lpColorTable)
  2991. if (fOldFormat) {
  2992. /*
  2993. * Honey - its triplets.
  2994. */
  2995. if (lpRGBw[0] == 0x0000)
  2996. return (lpRGBw[1] == 0xFF00) && (lpRGBw[2] == 0xFFFF);
  2997. else if (lpRGBw[0] == 0xFFFF)
  2998. return (lpRGBw[1] == 0x00FF) && (lpRGBw[2] == 0x0000);
  2999. } else {
  3000. /*
  3001. * Honey - its quadruplets!
  3002. */
  3003. if (lpRGB[0] == RESCLR_BLACK)
  3004. return (lpRGB[1] == RESCLR_WHITE);
  3005. else if (lpRGB[0] == RESCLR_WHITE)
  3006. return (lpRGB[1] == RESCLR_BLACK);
  3007. }
  3008. #undef lpRGB
  3009. #undef lpRGBw
  3010. return FALSE;
  3011. }
  3012. /***************************************************************************\
  3013. * CopyDibHdr
  3014. *
  3015. * Copies and converts a DIB resource header
  3016. *
  3017. * Handles conversion of OLDICON, OLDCURSOR and BITMAPCOREHEADER
  3018. * structures to BITMAPINFOHEADER headers.
  3019. *
  3020. * Note: fSingleHeightMasks is set for OLDICON and OLDCURSOR formats.
  3021. * This identifies that a monochrome AND/Color mask
  3022. * is NOT double height as it is in the newer formats.
  3023. *
  3024. * NOTE: On the off chance that LR_LOADTRANSPARENT is used, we want to
  3025. * copy a DWORD of the bits. Since DIB bits are DWORD aligned, we know
  3026. * at least a DWORD is there, even if the thing is a 1x1 mono bmp.
  3027. *
  3028. * The returned buffer is allocated in this function and needs to be
  3029. * freed by the caller.
  3030. *
  3031. * 22-Oct-1995 SanfordS Revised
  3032. \***************************************************************************/
  3033. LPBITMAPINFOHEADER CopyDibHdr(
  3034. IN UPBITMAPINFOHEADER upbih,
  3035. OUT LPSTR *lplpBits,
  3036. OUT LPBOOL lpfMono)
  3037. {
  3038. #define upbch ((UPBITMAPCOREHEADER)upbih)
  3039. DWORD cColors;
  3040. DWORD cMinColors;
  3041. DWORD i;
  3042. LPBITMAPINFOHEADER lpbihNew;
  3043. DWORD cbAlloc;
  3044. LPBYTE lpColorTable;
  3045. struct {
  3046. BITMAPINFOHEADER bih;
  3047. DWORD rgb[256];
  3048. DWORD dwBuffer;
  3049. } Fake;
  3050. switch (upbih->biSize) {
  3051. case sizeof(BITMAPINFOHEADER):
  3052. /*
  3053. * Cool. No conversion needed.
  3054. */
  3055. cColors = HowManyColors(upbih, FALSE, &lpColorTable);
  3056. *lplpBits = (LPSTR)(((LPDWORD)lpColorTable) + cColors);
  3057. break;
  3058. case sizeof(BITMAPCOREHEADER):
  3059. /*
  3060. * Convert the BITMAPCOREHEADER to a BITMAPINFOHEADER
  3061. */
  3062. Fake.bih.biSize = sizeof(BITMAPINFOHEADER);
  3063. Fake.bih.biWidth = upbch->bcWidth;
  3064. Fake.bih.biHeight = upbch->bcHeight;
  3065. Fake.bih.biPlanes = upbch->bcPlanes;
  3066. Fake.bih.biBitCount = upbch->bcBitCount;
  3067. Fake.bih.biCompression =
  3068. Fake.bih.biXPelsPerMeter =
  3069. Fake.bih.biYPelsPerMeter =
  3070. Fake.bih.biClrImportant = 0;
  3071. Fake.bih.biClrUsed = cColors = HowManyColors(upbih, TRUE, &lpColorTable);
  3072. Fake.bih.biSizeImage = BitmapWidth(Fake.bih.biWidth, Fake.bih.biBitCount) * Fake.bih.biHeight;
  3073. /*
  3074. * Copy and convert tripplet color table to rgbQuad color table.
  3075. */
  3076. for (i = 0; i < cColors; i++, lpColorTable += 3) {
  3077. Fake.rgb[i] = lpColorTable[0] +
  3078. (lpColorTable[1] << 8) +
  3079. (lpColorTable[2] << 16);
  3080. }
  3081. Fake.rgb[i] = *(DWORD UNALIGNED *)lpColorTable; // For LR_LOADTRANSPARENT
  3082. upbih = (UPBITMAPINFOHEADER)&Fake;
  3083. *lplpBits = lpColorTable;
  3084. break;
  3085. default:
  3086. #define upOldIcoCur ((UPOLDCURSOR)upbih)
  3087. if (upOldIcoCur->bType == BMR_ICON ||
  3088. upOldIcoCur->bType == BMR_CURSOR) {
  3089. /*
  3090. * Convert OLDICON/OLDCURSOR header to BITMAPINFHEADER
  3091. */
  3092. RIPMSG0(RIP_WARNING, "USER32:Converting a OLD header. - email sanfords if you see this");
  3093. Fake.bih.biSize = sizeof(BITMAPINFOHEADER);
  3094. Fake.bih.biWidth = upOldIcoCur->cx;
  3095. Fake.bih.biHeight = upOldIcoCur->cy * 2;
  3096. Fake.bih.biPlanes =
  3097. Fake.bih.biBitCount = 1;
  3098. Fake.bih.biCompression =
  3099. Fake.bih.biXPelsPerMeter =
  3100. Fake.bih.biYPelsPerMeter =
  3101. Fake.bih.biClrImportant = 0;
  3102. Fake.bih.biClrUsed = cColors = BPP01_MAXCOLORS;
  3103. Fake.bih.biSizeImage = BitmapWidth(upOldIcoCur->cx, 1) * upOldIcoCur->cy;
  3104. Fake.rgb[0] = RESCLR_BLACK;
  3105. Fake.rgb[1] = RESCLR_WHITE;
  3106. upbih = (LPBITMAPINFOHEADER)&Fake;
  3107. *lplpBits = upOldIcoCur->abBitmap;
  3108. Fake.rgb[2] = *((LPDWORD)*lplpBits); // For LR_LOADTRANSPARENT
  3109. } else {
  3110. RIPMSG0(RIP_WARNING, "ConvertDIBBitmap: not a valid format");
  3111. return NULL;
  3112. }
  3113. #undef pOldIcoCur
  3114. break;
  3115. }
  3116. *lpfMono = (cColors == BPP01_MAXCOLORS) &&
  3117. TrulyMonochrome((LPBYTE)upbih + sizeof(BITMAPINFOHEADER), FALSE);
  3118. /*
  3119. * Note: We have to allocate at least 2 color entries so that we have
  3120. * room in the color table to define black and white for monochrome
  3121. * conversions. See ChangeDibColors() and ConvertDIBIcon().
  3122. */
  3123. cMinColors = cColors >= 2 ? cColors : 2;
  3124. /*
  3125. * LR_LOADTRANSPARENT needs to examine the first pixel to determine the
  3126. * transparent color. This routine splits the bitmap header away
  3127. * from the actual bitmap bits. However, the routines that process the
  3128. * LR_LOADTRANSPARENT style expect the first pixel to immediately follow
  3129. * the bitmap header. Above we copied the first pixel of the bitmap
  3130. * bits right after the color table. Now we just need to make room for
  3131. * it in our buffer.
  3132. */
  3133. cMinColors++;
  3134. cbAlloc = sizeof(BITMAPINFOHEADER) + (cMinColors * sizeof(RGBQUAD));
  3135. if (lpbihNew = UserLocalAlloc(0, cbAlloc)) {
  3136. RtlCopyMemory(lpbihNew, upbih, cbAlloc);
  3137. }
  3138. return lpbihNew;
  3139. #undef upbch
  3140. }
  3141. /***************************************************************************\
  3142. * ConvertDIBBitmap
  3143. *
  3144. * This takes a BITMAPCOREHEADER, OLDICON, OLDCURSOR or BITMAPINFOHEADER DIB
  3145. * specification and creates a physical object from it.
  3146. * Handles Color fixups, DIB sections, color depth, and stretching options.
  3147. *
  3148. * Passes back: (if lplpbih is not NULL)
  3149. * lplpbih = copy of given header converted to BITMAPINFOHEADER form.
  3150. * lplpBits = pointer to next mask bits, or NULL if no second mask.
  3151. * Caller must free lplpbih returned.
  3152. *
  3153. * If lplpBits is not NULL and points to a non-NULL value, it supplies
  3154. * the location of the DIB bits allowing the header to be from a different
  3155. * location.
  3156. *
  3157. * 04-Oct-1995 SanfordS Recreated.
  3158. \***************************************************************************/
  3159. HBITMAP ConvertDIBBitmap(
  3160. IN UPBITMAPINFOHEADER upbih,
  3161. IN DWORD cxDesired,
  3162. IN DWORD cyDesired,
  3163. IN UINT LR_flags,
  3164. OUT OPTIONAL LPBITMAPINFOHEADER *lplpbih,
  3165. IN OUT OPTIONAL LPSTR *lplpBits)
  3166. {
  3167. LPBITMAPINFOHEADER lpbihNew;
  3168. BOOL fMono, fMonoGiven;
  3169. BYTE bPlanesDesired;
  3170. BYTE bppDesired;
  3171. LPSTR lpBits;
  3172. HBITMAP hBmpRet;
  3173. /*
  3174. * Make a copy of the DIB-Header. This returns a pointer
  3175. * which was allocated, so it must be freed later.
  3176. * The also converts the header to BITMAPINFOHEADER format.
  3177. */
  3178. if ((lpbihNew = CopyDibHdr(upbih, &lpBits, &fMono)) == NULL) {
  3179. return NULL;
  3180. }
  3181. /*
  3182. * When loading a DIB file, we may need to use a different
  3183. * bits pointer. See RtlRes.c/RtlLoadObjectFromDIBFile.
  3184. */
  3185. if (lplpBits && *lplpBits) {
  3186. lpBits = *lplpBits;
  3187. }
  3188. fMonoGiven = fMono;
  3189. if (!fMono) {
  3190. if (LR_flags & (LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS))
  3191. ChangeDibColors(lpbihNew, LR_flags & ~LR_MONOCHROME);
  3192. if (LR_flags & LR_CREATEREALDIB) {
  3193. bPlanesDesired = (BYTE) lpbihNew->biPlanes;
  3194. bppDesired = (BYTE) lpbihNew->biBitCount;
  3195. } else {
  3196. bPlanesDesired = gpsi->Planes;
  3197. bppDesired = gpsi->BitsPixel;
  3198. }
  3199. fMono = LR_flags & LR_MONOCHROME;
  3200. }
  3201. if (fMono) {
  3202. bPlanesDesired =
  3203. bppDesired = 1;
  3204. }
  3205. /*
  3206. * HACK area
  3207. */
  3208. if (lplpbih != NULL) {
  3209. /*
  3210. * pass back the translated/copied header
  3211. */
  3212. *lplpbih = lpbihNew;
  3213. /*
  3214. * When loading icon/cursors on a system with multiple monitors
  3215. * with different color depths, always convert to VGA color.
  3216. *
  3217. * dwaynen - 1/12/2001
  3218. * Note: This used to also check the SM_SAMEDISPLAYFORMAT metric. If
  3219. * the display formats (on a multi-mon system) were different, it
  3220. * would force the bpp to 4, We have removed this code because we
  3221. * suspect that it isn't really needed.
  3222. * Refer to bug 258022.
  3223. *
  3224. if (!fMono && !SYSMET(SAMEDISPLAYFORMAT)) {
  3225. bPlanesDesired = 1;
  3226. bppDesired = 4;
  3227. }
  3228. */
  3229. /*
  3230. * Return a ponter to the bits following this set of bits
  3231. * if there are any there.
  3232. *
  3233. * Note that the header given with an ICON DIB always reflects
  3234. * twice the height of the icon desired but the COLOR bitmap
  3235. * (if there is one) will only be half that high. We need to
  3236. * fixup cyDesired for monochrome icons so that the mask isnt
  3237. * stretched to half the height its supposed to be. Color
  3238. * bitmaps, however, must have the header corrected to reflect
  3239. * the bits actual height which is half what the header said.
  3240. * The correction must later be backed out so that the returned
  3241. * header reflects the dimensions of the XOR mask that immediately
  3242. * follows the color mask.
  3243. */
  3244. if (fMonoGiven) {
  3245. *lplpBits = NULL;
  3246. if (cyDesired)
  3247. cyDesired <<= 1; // mono icon bitmaps are double high.
  3248. } else {
  3249. UserAssert(!(lpbihNew->biHeight & 1));
  3250. lpbihNew->biHeight >>= 1; // color icon headers are off by 2
  3251. /*
  3252. * Gross calculation! We subtract the XOR part of the mask
  3253. * for this calculation so that we submit a double-high mask.
  3254. * The first half of this is garbage, but for icons its not
  3255. * used. This may be a bug for cursor use of icons.
  3256. */
  3257. *lplpBits = lpBits +
  3258. (BitmapWidth(lpbihNew->biWidth, lpbihNew->biBitCount) -
  3259. BitmapWidth(lpbihNew->biWidth, 1)) *
  3260. lpbihNew->biHeight;
  3261. }
  3262. }
  3263. if (cxDesired == 0)
  3264. cxDesired = lpbihNew->biWidth;
  3265. if (cyDesired == 0)
  3266. cyDesired = lpbihNew->biHeight;
  3267. hBmpRet = BitmapFromDIB(cxDesired,
  3268. cyDesired,
  3269. bPlanesDesired,
  3270. bppDesired,
  3271. LR_flags,
  3272. lpbihNew->biWidth,
  3273. lpbihNew->biHeight,
  3274. lpBits,
  3275. (LPBITMAPINFO)lpbihNew,
  3276. NULL);
  3277. if (lplpbih == NULL || hBmpRet == NULL) {
  3278. UserLocalFree(lpbihNew);
  3279. } else if (!fMonoGiven) {
  3280. lpbihNew->biHeight <<= 1; // restore header for next mask
  3281. }
  3282. return hBmpRet;
  3283. }
  3284. /***************************************************************************\
  3285. * MyAbs
  3286. *
  3287. * Calcules my weighted absolute value of the difference between 2 nums.
  3288. * This of course normalizes values to >= zero. But it can also "punish" the
  3289. * returned value by a factor of two if valueHave < valueWant. This is
  3290. * because you get worse results trying to extrapolate from less info up then
  3291. * interpolating from more info down.
  3292. *
  3293. \***************************************************************************/
  3294. UINT MyAbs(
  3295. int valueHave,
  3296. int valueWant,
  3297. BOOL fPunish)
  3298. {
  3299. int diff = (valueHave - valueWant);
  3300. if (diff < 0)
  3301. diff = (fPunish ? -2 : -1) * diff;
  3302. return (UINT)diff;
  3303. }
  3304. /***************************************************************************\
  3305. * Magnitude
  3306. *
  3307. * Used by the color-delta calculations. The reason is that num colors is
  3308. * always a power of 2. So we use the log 2 of the want vs. have values
  3309. * to avoid having weirdly huge sets.
  3310. *
  3311. \***************************************************************************/
  3312. UINT Magnitude(
  3313. int nValue)
  3314. {
  3315. if (nValue < 4)
  3316. return 1;
  3317. else if (nValue < 8)
  3318. return 2;
  3319. else if (nValue < 16)
  3320. return 3;
  3321. else if (nValue < 256)
  3322. return 4;
  3323. else
  3324. return 8;
  3325. }
  3326. /***************************************************************************\
  3327. * GetResourceBpp
  3328. *
  3329. * Extract the bpp for a icon/cursor resource. Handle low and high-color
  3330. * formats.
  3331. *
  3332. \***************************************************************************/
  3333. UINT GetResourceBpp(LPRESDIR lprd, BOOL fIcon)
  3334. {
  3335. UINT bpp = 0;
  3336. if (fIcon) {
  3337. if (lprd->Icon.ColorCount != 0) {
  3338. bpp = Magnitude(lprd->Icon.ColorCount);
  3339. TAGMSG2(DBGTAG_Icon, "GetResourceBpp: icon color count = %d, bpp = %d", lprd->Icon.ColorCount, bpp);
  3340. } else {
  3341. bpp = lprd->BitCount;
  3342. TAGMSG1(DBGTAG_Icon, "GetResourceBpp: icon bpp = %d", bpp);
  3343. }
  3344. } else {
  3345. /*
  3346. * NTRAID#NTBUG9-360375-2001/04/05-dwaynen
  3347. * This seems really suspicious to me.
  3348. * Forcing bppNew to 1.
  3349. * Cursors provide a hotspot where an icon provides bit-depth
  3350. * information. So we just set the bppNew to 1, since we don't
  3351. * have any better ideas. We just hope that there is only
  3352. * one cursor candidate, otherwise our scoring logic is broken.
  3353. * Also this is broken when we try to load a cursor resource
  3354. * as an icon. We won't match color depth properly!
  3355. */
  3356. bpp = 1;
  3357. TAGMSG1(DBGTAG_Icon, "GetResourceBpp: cursor bpp = %d", bpp);
  3358. }
  3359. /*
  3360. * Nothing has 0 bpp.
  3361. */
  3362. if(bpp == 0) {
  3363. bpp = ICON_DEFAULTDEPTH;
  3364. TAGMSG1(DBGTAG_Icon, "GetResourceBpp: icon color depth unknown! Assuming %d!", bpp);
  3365. }
  3366. return bpp;
  3367. }
  3368. /***************************************************************************\
  3369. * MatchImage
  3370. *
  3371. * This function takes LPINTs for width & height in case of "real size".
  3372. * For this option, we use dimensions of 1st icon in resdir as size to
  3373. * load, instead of system metrics.
  3374. *
  3375. * Returns a number that measures how "far away" the given image is
  3376. * from a desired one. The value is 0 for an exact match. Note that our
  3377. * formula has the following properties:
  3378. * (1) Differences in width/height count much more than differences in
  3379. * color format.
  3380. * (2) Bigger images are better than smaller, since shrinking produces
  3381. * better results than stretching.
  3382. * (3) Color matching is done by the difference in bit depth. No
  3383. * preference is given to having a candidate equally different
  3384. * above and below the target.
  3385. *
  3386. * The formula is the sum of the following terms:
  3387. * abs(bppCandidate - bppTarget)
  3388. * abs(cxCandidate - cxTarget), times 2 if the image is
  3389. * narrower than what we'd like. This is because we will get a
  3390. * better result when consolidating more information into a smaller
  3391. * space, than when extrapolating from less information to more.
  3392. * abs(cxCandidate - cxTarget), times 2 if the image is
  3393. * shorter than what we'd like. This is for the same reason as
  3394. * the width.
  3395. *
  3396. * Let's step through an example. Suppose we want a 4bpp (16 color),
  3397. * 32x32 image. We would choose the various candidates in the following order:
  3398. *
  3399. * Candidate Score Formula
  3400. *
  3401. * 32x32x4bpp = 0 abs(32-32)*1 + abs(32-32)*1 + 2*abs(4-4)*1
  3402. * 32x32x2bpp = 4
  3403. * 32x32x8bpp = 8
  3404. * 32x32x16bpp = 24
  3405. * 48x48x4bpp = 32
  3406. * 48x48x2bpp = 36
  3407. * 48x48x8bpp = 40
  3408. * 32x32x32bpp = 56
  3409. * 48x48x16bpp = 56 abs(48-32)*1 + abs(48-32)*1 + 2*abs(16-4)*1
  3410. * 16x16x4bpp = 64
  3411. * 16x16x2bpp = 68 abs(16-32)*2 + abs(16-32)*2 + 2*abs(2-4)*1
  3412. * 16x16x8bpp = 72
  3413. * 48x48x32bpp = 88 abs(48-32)*1 + abs(48-32)*1 + 2*abs(32-4)*1
  3414. * 16x16x16bpp = 88
  3415. * 16x16x32bpp = 104
  3416. *
  3417. \***************************************************************************/
  3418. UINT MatchImage(
  3419. LPRESDIR lprd,
  3420. LPINT lpcxWant,
  3421. LPINT lpcyWant,
  3422. UINT bppWant,
  3423. BOOL fIcon)
  3424. {
  3425. UINT bppNew;
  3426. int cxNew;
  3427. int cyNew;
  3428. UINT score;
  3429. cxNew = lprd->Icon.Width;
  3430. cyNew = lprd->Icon.Height;
  3431. bppNew = GetResourceBpp(lprd, fIcon);
  3432. if (!fIcon) {
  3433. /*
  3434. * NTRAID#NTBUG9-360375-2001/04/05-dwaynen
  3435. *
  3436. * This seems really suspicious to me.
  3437. * Cutting the height in half.
  3438. * This is because cursors store a 2X height for legacy reasons.
  3439. * Unfortunately, this code path can also be used to load an
  3440. * icon resource AS a cursor. Maybe we should only do this for
  3441. * cursor resources. But how to tell?
  3442. */
  3443. cyNew >>= 1;
  3444. }
  3445. /*
  3446. * 0 really means maximum size (256) or colors (256).
  3447. */
  3448. if (!cxNew) {
  3449. cxNew = ICON_MAXWIDTH;
  3450. TAGMSG1(DBGTAG_Icon, "MatchImage: icon width unknown! Assuming %d!", cxNew);
  3451. }
  3452. if (!*lpcxWant) {
  3453. *lpcxWant = cxNew;
  3454. }
  3455. if (!cyNew) {
  3456. cyNew = ICON_MAXHEIGHT;
  3457. TAGMSG1(DBGTAG_Icon, "MatchImage: icon height unknown! Assuming %d!", cyNew);
  3458. }
  3459. if (!*lpcyWant) {
  3460. *lpcyWant = cyNew;
  3461. }
  3462. /*
  3463. * Here are the rules for our "match" formula:
  3464. * (1) A close size match is much preferable to a color match
  3465. * (2) Bigger icons are better than smaller
  3466. * (3) The smaller the difference in bit depths the better
  3467. */
  3468. score = 2*MyAbs(bppNew, bppWant, FALSE) +
  3469. MyAbs(cxNew, *lpcxWant, TRUE) +
  3470. MyAbs(cyNew, *lpcyWant, TRUE);
  3471. TAGMSG4(DBGTAG_Icon, "MatchImage: Candidate Summary: cx=%d, cy=%d, bpp=%d, score=%d", cxNew, cyNew, bppNew, score);
  3472. return score;
  3473. }
  3474. /***************************************************************************\
  3475. * GetBestImage
  3476. *
  3477. * Among the different forms of images, choose the one that best matches the
  3478. * color format & dimensions of the request.
  3479. *
  3480. * Here are the rules for our "match" formula:
  3481. * (1) A close size match is much preferable to a color match
  3482. * (2) Bigger icons are better than smaller
  3483. * (3) Closer bit depths are better
  3484. *
  3485. * Here are some additional rules:
  3486. * (4) A tie is broken by choosing the one with the largest bpp.
  3487. * (5) A further tie is broken by choosing the first in the resource.
  3488. * (6) If we find an identical match, we return immediately.
  3489. *
  3490. \***************************************************************************/
  3491. UINT GetBestImage(
  3492. LPRESDIR lprd,
  3493. UINT uCount,
  3494. int cxDesired,
  3495. int cyDesired,
  3496. UINT bppDesired,
  3497. BOOL fIcon)
  3498. {
  3499. UINT i;
  3500. UINT iBest = 0;
  3501. UINT score;
  3502. UINT scoreBest = (UINT)-1;
  3503. UINT bppBest;
  3504. UINT bppCandidate;
  3505. TAGMSG0(DBGTAG_Icon, "GetBestImage: Icon dir has %d candidates.");
  3506. TAGMSG4(DBGTAG_Icon, "GetBestImage: Looking for cx=%d, cy=%d, bpp=%d, fIcon=%s", cxDesired, cyDesired, bppDesired, fIcon ? "TRUE" : "FALSE");
  3507. /*
  3508. * If the bpp was not specified, grab the primary monitor's color depth.
  3509. */
  3510. if (bppDesired == 0) {
  3511. bppDesired = (UINT)gpsi->BitCount;
  3512. TAGMSG1(DBGTAG_Icon, "GetBestImage: Using screen bpp=%d", bppDesired);
  3513. }
  3514. /*
  3515. * 10/18/2000 - dwaynen
  3516. *
  3517. * We no longer do the following, because we now pass along the
  3518. * actuall bpp, instead of a color count. The old code (commented out
  3519. * below) used to crop the supported bpp to 8, and to convert the bpp
  3520. * into an actual color count. We used to pass the color count because
  3521. * the resource format (see ICONDIR) stores the color count in a byte,
  3522. * and we would simply compare the desired colors against the available
  3523. * colors. If an icon had 256 colors, it actually just stored a 0 in
  3524. * the ICONDIR::ColorCount field. The problem is obvious, what about
  3525. * icons/cursors with more than 256 colors?
  3526. *
  3527. * Fortunately, the resource format also stores the bits-per-pixel (bpp).
  3528. * So, we now pass along the desired bpp, instead of the desired color
  3529. * count, to do our matching against.
  3530. *
  3531. * Old code and comments below:
  3532. * --------
  3533. *
  3534. * Get desired number of colors in # value, not bits value. Note that
  3535. * we do NOT allow you to have 16- or 32- or 24- bit color icons.
  3536. *
  3537. * the icon resources can be 16, 24, 32 bpp, but the restable only has
  3538. * a color count, so a HiColor icon would have a max value in the
  3539. * restable. we treat a 0 in the color count as "max colors"
  3540. *
  3541. if (bpp > 8)
  3542. bpp = 8;
  3543. bpp = 1 << bpp;
  3544. */
  3545. /*
  3546. * Loop through resource entries, saving the "closest" item so far. Most
  3547. * of the real work is in MatchImage(), which uses a fabricated formula
  3548. * to give us the results that we desire. Namely, an image as close in
  3549. * size to what we want preferring bigger over smaller, then an image
  3550. * with the right color format
  3551. */
  3552. for (i = 0; i < uCount; i++, lprd++) {
  3553. TAGMSG1(DBGTAG_Icon, "GetBestImage: Checking candidate %d...", i);
  3554. bppCandidate = GetResourceBpp(lprd, fIcon);
  3555. /*
  3556. * Get "matching" value. How close are we to what we want?
  3557. */
  3558. score = MatchImage(lprd, &cxDesired, &cyDesired, bppDesired, fIcon);
  3559. TAGMSG0(DBGTAG_Icon, "---------------------------------------------");
  3560. if (score == 0) {
  3561. /*
  3562. * We've found an exact match!
  3563. */
  3564. TAGMSG1(DBGTAG_Icon, "GetBestImage: Found exact match: candidate=%d", i);
  3565. iBest = i;
  3566. break;
  3567. } else if (score < scoreBest) {
  3568. /*
  3569. * We've found a better match than the current alternative.
  3570. */
  3571. scoreBest = score;
  3572. iBest = i;
  3573. bppBest = bppCandidate;
  3574. } else if (score == scoreBest) {
  3575. /*
  3576. * Tie breaker: choose the higher color depth. If that fails, choose first one.
  3577. */
  3578. if (bppBest < bppCandidate) {
  3579. iBest = i;
  3580. bppBest = bppCandidate;
  3581. }
  3582. }
  3583. }
  3584. TAGMSG2(DBGTAG_Icon, "GetBestImage: Using best match: candidate=%d, score=%d", iBest, scoreBest);
  3585. return iBest;
  3586. }
  3587. /***************************************************************************\
  3588. * GetIcoCurWidth
  3589. *
  3590. * When zero is passed in for a dimension, calculates what size we should
  3591. * really used. Done in a couple o' places, so made it a FN().
  3592. *
  3593. \***************************************************************************/
  3594. _inline DWORD GetIcoCurWidth(
  3595. DWORD cxOrg,
  3596. BOOL fIcon,
  3597. UINT lrFlags,
  3598. DWORD cxDes)
  3599. {
  3600. if (cxOrg) {
  3601. return cxOrg;
  3602. } else if (lrFlags & LR_DEFAULTSIZE) {
  3603. return (fIcon ? SYSMET(CXICON) : SYSMET(CXCURSOR));
  3604. } else {
  3605. return cxDes;
  3606. }
  3607. }
  3608. /***************************************************************************\
  3609. * GetIcoCurHeight
  3610. *
  3611. * Vertical counterpart to GetWidth().
  3612. *
  3613. \***************************************************************************/
  3614. _inline DWORD GetIcoCurHeight(
  3615. DWORD cyOrg,
  3616. BOOL fIcon,
  3617. UINT lrFlags,
  3618. DWORD cyDes)
  3619. {
  3620. if (cyOrg) {
  3621. return cyOrg;
  3622. } else if (lrFlags & LR_DEFAULTSIZE) {
  3623. return (fIcon ? SYSMET(CYICON) : SYSMET(CYCURSOR));
  3624. } else {
  3625. return cyDes;
  3626. }
  3627. }
  3628. /***************************************************************************\
  3629. * GetIcoCurBpp
  3630. *
  3631. * Returns best match Bpp based on lr-flags.
  3632. *
  3633. \***************************************************************************/
  3634. _inline DWORD GetIcoCurBpp(
  3635. UINT lrFlags)
  3636. {
  3637. if (lrFlags & LR_MONOCHROME) {
  3638. #if DBG
  3639. if (lrFlags & LR_VGACOLOR) {
  3640. RIPMSG0(RIP_WARNING, "lrFlags has both MONOCHROME and VGACOLOR; assuming MONOCHROME");
  3641. }
  3642. #endif
  3643. return 1;
  3644. } else if (TEST_PUSIF(PUSIF_PALETTEDISPLAY) || (lrFlags & LR_VGACOLOR)) {
  3645. /*
  3646. * dwaynen - 1/12/2001
  3647. * Note: This used to also check the SM_SAMEDISPLAYFORMAT metric. If
  3648. * the display formats (on a multi-mon system) were different, it
  3649. * would also return 4, We have removed this code because we suspect
  3650. * that it isn't really needed.
  3651. * Refer to bug 258022.
  3652. *
  3653. * || !SYSMET(SAMEDISPLAYFORMAT)
  3654. *
  3655. */
  3656. return 4;
  3657. } else {
  3658. return 0;
  3659. }
  3660. }
  3661. /***************************************************************************\
  3662. * WOWFindResourceExWCover
  3663. *
  3664. * The WOW FindResource routines expect an ansi string so we have to
  3665. * convert the calling string IFF it is not an ID
  3666. *
  3667. \***************************************************************************/
  3668. HANDLE WOWFindResourceExWCover(
  3669. HANDLE hmod,
  3670. LPCWSTR rt,
  3671. LPCWSTR lpUniName,
  3672. WORD LangId)
  3673. {
  3674. LPSTR lpAnsiName;
  3675. HANDLE hRes;
  3676. if (ID(lpUniName))
  3677. return FINDRESOURCEEXA(hmod, (LPSTR)lpUniName, (LPSTR)rt, LangId);
  3678. /*
  3679. * Otherwise convert the name of the menu then call LoadMenu
  3680. */
  3681. if (!WCSToMB(lpUniName, -1, &lpAnsiName, -1, TRUE))
  3682. return NULL;
  3683. hRes = FINDRESOURCEEXA(hmod, lpAnsiName, (LPSTR)rt, LangId);
  3684. UserLocalFree(lpAnsiName);
  3685. return hRes;
  3686. }
  3687. /***************************************************************************\
  3688. * WOWLoadBitmapA
  3689. *
  3690. *
  3691. \***************************************************************************/
  3692. HBITMAP WOWLoadBitmapA(
  3693. HINSTANCE hmod,
  3694. LPCSTR lpName,
  3695. LPBYTE pResData,
  3696. DWORD cbResData)
  3697. {
  3698. LPWSTR lpUniName;
  3699. HBITMAP hRet;
  3700. UNREFERENCED_PARAMETER(cbResData);
  3701. if (pResData == NULL) {
  3702. if (ID(lpName))
  3703. return LoadBmp(hmod, (LPCWSTR)lpName, 0, 0, 0);
  3704. if (!MBToWCS(lpName, -1, &lpUniName, -1, TRUE))
  3705. return NULL;
  3706. hRet = LoadBmp(hmod, lpUniName, 0, 0, 0);
  3707. UserLocalFree(lpUniName);
  3708. } else {
  3709. hRet = ConvertDIBBitmap((LPBITMAPINFOHEADER)pResData,
  3710. 0,
  3711. 0,
  3712. LR_DEFAULTSIZE,
  3713. NULL,
  3714. NULL);
  3715. }
  3716. return hRet;
  3717. }
  3718. /***************************************************************************\
  3719. *
  3720. * WOWServerLoadCreateCursorIcon
  3721. *
  3722. \***************************************************************************/
  3723. HICON WowServerLoadCreateCursorIcon(
  3724. HANDLE hmod,
  3725. LPWSTR pszModName,
  3726. DWORD dwExpWinVer,
  3727. LPCWSTR lpName,
  3728. DWORD cb,
  3729. PVOID pResData,
  3730. LPWSTR type,
  3731. BOOL fClient)
  3732. {
  3733. HICON hRet;
  3734. BOOL fIcon = (type == RT_ICON);
  3735. UINT LR_Flags = LR_SHARED;
  3736. UNREFERENCED_PARAMETER(pszModName);
  3737. UNREFERENCED_PARAMETER(dwExpWinVer);
  3738. UNREFERENCED_PARAMETER(cb);
  3739. UNREFERENCED_PARAMETER(fClient);
  3740. if (!fIcon)
  3741. LR_Flags |= LR_MONOCHROME;
  3742. if (pResData == NULL) {
  3743. hRet = LoadIcoCur(hmod,
  3744. lpName,
  3745. type,
  3746. 0,
  3747. 0,
  3748. LR_Flags | LR_DEFAULTSIZE);
  3749. } else {
  3750. hRet = ConvertDIBIcon((LPBITMAPINFOHEADER)pResData,
  3751. hmod,
  3752. lpName,
  3753. fIcon,
  3754. GetIcoCurWidth(0 , fIcon, LR_DEFAULTSIZE, 0),
  3755. GetIcoCurHeight(0, fIcon, LR_DEFAULTSIZE, 0),
  3756. LR_Flags);
  3757. }
  3758. return hRet;
  3759. }
  3760. /***************************************************************************\
  3761. * WOWServerLoadCreateMenu
  3762. *
  3763. *
  3764. \***************************************************************************/
  3765. HMENU WowServerLoadCreateMenu(
  3766. HANDLE hMod,
  3767. LPCSTR lpName,
  3768. CONST LPMENUTEMPLATE pmt,
  3769. DWORD cb,
  3770. BOOL fCallClient)
  3771. {
  3772. UNREFERENCED_PARAMETER(cb);
  3773. UNREFERENCED_PARAMETER(fCallClient);
  3774. if (pmt == NULL) {
  3775. return LoadMenuA(hMod, lpName);
  3776. } else
  3777. return CreateMenuFromResource(pmt);
  3778. }
  3779. /***********************************************************************\
  3780. * DIBFromBitmap()
  3781. *
  3782. * Creates a memory block with DIB information from a physical bitmap tagged
  3783. * to a specific DC.
  3784. *
  3785. * A DIB block consists of a BITMAPINFOHEADER + RGB colors + DIB bits.
  3786. *
  3787. * Returns: UserLocalAlloc pointer to DIB info.
  3788. *
  3789. * 03-Nov-1995 SanfordS Created.
  3790. \***********************************************************************/
  3791. PVOID DIBFromBitmap(
  3792. HBITMAP hbmp,
  3793. HDC hdc)
  3794. {
  3795. BITMAP bmp;
  3796. LPBITMAPINFOHEADER lpbi;
  3797. DWORD cbBits;
  3798. DWORD cbPalette;
  3799. DWORD cbTotal;
  3800. WORD cBits;
  3801. UserAssert(hbmp);
  3802. UserAssert(hdc);
  3803. if (GetObject(hbmp, sizeof(BITMAP), &bmp) == 0)
  3804. return NULL;
  3805. cBits = ((WORD)bmp.bmPlanes * (WORD)bmp.bmBitsPixel);
  3806. TrySmallerDIB:
  3807. cbBits = (DWORD)WIDTHBYTES((WORD)bmp.bmWidth * cBits) * (DWORD)bmp.bmHeight;
  3808. cbPalette = 0;
  3809. if (cBits <= 8)
  3810. cbPalette = (1 << cBits) * sizeof(RGBQUAD);
  3811. else
  3812. cbPalette = 3 * sizeof(RGBQUAD);
  3813. cbTotal = sizeof(BITMAPINFOHEADER) + cbPalette + cbBits;
  3814. lpbi = (LPBITMAPINFOHEADER)UserLocalAlloc(HEAP_ZERO_MEMORY, cbTotal);
  3815. if (lpbi == NULL) {
  3816. /*
  3817. * Try a smaller DIB, if we can. We can't if the DIB is mono.
  3818. */
  3819. switch (cBits) {
  3820. case 4:
  3821. cBits = 1;
  3822. break;
  3823. case 8:
  3824. cBits = 4;
  3825. break;
  3826. case 16:
  3827. cBits = 8;
  3828. break;
  3829. case 24:
  3830. cBits = 16;
  3831. break;
  3832. case 32:
  3833. cBits = 24;
  3834. break;
  3835. default:
  3836. return NULL; // 1 or wierd.
  3837. }
  3838. RIPMSG1(RIP_WARNING, "Not enough memory to create large color DIB, trying %d bpp.", cBits);
  3839. goto TrySmallerDIB;
  3840. }
  3841. RtlZeroMemory(lpbi, sizeof(BITMAPINFOHEADER));
  3842. lpbi->biSize = sizeof(BITMAPINFOHEADER);
  3843. lpbi->biWidth = bmp.bmWidth;
  3844. lpbi->biHeight = bmp.bmHeight;
  3845. lpbi->biPlanes = 1;
  3846. lpbi->biBitCount = cBits;
  3847. /*
  3848. * Get old bitmap's DIB bits, using the current DC.
  3849. */
  3850. GetDIBits(hdc,
  3851. hbmp,
  3852. 0,
  3853. lpbi->biHeight,
  3854. ((LPSTR)lpbi) + lpbi->biSize + cbPalette,
  3855. (LPBITMAPINFO)lpbi,
  3856. DIB_RGB_COLORS);
  3857. lpbi->biClrUsed = cbPalette / sizeof(RGBQUAD);
  3858. lpbi->biSizeImage = cbBits;
  3859. return lpbi;
  3860. }
  3861. /***************************************************************************\
  3862. * CopyBmp
  3863. *
  3864. * Creates a new bitmap and copies the given bitmap to the new one,
  3865. * stretching and color-converting the bits if desired.
  3866. *
  3867. * 03-Nov-1995 SanfordS Created.
  3868. \***************************************************************************/
  3869. HBITMAP CopyBmp(
  3870. HBITMAP hbmpOrg,
  3871. int cxNew,
  3872. int cyNew,
  3873. UINT LR_flags)
  3874. {
  3875. HBITMAP hbmNew = NULL;
  3876. LPBITMAPINFOHEADER pdib;
  3877. RtlEnterCriticalSection(&gcsHdc);
  3878. if (pdib = DIBFromBitmap(hbmpOrg, ghdcBits2)) {
  3879. #if 0 // Win-9x comments this code out
  3880. if (LR_flags & LR_COPYRETURNORG) {
  3881. DWORD bpp = GetIcoCurBpp(LR_flags);
  3882. if ((cxNew == 0 || cxNew == pdib->biWidth) &&
  3883. (cyNew == 0 || cyNew == pdib->biHeight) &&
  3884. (bpp == 0 || bpp == pdib->biBitCount)) {
  3885. hbmNew = hbmpOrg;
  3886. }
  3887. }
  3888. if (hbmNew == NULL)
  3889. hbmNew = ConvertDIBBitmap(pdib, cxNew, cyNew, LR_flags, NULL, NULL);
  3890. #endif
  3891. hbmNew = ConvertDIBBitmap(pdib, cxNew, cyNew, LR_flags, NULL, NULL);
  3892. UserLocalFree(pdib);
  3893. }
  3894. RtlLeaveCriticalSection(&gcsHdc);
  3895. if ((LR_flags & LR_COPYDELETEORG) && hbmNew && (hbmNew != hbmpOrg))
  3896. DeleteObject(hbmpOrg);
  3897. return hbmNew;
  3898. }
  3899. /***********************************************************************\
  3900. * CopyImageFromRes
  3901. *
  3902. * This is used by the LR_COPYFROMRESOURCE option. We assume that the
  3903. * icon/cursor passed in is among the process list of loaded shared
  3904. * icons. If we find it there, we can attempt to load the icon from
  3905. * the resource to get an image that looks better than a stretched or
  3906. * compressed one.
  3907. *
  3908. * That way we will not stretch a 32x32 icon to 16x16 if someone added
  3909. * a 16x16 image to their class icon--a simple way for apps to jazz up
  3910. * their appearance.
  3911. *
  3912. * 12-Mar-1996 ChrisWil Created.
  3913. \***********************************************************************/
  3914. HICON CopyImageFromRes(
  3915. LPWSTR pszModName,
  3916. LPWSTR pszResName,
  3917. PCURSORFIND pcfSearch,
  3918. UINT LR_flags)
  3919. {
  3920. HINSTANCE hmod;
  3921. HICON hicoDst = NULL;
  3922. /*
  3923. * Override the search-criteria if this is the user-module. By
  3924. * setting these to zero, we are basically saying "don't care" for
  3925. * these attributes.
  3926. */
  3927. hmod = (pszModName ? WowGetModuleHandle(pszModName) : hmodUser);
  3928. if (hmod == hmodUser) {
  3929. pcfSearch->cx = 0;
  3930. pcfSearch->cy = 0;
  3931. pcfSearch->bpp = 0;
  3932. pszModName = szUSER32;
  3933. }
  3934. /*
  3935. * If a resource has been found with this name/bpp, then attempt
  3936. * to load the resource with the desired dimensions.
  3937. */
  3938. if (FindExistingCursorIcon(pszModName, pszResName, pcfSearch)) {
  3939. hicoDst = LoadIcoCur(hmod,
  3940. pszResName,
  3941. (LPWSTR)ULongToPtr( pcfSearch->rt ),
  3942. pcfSearch->cx,
  3943. pcfSearch->cy,
  3944. LR_flags);
  3945. }
  3946. return hicoDst;
  3947. }
  3948. /***********************************************************************\
  3949. * CopyIcoCur()
  3950. *
  3951. * Allocates a new icon resource and transmogrifies the old icon into the
  3952. * newly desired format.
  3953. *
  3954. * Note that if we have to stretch the icon, the hotspot area changes. For
  3955. * icons, the hotspot is set to be the middle of the icon.
  3956. *
  3957. * Returns:
  3958. *
  3959. * 01-Nov-1995 SanfordS Created.
  3960. * 12-Mar-1996 ChrisWil Added lookup for existing icon/cursor.
  3961. \***********************************************************************/
  3962. HICON CopyIcoCur(
  3963. HICON hicoSrc,
  3964. BOOL fIcon,
  3965. int cxNew,
  3966. int cyNew,
  3967. UINT LR_flags)
  3968. {
  3969. HBITMAP hbmMaskNew;
  3970. HBITMAP hbmColorNew;
  3971. int cx;
  3972. int cy;
  3973. DWORD bpp;
  3974. DWORD bppDesired;
  3975. HICON hicoDst = NULL;
  3976. ICONINFO ii;
  3977. CURSORDATA cur;
  3978. UNICODE_STRING strModName;
  3979. UNICODE_STRING strResName;
  3980. WCHAR awszModName[MAX_PATH];
  3981. WCHAR awszResName[MAX_PATH];
  3982. /*
  3983. * Extract needed info from existing icon/cursor from the kernel
  3984. */
  3985. if (!NtUserGetIconSize(hicoSrc, 0, &cx, &cy))
  3986. return NULL;
  3987. cy >>= 1;
  3988. if (LR_flags & LR_CREATEDIBSECTION)
  3989. LR_flags = (LR_flags & ~LR_CREATEDIBSECTION) | LR_CREATEREALDIB;
  3990. /*
  3991. * Setup unicode-strings for calls to kernel-side.
  3992. */
  3993. strModName.Length = 0;
  3994. strModName.MaximumLength = MAX_PATH;
  3995. strModName.Buffer = awszModName;
  3996. strResName.Length = 0;
  3997. strResName.MaximumLength = MAX_PATH;
  3998. strResName.Buffer = awszResName;
  3999. /*
  4000. * Note: this creates copies of hbmMask and hbmColor that need to be
  4001. * freed before we leave.
  4002. */
  4003. if (!NtUserGetIconInfo(hicoSrc,
  4004. &ii,
  4005. &strModName,
  4006. &strResName,
  4007. &bpp,
  4008. TRUE)) {
  4009. return NULL;
  4010. }
  4011. cxNew = GetIcoCurWidth(cxNew, fIcon, LR_flags, cx);
  4012. cyNew = GetIcoCurHeight(cyNew, fIcon, LR_flags, cy);
  4013. if (LR_flags & LR_COPYFROMRESOURCE) {
  4014. CURSORFIND cfSearch;
  4015. LPWSTR pszModName;
  4016. /*
  4017. * Setup the search criteria.
  4018. */
  4019. cfSearch.hcur = hicoSrc;
  4020. cfSearch.rt = PtrToUlong((fIcon ? RT_ICON : RT_CURSOR));
  4021. cfSearch.cx = cxNew;
  4022. cfSearch.cy = cyNew;
  4023. cfSearch.bpp = bpp;
  4024. /*
  4025. * Copy the image. This performs a lookup for the hicoSrc. If
  4026. * it is not found in the process and shared caches, then we
  4027. * will proceed with copying the hicoSrc. If an icon is found
  4028. * in the cache, then we will attempt to reload the image for
  4029. * the best resolution possible.
  4030. */
  4031. pszModName = (strModName.Length ? strModName.Buffer : NULL);
  4032. hicoDst = CopyImageFromRes(pszModName,
  4033. strResName.Buffer,
  4034. &cfSearch,
  4035. LR_flags);
  4036. if (hicoDst)
  4037. goto CleanupExit;
  4038. }
  4039. bppDesired = GetIcoCurBpp(LR_flags);
  4040. if ((cxNew != cx) ||
  4041. (cyNew != cy) ||
  4042. ((bpp != 1) && (bppDesired != 0) && (bppDesired != bpp))) {
  4043. /*
  4044. * Since we have to stretch or maybe fixup the colors just get
  4045. * the DIB bits and let ConverDIBBitmap do all the magic.
  4046. */
  4047. hbmMaskNew = CopyBmp(ii.hbmMask, cxNew, cyNew * 2, LR_MONOCHROME);
  4048. if (hbmMaskNew == NULL)
  4049. goto CleanupExit;
  4050. hbmColorNew = NULL;
  4051. if (ii.hbmColor) {
  4052. hbmColorNew = CopyBmp(ii.hbmColor, cxNew, cyNew, LR_flags);
  4053. if (hbmColorNew == NULL) {
  4054. DeleteObject(hbmMaskNew);
  4055. goto CleanupExit;
  4056. }
  4057. }
  4058. /*
  4059. * Replace ii.hbmxxx guys with our fixed up copies and delete the old.
  4060. */
  4061. DeleteObject(ii.hbmMask);
  4062. ii.hbmMask = hbmMaskNew;
  4063. if (ii.hbmColor && (ii.hbmColor != hbmColorNew)) {
  4064. DeleteObject(ii.hbmColor);
  4065. ii.hbmColor = hbmColorNew;
  4066. }
  4067. /*
  4068. * tweak the hotspots for changes in size.
  4069. */
  4070. if (cxNew != cx)
  4071. ii.xHotspot = MultDiv(ii.xHotspot, cxNew, cx);
  4072. if (cyNew != cy)
  4073. ii.yHotspot = MultDiv(ii.yHotspot, cyNew, cy);
  4074. } else if (LR_flags & LR_COPYRETURNORG) {
  4075. hicoDst = hicoSrc;
  4076. CleanupExit:
  4077. /*
  4078. * Free up the bitmaps which were created by GetIconInfo().
  4079. */
  4080. DeleteObject(ii.hbmMask);
  4081. if (ii.hbmColor)
  4082. DeleteObject(ii.hbmColor);
  4083. goto Exit;
  4084. }
  4085. /*
  4086. * Build the icon/cursor object from the info. The bitmaps
  4087. * are not freed in this case.
  4088. */
  4089. hicoDst = (HICON)NtUserCallOneParam(0, SFI__CREATEEMPTYCURSOROBJECT);
  4090. if (hicoDst == NULL)
  4091. goto CleanupExit;
  4092. RtlZeroMemory(&cur, sizeof(cur));
  4093. cur.lpName = strResName.Length ? strResName.Buffer : NULL;
  4094. cur.lpModName = strModName.Length ? strModName.Buffer : NULL;
  4095. cur.rt = ii.fIcon ? PTR_TO_ID(RT_ICON) : PTR_TO_ID(RT_CURSOR);
  4096. cur.bpp = bpp;
  4097. cur.cx = cxNew;
  4098. cur.cy = cyNew * 2;
  4099. cur.xHotspot = (short)ii.xHotspot;
  4100. cur.yHotspot = (short)ii.yHotspot;
  4101. cur.hbmMask = ii.hbmMask;
  4102. cur.hbmColor = ii.hbmColor;
  4103. if (!_SetCursorIconData(hicoDst, &cur)) {
  4104. NtUserDestroyCursor(hicoDst, CURSOR_ALWAYSDESTROY);
  4105. return NULL;
  4106. }
  4107. Exit:
  4108. /*
  4109. * destroy the original if asked to.
  4110. */
  4111. if (hicoDst != hicoSrc && (LR_flags & LR_COPYDELETEORG))
  4112. DestroyCursor(hicoSrc);
  4113. return hicoDst;
  4114. }
  4115. /***********************************************************************\
  4116. * CopyImage
  4117. *
  4118. * Allocates a new icon resource and copies the attributes of the old icon
  4119. * to the new icon.
  4120. *
  4121. * Returns: hIconNew
  4122. *
  4123. * 01-Nov-1995 SanfordS Created.
  4124. \***********************************************************************/
  4125. FUNCLOG5(LOG_GENERAL, HANDLE, WINAPI, CopyImage, HANDLE, hImage, UINT, IMAGE_flag, int, cxNew, int, cyNew, UINT, LR_flags)
  4126. HANDLE WINAPI CopyImage(
  4127. HANDLE hImage,
  4128. UINT IMAGE_flag,
  4129. int cxNew,
  4130. int cyNew,
  4131. UINT LR_flags)
  4132. {
  4133. if (LR_flags & ~LR_VALID) {
  4134. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "CopyImage: bad LR_flags.");
  4135. return NULL;
  4136. }
  4137. return InternalCopyImage(hImage, IMAGE_flag, cxNew, cyNew, LR_flags);
  4138. }
  4139. /***********************************************************************\
  4140. * InternalCopyImage
  4141. *
  4142. * Performs the copyimage work. This is called from the callback-thunk.
  4143. *
  4144. \***********************************************************************/
  4145. HANDLE InternalCopyImage(
  4146. HANDLE hImage,
  4147. UINT IMAGE_flag,
  4148. int cxNew,
  4149. int cyNew,
  4150. UINT LR_flags)
  4151. {
  4152. switch (IMAGE_flag) {
  4153. case IMAGE_BITMAP:
  4154. if (GetObjectType(hImage) != OBJ_BITMAP) {
  4155. RIPERR0(ERROR_INVALID_HANDLE, RIP_WARNING, "CopyImage: invalid bitmap");
  4156. return NULL;
  4157. }
  4158. return (HICON)CopyBmp(hImage, cxNew, cyNew, LR_flags);
  4159. case IMAGE_CURSOR:
  4160. case IMAGE_ICON:
  4161. return CopyIcoCur(hImage,
  4162. (IMAGE_flag == IMAGE_ICON),
  4163. cxNew,
  4164. cyNew,
  4165. LR_flags);
  4166. }
  4167. RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "CopyImage: bad IMAGE_flag.");
  4168. return NULL;
  4169. }
  4170. /***************************************************************************\
  4171. * RtlGetIdFromDirectory
  4172. *
  4173. * History:
  4174. * 06-Apr-1991 ScottLu Cleaned up, make work with client/server.
  4175. * 16-Nov-1995 SanfordS Now uses LookupIconIdFromDirectoryEx
  4176. \***************************************************************************/
  4177. int RtlGetIdFromDirectory(
  4178. PBYTE presbits,
  4179. BOOL fIcon,
  4180. int cxDesired,
  4181. int cyDesired,
  4182. DWORD LR_flags,
  4183. PDWORD pdwResSize)
  4184. {
  4185. LPNEWHEADER lpnh;
  4186. LPRESDIR lprsd;
  4187. UINT iImage;
  4188. UINT cImage;
  4189. UINT bpp;
  4190. /*
  4191. * Make sure this is pointing to valid resource bits.
  4192. */
  4193. if (presbits == NULL)
  4194. return 0;
  4195. lpnh = (LPNEWHEADER)presbits;
  4196. /*
  4197. * Fill in defaults.
  4198. */
  4199. cxDesired = GetIcoCurWidth(cxDesired, fIcon, LR_flags, 0);
  4200. cyDesired = GetIcoCurHeight(cyDesired, fIcon, LR_flags, 0);
  4201. bpp = GetIcoCurBpp(LR_flags);
  4202. /*
  4203. * We'll use the first image in the directory if we can't find one
  4204. * that's appropriate.
  4205. */
  4206. cImage = lpnh->ResCount;
  4207. lprsd = (LPRESDIR)(lpnh + 1);
  4208. iImage = GetBestImage(lprsd, cImage, cxDesired, cyDesired, bpp, fIcon);
  4209. if (iImage == cImage)
  4210. iImage = 0;
  4211. if (pdwResSize != NULL)
  4212. *pdwResSize = (lprsd + iImage)->BytesInRes;
  4213. return ((LPRESDIR)(lprsd + iImage))->idIcon;
  4214. }