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

1754 lines
50 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * RMLOAD.C
  8. * WOW16 user resource services
  9. *
  10. * History:
  11. *
  12. * Created 12-Apr-1991 by Nigel Thompson (nigelt)
  13. * Much hacked about version of the Win 3.1 rmload.c source
  14. * It doesn't attempt any device driver resource loading
  15. * or do anything to support Win 2.x apps.
  16. *
  17. * Revised 19-May-1991 by Jeff Parsons (jeffpar)
  18. * IFDEF'ed everything except LoadString; because of the client/server
  19. * split in USER32, most resources are copied to the server's context and
  20. * freed in the client's, meaning the client no longer gets a handle to
  21. * a global memory object. We could give it one, but it would be a separate
  22. * object, which we would have to keep track of, and which would be difficult
  23. * to keep in sync with the server's copy if changes were made.
  24. --*/
  25. /****************************************************************************/
  26. /* */
  27. /* RMLOAD.C - */
  28. /* */
  29. /* Resource Loading Routines. */
  30. /* */
  31. /****************************************************************************/
  32. #define RESOURCESTRINGS
  33. #include "user.h"
  34. #include "multires.h"
  35. //
  36. // We define certain things here because including mvdm\inc\*.h files here
  37. // will lead to endless mess.
  38. //
  39. DWORD API NotifyWow(WORD, LPBYTE);
  40. typedef struct _LOADACCEL16 { /* ldaccel */
  41. WORD hInst;
  42. WORD hAccel;
  43. LPBYTE pAccel;
  44. DWORD cbAccel;
  45. } LOADACCEL16, FAR *PLOADACCEL16;
  46. /* This must match its counterpart in mvdm\inc\wowusr.h */
  47. #define NW_LOADACCELERATORS 3 //
  48. /*--------------------------------------------------------------------------*/
  49. /* */
  50. /* LoadAccelerators() - */
  51. /* */
  52. /*--------------------------------------------------------------------------*/
  53. HACCEL API ILoadAccelerators(HINSTANCE hInstance, LPCSTR lpszAccName)
  54. {
  55. HRSRC hrl;
  56. HACCEL hAccel = NULL;
  57. LOADACCEL16 loadaccel;
  58. hrl = FindResource(hInstance, lpszAccName, RT_ACCELERATOR);
  59. #ifdef WOW
  60. if (hrl) {
  61. hAccel = (HACCEL)LoadResource(hInstance, hrl);
  62. if (hAccel) {
  63. // create 32bit accelerator and 16-32 alias.
  64. loadaccel.hInst = (WORD)hInstance;
  65. loadaccel.hAccel = (WORD)hAccel;
  66. loadaccel.pAccel = (LPBYTE)LockResource(hAccel);
  67. loadaccel.cbAccel = (DWORD)SizeofResource(hInstance, hrl);
  68. if (NotifyWow(NW_LOADACCELERATORS, (LPBYTE)&loadaccel)) {
  69. UnlockResource(hAccel);
  70. }
  71. else {
  72. UnlockResource(hAccel);
  73. hAccel = NULL;
  74. }
  75. }
  76. }
  77. return (hAccel);
  78. #else
  79. if (!hrl)
  80. return NULL;
  81. return (HACCEL)LoadResource(hInstance, hrl);
  82. #endif
  83. }
  84. int API ILoadString(
  85. HINSTANCE h16Task,
  86. UINT wID,
  87. LPSTR lpBuffer,
  88. register int nBufferMax)
  89. {
  90. HANDLE hResInfo;
  91. HANDLE hStringSeg;
  92. LPSTR lpsz;
  93. register int cch, i;
  94. /* Make sure the parms are valid. */
  95. if (!lpBuffer || (nBufferMax-- == 0))
  96. return(0);
  97. cch = 0;
  98. /* String Tables are broken up into 16 string segments. Find the segment
  99. * containing the string we are interested in.
  100. */
  101. if (hResInfo = FindResource(h16Task, (LPSTR)((LONG)((wID >> 4) + 1)), RT_STRING))
  102. {
  103. /* Load that segment. */
  104. hStringSeg = LoadResource(h16Task, hResInfo);
  105. /* Lock the resource. */
  106. if (lpsz = (LPSTR)LockResource(hStringSeg))
  107. {
  108. /* Move past the other strings in this segment. */
  109. wID &= 0x0F;
  110. while (TRUE)
  111. {
  112. cch = *((BYTE FAR *)lpsz++);
  113. if (wID-- == 0)
  114. break;
  115. lpsz += cch;
  116. }
  117. /* Don't copy more than the max allowed. */
  118. if (cch > nBufferMax)
  119. cch = nBufferMax;
  120. /* Copy the string into the buffer. */
  121. LCopyStruct(lpsz, lpBuffer, cch);
  122. GlobalUnlock(hStringSeg);
  123. /* BUG: If we free the resource here, we will have to reload it
  124. * immediately for many apps with sequential strings.
  125. * Force it to be discardable however because non-discardable
  126. * string resources make no sense. Chip
  127. */
  128. GlobalReAlloc(hStringSeg, 0L,
  129. GMEM_MODIFY | GMEM_MOVEABLE | GMEM_DISCARDABLE);
  130. }
  131. }
  132. /* Append a NULL. */
  133. lpBuffer[cch] = 0;
  134. return(cch);
  135. }
  136. #ifdef NEEDED
  137. #define DIB_RGB_COLORS 0
  138. HBITMAP FAR PASCAL ConvertBitmap(HBITMAP hBitmap);
  139. HANDLE NEAR PASCAL LoadDIBCursorIconHandler(HANDLE, HANDLE, HANDLE, BOOL);
  140. WORD FAR PASCAL GetIconId(HANDLE, LPSTR);
  141. HBITMAP FAR PASCAL StretchBitmap(int, int, int, int, HBITMAP, BYTE, BYTE);
  142. WORD NEAR PASCAL StretchIcon(LPCURSORSHAPE, WORD, HBITMAP, BOOL);
  143. WORD NEAR PASCAL SizeReqd(BOOL, WORD, WORD, BOOL, int, int);
  144. WORD NEAR PASCAL CrunchAndResize(LPCURSORSHAPE, BOOL, BOOL, BOOL, BOOL);
  145. HANDLE FAR PASCAL LoadCursorIconHandler2(HANDLE, LPCURSORSHAPE, WORD);
  146. HANDLE FAR PASCAL LoadDIBCursorIconHandler2(HANDLE, LPCURSORSHAPE, WORD, BOOL);
  147. /*--------------------------------------------------------------------------*/
  148. /* */
  149. /* LoadIconHandler() - */
  150. /* */
  151. /*--------------------------------------------------------------------------*/
  152. HICON FAR PASCAL LoadIconHandler(hIcon, fNewFormat)
  153. HICON hIcon;
  154. BOOL fNewFormat;
  155. {
  156. LPCURSORSHAPE lpIcon;
  157. WORD wSize;
  158. dprintf(7,"LoadIconHandler");
  159. wSize = (WORD)GlobalSize(hIcon);
  160. lpIcon = (LPCURSORSHAPE)(GlobalLock(hIcon));
  161. if (fNewFormat)
  162. return(LoadDIBCursorIconHandler2(hIcon, lpIcon, wSize, TRUE));
  163. else
  164. return(LoadCursorIconHandler2(hIcon, lpIcon, wSize));
  165. }
  166. /*--------------------------------------------------------------------------*/
  167. /* */
  168. /* FindIndividualResource() */
  169. /* */
  170. /*--------------------------------------------------------------------------*/
  171. HANDLE NEAR PASCAL FindIndividualResource(register HANDLE hResFile,
  172. LPSTR lpszName,
  173. LPSTR lpszType)
  174. {
  175. WORD idIcon;
  176. register HANDLE h;
  177. dprintf(7,"FindIndividualResource");
  178. /* Check if the resource is to be taken from the display driver.
  179. * If so, check the driver version; If the resource is to be taken from
  180. * the application, check the app version.
  181. */
  182. if ((lpszType != RT_BITMAP) && ((LOWORD(GetExpWinVer(hResFile)) >= VER)))
  183. {
  184. /* Locate the directory resource */
  185. h = SplFindResource(hResFile, lpszName, (LPSTR)(lpszType + DIFFERENCE));
  186. if (h == NULL)
  187. return((HANDLE)0);
  188. /* Load the directory resource */
  189. h = LoadResource(hResFile, h);
  190. /* Get the name of the matching resource */
  191. idIcon = GetIconId(h, lpszType);
  192. /* NOTE: Don't free the (discardable) directory resource!!! - ChipA */
  193. /*
  194. * We should not call SplFindResource here, because idIcon is
  195. * internal to us and GetDriverResourceId won't know how tomap it.
  196. */
  197. return(FindResource(hResFile, MAKEINTRESOURCE(idIcon), lpszType));
  198. }
  199. else
  200. /* It is an Old app; The resource is in old format */
  201. return(SplFindResource(hResFile, lpszName, lpszType));
  202. }
  203. /*--------------------------------------------------------------------------*/
  204. /* */
  205. /* GetBestFormIcon() */
  206. /* */
  207. /* Among the different forms of Icons present, choose the one that */
  208. /* matches the PixelsPerInch values and the number of colors of the */
  209. /* current display. */
  210. /* */
  211. /*--------------------------------------------------------------------------*/
  212. WORD NEAR PASCAL GetBestFormIcon(LPRESDIR ResDirPtr,
  213. WORD ResCount)
  214. {
  215. register WORD wIndex;
  216. register WORD ColorCount;
  217. WORD MaxColorCount;
  218. WORD MaxColorIndex;
  219. WORD MoreColorCount;
  220. WORD MoreColorIndex;
  221. WORD LessColorCount;
  222. WORD LessColorIndex;
  223. WORD DevColorCount;
  224. dprintf(7,"GetBestFormIcon");
  225. /* Initialse all the values to zero */
  226. MaxColorCount = MaxColorIndex = MoreColorCount =
  227. MoreColorIndex = LessColorIndex = LessColorCount = 0;
  228. /* get number of colors on device. if device is very colorful,
  229. ** set to a high number without doing meaningless 1<<X operation.
  230. */
  231. if (oemInfo.ScreenBitCount >= 16)
  232. DevColorCount = 32000;
  233. else
  234. DevColorCount = 1 << oemInfo.ScreenBitCount;
  235. for (wIndex=0; wIndex < ResCount; wIndex++, ResDirPtr++)
  236. {
  237. /* Check for the number of colors */
  238. if ((ColorCount = (ResDirPtr->ResInfo.Icon.ColorCount)) <= DevColorCount)
  239. {
  240. if (ColorCount > MaxColorCount)
  241. {
  242. MaxColorCount = ColorCount;
  243. MaxColorIndex = wIndex;
  244. }
  245. }
  246. /* Check for the size */
  247. /* Match the pixels per inch information */
  248. if ((ResDirPtr->ResInfo.Icon.Width == (BYTE)oemInfo.cxIcon) &&
  249. (ResDirPtr->ResInfo.Icon.Height == (BYTE)oemInfo.cyIcon))
  250. {
  251. /* Matching size found */
  252. /* Check if the color also matches */
  253. if (ColorCount == DevColorCount)
  254. return(wIndex); /* Exact match found */
  255. if (ColorCount < DevColorCount)
  256. {
  257. /* Choose the one with max colors, but less than reqd */
  258. if (ColorCount > LessColorCount)
  259. {
  260. LessColorCount = ColorCount;
  261. LessColorIndex = wIndex;
  262. }
  263. }
  264. else
  265. {
  266. if ((LessColorCount == 0) && (ColorCount < MoreColorCount))
  267. {
  268. MoreColorCount = ColorCount;
  269. MoreColorIndex = wIndex;
  270. }
  271. }
  272. }
  273. }
  274. /* Check if we have a correct sized but with less colors than reqd */
  275. if (LessColorCount)
  276. return(LessColorIndex);
  277. /* Check if we have a correct sized but with more colors than reqd */
  278. if (MoreColorCount)
  279. return(MoreColorIndex);
  280. /* Check if we have one that has maximum colors but less than reqd */
  281. if (MaxColorCount)
  282. return(MaxColorIndex);
  283. return(0);
  284. }
  285. /*--------------------------------------------------------------------------*/
  286. /* */
  287. /* GetBestFormCursor() */
  288. /* */
  289. /* Among the different forms of cursors present, choose the one that */
  290. /* matches the width and height defined by the current display driver. */
  291. /* */
  292. /*--------------------------------------------------------------------------*/
  293. WORD NEAR PASCAL GetBestFormCursor(LPRESDIR ResDirPtr,
  294. WORD ResCount)
  295. {
  296. register WORD wIndex;
  297. dprintf(7,"GetBestFormCursor");
  298. for (wIndex=0; wIndex < ResCount; wIndex++, ResDirPtr++)
  299. {
  300. /* Match the Width and Height of the cursor */
  301. if ((ResDirPtr->ResInfo.Cursor.Width == oemInfo.cxCursor) &&
  302. ((ResDirPtr->ResInfo.Cursor.Height >> 1) == oemInfo.cyCursor))
  303. return(wIndex);
  304. }
  305. return(0);
  306. }
  307. /*--------------------------------------------------------------------------*/
  308. /* */
  309. /* GetIconId() */
  310. /* */
  311. /*--------------------------------------------------------------------------*/
  312. WORD FAR PASCAL GetIconId(hRes, lpszType)
  313. HANDLE hRes;
  314. LPSTR lpszType;
  315. {
  316. WORD w;
  317. LPRESDIR ResDirPtr;
  318. LPNEWHEADER DataPtr;
  319. register WORD RetIndex;
  320. register WORD ResCount;
  321. dprintf(7,"GetIconId");
  322. if ((DataPtr = (LPNEWHEADER)LockResource(hRes)) == NULL)
  323. return(0);
  324. ResCount = DataPtr->ResCount;
  325. ResDirPtr = (LPRESDIR)(DataPtr + 1);
  326. switch (LOWORD((DWORD)lpszType))
  327. {
  328. case RT_ICON:
  329. RetIndex = GetBestFormIcon(ResDirPtr, ResCount);
  330. break;
  331. case RT_CURSOR:
  332. RetIndex = GetBestFormCursor(ResDirPtr, ResCount);
  333. break;
  334. }
  335. if (RetIndex == ResCount)
  336. RetIndex = 0;
  337. ResCount = ((LPRESDIR)(ResDirPtr+RetIndex))->idIcon;
  338. UnlockResource(hRes);
  339. return(ResCount);
  340. }
  341. /*--------------------------------------------------------------------------*/
  342. /* */
  343. /* UT_LoadCursorIconBitmap() - */
  344. /* */
  345. /*--------------------------------------------------------------------------*/
  346. HANDLE NEAR PASCAL UT_LoadCursorIconBitmap(register HANDLE hrf,
  347. LPSTR lpszName,
  348. int type)
  349. {
  350. register HANDLE h;
  351. dprintf(7,"LoadCursorIconBitmap");
  352. if (hrf == NULL) return (HANDLE)0; // no 2.x support - NigelT
  353. h = FindIndividualResource(hrf, lpszName, MAKEINTRESOURCE(type));
  354. if (h != NULL)
  355. h = LoadResource(hrf, h);
  356. return(h);
  357. }
  358. /*--------------------------------------------------------------------------*/
  359. /* */
  360. /* fCheckMono() - */
  361. /* Checks a DIB for being truely monochrome. Only called if */
  362. /* BitCount == 1. This function checks the color table (address */
  363. /* passed) for true black and white RGB's */
  364. /* */
  365. /*--------------------------------------------------------------------------*/
  366. BOOL NEAR PASCAL fCheckMono(LPVOID lpColorTable,
  367. BOOL fNewDIB)
  368. {
  369. LPLONG lpRGB;
  370. LPWORD lpRGBw;
  371. dprintf(7,"fCheckMono");
  372. lpRGB = lpColorTable;
  373. if (fNewDIB)
  374. {
  375. if ((*lpRGB == 0 && *(lpRGB + 1) == 0x00FFFFFF) ||
  376. (*lpRGB == 0x00FFFFFF && *(lpRGB + 1) == 0))
  377. return(TRUE);
  378. }
  379. else
  380. {
  381. lpRGBw = lpColorTable;
  382. if (*(LPSTR)lpRGBw == 0)
  383. {
  384. if (*lpRGBw == 0 && *(lpRGBw+1) == 0xFF00 && *(lpRGBw+2) == 0xFFFF)
  385. return(TRUE);
  386. }
  387. else if (*lpRGBw == 0xFFFF && *(lpRGBw+1) == 0x00FF && *(lpRGBw+2) == 0)
  388. return(TRUE);
  389. }
  390. return(FALSE);
  391. }
  392. /*--------------------------------------------------------------------------*/
  393. /* */
  394. /* LoadNewBitmap() - */
  395. /* */
  396. /*--------------------------------------------------------------------------*/
  397. /* Loads a 3.x format bitmap into the DIB structure. */
  398. HBITMAP NEAR PASCAL LoadNewBitmap(HANDLE hRes,
  399. LPSTR lpName)
  400. {
  401. register HBITMAP hbmS;
  402. register HBITMAP hBitmap;
  403. dprintf(7,"LoadNewBitmap");
  404. if ((hbmS = hBitmap = UT_LoadCursorIconBitmap(hRes,lpName,(WORD)RT_BITMAP)))
  405. {
  406. /* Convert the DIB bitmap into a bitmap in the internal format */
  407. hbmS = ConvertBitmap(hBitmap);
  408. /* Converted bitmap is in hbmS; So, release the DIB */
  409. FreeResource(hBitmap);
  410. }
  411. return(hbmS);
  412. }
  413. /*--------------------------------------------------------------------------*/
  414. /* */
  415. /* ConvertBitmap() */
  416. /* */
  417. /* This takes in a handle to data in PM 1.1 or 1.2 DIB format or */
  418. /* Windows 3.0 DIB format and creates a bitmap in the internal */
  419. /* bitmap format and returns the handle to it. */
  420. /* */
  421. /* NOTE: */
  422. /* This function is exported because it is called from CLIPBRD.EXE */
  423. /* */
  424. /*--------------------------------------------------------------------------*/
  425. HBITMAP FAR PASCAL ConvertBitmap(HBITMAP hBitmap)
  426. {
  427. int Width;
  428. register int Height;
  429. HDC hDC;
  430. BOOL fMono = FALSE;
  431. LPSTR lpBits;
  432. register HBITMAP hbmS;
  433. LPBITMAPINFOHEADER lpBitmap1;
  434. LPBITMAPCOREHEADER lpBitmap2;
  435. dprintf(7,"ConvertBitmap");
  436. lpBitmap1 = (LPBITMAPINFOHEADER)LockResource(hBitmap);
  437. if (!lpBitmap1)
  438. return(NULL);
  439. if ((WORD)lpBitmap1->biSize == sizeof(BITMAPCOREHEADER))
  440. {
  441. /* This is an "old form" DIB. This matches the PM 1.1 format. */
  442. lpBitmap2 = (LPBITMAPCOREHEADER)lpBitmap1;
  443. Width = lpBitmap2->bcWidth;
  444. Height = lpBitmap2->bcHeight;
  445. /* Calcluate the pointer to the Bits information */
  446. /* First skip over the header structure */
  447. lpBits = (LPSTR)(lpBitmap2 + 1);
  448. /* Skip the color table entries, if any */
  449. if (lpBitmap2->bcBitCount != 24)
  450. {
  451. if (lpBitmap2->bcBitCount == 1)
  452. fMono = fCheckMono(lpBits, FALSE);
  453. lpBits += (1 << (lpBitmap2->bcBitCount)) * sizeof(RGBTRIPLE);
  454. }
  455. }
  456. else
  457. {
  458. Width = (WORD)lpBitmap1->biWidth;
  459. Height = (WORD)lpBitmap1->biHeight;
  460. /* Calcluate the pointer to the Bits information */
  461. /* First skip over the header structure */
  462. lpBits = (LPSTR)(lpBitmap1 + 1);
  463. /* Skip the color table entries, if any */
  464. if (lpBitmap1->biClrUsed != 0)
  465. {
  466. if (lpBitmap1->biClrUsed == 2)
  467. fMono = fCheckMono(lpBits, TRUE);
  468. lpBits += lpBitmap1->biClrUsed * sizeof(RGBQUAD);
  469. }
  470. else
  471. {
  472. if (lpBitmap1->biBitCount != 24)
  473. {
  474. if (lpBitmap1->biBitCount == 1)
  475. fMono = fCheckMono(lpBits, TRUE);
  476. lpBits += (1 << (lpBitmap1->biBitCount)) * sizeof(RGBQUAD);
  477. }
  478. }
  479. }
  480. /* Create a bitmap */
  481. if (fMono)
  482. hbmS = CreateBitmap(Width, Height, 1, 1, (LPSTR)NULL);
  483. else
  484. {
  485. /* Create a color bitmap compatible with the display device */
  486. hDC = GetScreenDC();
  487. hbmS = CreateCompatibleBitmap(hDC, Width, Height);
  488. InternalReleaseDC(hDC);
  489. }
  490. /* Initialize the new bitmap by converting from PM format */
  491. if (hbmS != NULL)
  492. SetDIBits(hdcBits, hbmS, 0, Height, lpBits,
  493. (LPBITMAPINFO)lpBitmap1, DIB_RGB_COLORS);
  494. GlobalUnlock(hBitmap);
  495. return(hbmS);
  496. }
  497. HANDLE NEAR PASCAL Helper_LoadCursorOrIcon(HANDLE hRes,
  498. LPSTR lpName,
  499. WORD type)
  500. {
  501. HANDLE h;
  502. dprintf(7,"Helper_LoadCursorOrIcon");
  503. /* If we can't find the cursor/icon in the app, and this is a 2.x app, we
  504. * need to search into the display driver to find it.
  505. */
  506. h = UT_LoadCursorIconBitmap(hRes, lpName, type);
  507. return(h);
  508. }
  509. /*--------------------------------------------------------------------------*/
  510. /* */
  511. /* LoadCursor() - */
  512. /* */
  513. /*--------------------------------------------------------------------------*/
  514. HCURSOR API LoadCursor(hRes, lpName)
  515. HANDLE hRes;
  516. LPSTR lpName;
  517. {
  518. HCURSOR hcur;
  519. dprintf(5,"LoadCursor");
  520. if (hRes == NULL) {
  521. dprintf(9," Calling Win32 to load Cursor");
  522. hcur = WOWLoadCursor32(hRes, lpName);
  523. } else {
  524. hcur = ((HCURSOR)Helper_LoadCursorOrIcon(hRes, lpName, (WORD)RT_CURSOR));
  525. }
  526. #ifdef DEBUG
  527. if (hcur == NULL) {
  528. dprintf(9," Failed, BUT returning 1 so app won't die (yet)");
  529. return (HCURSOR)1;
  530. }
  531. #endif
  532. dprintf(5,"LoadCursor returning %4.4XH", hcur);
  533. return hcur;
  534. }
  535. /*--------------------------------------------------------------------------*/
  536. /* */
  537. /* LoadIcon() - */
  538. /* */
  539. /*--------------------------------------------------------------------------*/
  540. HICON API LoadIcon(hRes, lpName)
  541. HANDLE hRes;
  542. LPSTR lpName;
  543. {
  544. HICON hicon;
  545. dprintf(5,"LoadIcon");
  546. if (hRes == NULL) {
  547. dprintf(9," Calling Win32 to load Icon");
  548. hicon = WOWLoadIcon32(hRes, lpName);
  549. } else {
  550. hicon = ((HICON)Helper_LoadCursorOrIcon(hRes, lpName, (WORD)RT_ICON));
  551. }
  552. #ifdef DEBUG
  553. if (hicon == NULL) {
  554. dprintf(9," Failed, BUT returning 1 so app won't die (yet)");
  555. return (HICON)1;
  556. }
  557. #endif
  558. dprintf(5,"LoadIcon returning %4.4XH", hicon);
  559. return hicon;
  560. }
  561. /*--------------------------------------------------------------------------*/
  562. /* */
  563. /* StretchBitmap() - */
  564. /* */
  565. /* This routine stretches a bitmap into another bitmap, */
  566. /* and returns the stretched bitmap. */
  567. /*--------------------------------------------------------------------------*/
  568. HBITMAP FAR PASCAL StretchBitmap(iOWidth, iOHeight, iNWidth, iNHeight, hbmS,
  569. byPlanes, byBitsPixel)
  570. int iOWidth;
  571. int iOHeight;
  572. int iNWidth;
  573. int iNHeight;
  574. HBITMAP hbmS;
  575. BYTE byPlanes;
  576. BYTE byBitsPixel;
  577. {
  578. register HBITMAP hbmD;
  579. HBITMAP hbmDSave;
  580. register HDC hdcSrc;
  581. dprintf(7,"StretchBitmap");
  582. if ((hdcSrc = CreateCompatibleDC(hdcBits)) != NULL)
  583. {
  584. if ((hbmD = (HBITMAP)CreateBitmap(iNWidth, iNHeight, byPlanes, byBitsPixel, (LPINT)NULL)) == NULL)
  585. goto GiveUp;
  586. if ((hbmDSave = SelectObject(hdcBits, hbmD)) == NULL)
  587. goto GiveUp;
  588. if (SelectObject(hdcSrc, hbmS) != NULL)
  589. {
  590. /* NOTE: We don't have to save the bitmap returned from
  591. * SelectObject(hdcSrc) and select it back in to hdcSrc,
  592. * because we delete hdcSrc.
  593. */
  594. SetStretchBltMode(hdcBits, COLORONCOLOR);
  595. StretchBlt(hdcBits, 0, 0, iNWidth, iNHeight, hdcSrc, 0, 0, iOWidth, iOHeight, SRCCOPY);
  596. SelectObject(hdcBits, hbmDSave);
  597. DeleteDC(hdcSrc);
  598. return(hbmD);
  599. }
  600. else
  601. {
  602. GiveUp:
  603. if (hbmD != NULL)
  604. DeleteObject(hbmD);
  605. DeleteDC(hdcSrc);
  606. goto Step1;
  607. }
  608. }
  609. else
  610. {
  611. Step1:
  612. return(NULL);
  613. }
  614. }
  615. /*--------------------------------------------------------------------------*/
  616. /* */
  617. /* LoadOldBitmap() - */
  618. /* */
  619. /* This loads bitmaps in old formats( Version 2.10 and below) */
  620. /*--------------------------------------------------------------------------*/
  621. HANDLE NEAR PASCAL LoadOldBitmap(HANDLE hRes,
  622. LPSTR lpName)
  623. {
  624. int oWidth;
  625. int oHeight;
  626. BYTE planes;
  627. BYTE bitsPixel;
  628. WORD wCount;
  629. DWORD dwCount;
  630. LPBITMAP lpBitmap;
  631. register HBITMAP hbmS;
  632. HBITMAP hbmD;
  633. register HBITMAP hBitmap;
  634. BOOL fCrunch;
  635. WORD wDevDep;
  636. dprintf(7,"LoadOldBitmap");
  637. if (hbmS = hBitmap = UT_LoadCursorIconBitmap(hRes, lpName, BMR_BITMAP))
  638. {
  639. lpBitmap = (LPBITMAP)LockResource(hBitmap);
  640. fCrunch = ((*(((BYTE FAR *)lpBitmap) + 1) & 0x0F) != BMR_DEVDEP);
  641. lpBitmap = (LPBITMAP)((BYTE FAR *)lpBitmap + 2);
  642. oWidth = lpBitmap->bmWidth;
  643. oHeight = lpBitmap->bmHeight;
  644. planes = lpBitmap->bmPlanes;
  645. bitsPixel = lpBitmap->bmBitsPixel;
  646. if (!(*(((BYTE FAR *)lpBitmap) + 1) & 0x80))
  647. {
  648. hbmS = CreateBitmap(oWidth, oHeight, planes, bitsPixel,
  649. (LPSTR)(lpBitmap + 1));
  650. }
  651. else
  652. {
  653. hbmS = (HBITMAP)CreateDiscardableBitmap(hdcBits, oWidth, oHeight);
  654. wCount = (((oWidth * bitsPixel + 0x0F) & ~0x0F) >> 3);
  655. dwCount = wCount * oHeight * planes;
  656. SetBitmapBits(hbmS, dwCount, (LPSTR)(lpBitmap + 1));
  657. }
  658. GlobalUnlock(hBitmap);
  659. FreeResource(hBitmap);
  660. if (hbmS != NULL)
  661. {
  662. if (fCrunch && ((64/oemInfo.cxIcon + 64/oemInfo.cyIcon) > 2))
  663. {
  664. /* Stretch the Bitmap to suit the device */
  665. hbmD = StretchBitmap(oWidth, oHeight,
  666. (oWidth * oemInfo.cxIcon/64),
  667. (oHeight * oemInfo.cyIcon/64),
  668. hbmS, planes, bitsPixel);
  669. /* Delete the old bitmap */
  670. DeleteObject(hbmS);
  671. if (hbmD == NULL)
  672. return(NULL); /* Some problem in stretching */
  673. else
  674. return(hbmD); /* Return the stretched bitmap */
  675. }
  676. }
  677. }
  678. else
  679. {
  680. return (HANDLE)0;
  681. }
  682. return(hbmS);
  683. }
  684. /*--------------------------------------------------------------------------*/
  685. /* */
  686. /* LoadBitmap() - */
  687. /* */
  688. /* This routine decides whether the bitmap to be loaded is in old or */
  689. /* new (DIB) format and calls appropriate handlers. */
  690. /* */
  691. /*--------------------------------------------------------------------------*/
  692. HANDLE API LoadBitmap(hRes, lpName)
  693. HANDLE hRes;
  694. LPSTR lpName;
  695. {
  696. HANDLE hbmp;
  697. dprintf(5,"LoadBitmap");
  698. if (hRes == NULL) {
  699. dprintf(9," Calling Win32 to load Bitmap");
  700. hbmp = WOWLoadBitmap32(hRes, lpName);
  701. } else {
  702. /* Check if the resource is to be taken from the display driver. If so,
  703. * check the driver version; If the resource is to be taken from the
  704. * application, check the app version
  705. */
  706. if (((hRes == NULL) && (oemInfo.DispDrvExpWinVer >= VER)) ||
  707. ((hRes != NULL) && (LOWORD(GetExpWinVer(hRes)) >= VER))) {
  708. hbmp = (LoadNewBitmap(hRes, lpName));
  709. } else {
  710. hbmp = (LoadOldBitmap(hRes, lpName));
  711. }
  712. }
  713. #ifdef DEBUG
  714. if (hbmp == NULL) {
  715. dprintf(9," Failed, BUT returning 1 so app won't die (yet)");
  716. return (HANDLE)1;
  717. }
  718. #endif
  719. dprintf(5,"LoadBitmap returning %4.4XH", hbmp);
  720. return hbmp;
  721. }
  722. /*--------------------------------------------------------------------------*/
  723. /* */
  724. /* CrunchAndResize() - */
  725. /* This Crunches the monochrome icons and cursors if required and */
  726. /* returns the newsize of the resource after crunching. */
  727. /* This routine is also called to resize the monochrome AND mask of a */
  728. /* color icon. */
  729. /* Parameters: */
  730. /* lpIcon: Ptr to the resource */
  731. /* fIcon : TRUE, if the resource is an icon. FALSE, if it is a cursor. */
  732. /* fCrunch : TRUE if resource is to be resized. */
  733. /* fSinglePlane: TRUE if only AND mask of a color icon is passed */
  734. /* through lpIcon */
  735. /* fUseSysMetrics: Whether to use the icon/cursor values found in */
  736. /* oemInfo or not. */
  737. /* Returns: */
  738. /* The new size of the resource is returned. */
  739. /* */
  740. /*--------------------------------------------------------------------------*/
  741. WORD NEAR PASCAL CrunchAndResize(lpIcon, fIcon, fCrunch, fSinglePlane, fUseSysMetrics)
  742. LPCURSORSHAPE lpIcon;
  743. BOOL fIcon;
  744. BOOL fCrunch;
  745. BOOL fSinglePlane;
  746. BOOL fUseSysMetrics;
  747. {
  748. WORD size;
  749. register int cx;
  750. register int cy;
  751. int oHeight;
  752. int nHeight;
  753. int iNewcbWidth;
  754. BOOL bStretch;
  755. HBITMAP hbmS;
  756. HBITMAP hbmD;
  757. dprintf(7,"CrunhAndResize");
  758. if(fUseSysMetrics)
  759. {
  760. if(fIcon)
  761. {
  762. cx = oemInfo.cxIcon;
  763. cy = oemInfo.cyIcon;
  764. }
  765. else
  766. {
  767. cx = oemInfo.cxCursor;
  768. cy = oemInfo.cyCursor;
  769. }
  770. }
  771. else
  772. {
  773. cx = lpIcon->cx;
  774. cy = lpIcon->cy;
  775. }
  776. if (fIcon)
  777. {
  778. lpIcon->xHotSpot = cx >> 1;
  779. lpIcon->yHotSpot = cy >> 1;
  780. if (fSinglePlane)
  781. {
  782. /* Only the AND mask exists */
  783. oHeight = lpIcon->cy;
  784. nHeight = cy;
  785. }
  786. else
  787. {
  788. /* Both AND ans XOR masks exist; So, height must be twice */
  789. oHeight = lpIcon->cy << 1;
  790. nHeight = cy << 1;
  791. }
  792. }
  793. else
  794. {
  795. oHeight = lpIcon->cy << 1;
  796. nHeight = cy << 1;
  797. }
  798. iNewcbWidth = ((cx + 0x0F) & ~0x0F) >> 3;
  799. size = iNewcbWidth * nHeight;
  800. if (fCrunch && ((lpIcon->cx != cx) || (lpIcon->cy != cy)))
  801. {
  802. if (!fIcon)
  803. {
  804. lpIcon->xHotSpot = (lpIcon->xHotSpot * cx)/(lpIcon->cx);
  805. lpIcon->yHotSpot = (lpIcon->yHotSpot * cy)/(lpIcon->cy);
  806. }
  807. /* To begin with, assume that no stretching is required */
  808. bStretch = FALSE;
  809. /* Check if the width is to be reduced */
  810. if (lpIcon->cx != cx)
  811. {
  812. /* Stretching the Width is necessary */
  813. bStretch = TRUE;
  814. }
  815. /* Check if the Height is to be reduced */
  816. if (lpIcon->cy != cy)
  817. {
  818. /* Stretching in Y direction is necessary */
  819. bStretch = TRUE;
  820. }
  821. /* Check if stretching is necessary */
  822. if (bStretch)
  823. {
  824. /* Create a monochrome bitmap with the icon/cursor bits */
  825. if ((hbmS = CreateBitmap(lpIcon->cx, oHeight, 1, 1, (LPSTR)(lpIcon + 1))) == NULL)
  826. return(NULL);
  827. if ((hbmD = StretchBitmap(lpIcon->cx, oHeight, cx, nHeight, hbmS, 1, 1)) == NULL)
  828. {
  829. DeleteObject(hbmS);
  830. return(NULL);
  831. }
  832. DeleteObject(hbmS);
  833. lpIcon->cx = cx;
  834. lpIcon->cy = cy;
  835. lpIcon->cbWidth = iNewcbWidth;
  836. GetBitmapBits(hbmD, (DWORD)size, (LPSTR)(lpIcon + 1));
  837. DeleteObject(hbmD);
  838. }
  839. }
  840. return(size + sizeof(CURSORSHAPE));
  841. }
  842. /*--------------------------------------------------------------------------*/
  843. /* */
  844. /* LoadCursorIconHandler() - */
  845. /* */
  846. /* This handles 2.x (and less) Cursors and Icons */
  847. /* */
  848. /*--------------------------------------------------------------------------*/
  849. HANDLE FAR PASCAL LoadCursorIconHandler(hRes, hResFile, hResIndex)
  850. register HANDLE hRes;
  851. HANDLE hResFile;
  852. HANDLE hResIndex;
  853. {
  854. register int fh = 0;
  855. BOOL bNew = FALSE;
  856. WORD wMemSize;
  857. LPCURSORSHAPE lpIcon;
  858. HANDLE hTempRes;
  859. dprintf(7,"LoadCursorIconHandler");
  860. wMemSize = SizeofResource(hResFile, hResIndex);
  861. #if 1 // was 0 - NigelT
  862. if (!hRes)
  863. {
  864. if (!(hRes = AllocResource(hResFile, hResIndex, 0L)))
  865. return(NULL);
  866. fh = -1;
  867. bNew = TRUE;
  868. }
  869. while (!(lpIcon = (LPCURSORSHAPE)GlobalLock(hRes)))
  870. {
  871. if (!GlobalReAlloc(hRes, (DWORD)wMemSize, 0))
  872. goto LoadCIFail;
  873. else
  874. fh = -1;
  875. }
  876. if (fh)
  877. {
  878. fh = AccessResource(hResFile, hResIndex);
  879. if (fh != -1 && _lread(fh, (LPSTR)lpIcon, wMemSize) != 0xFFFF)
  880. _lclose(fh);
  881. else
  882. {
  883. if (fh != -1)
  884. _lclose(fh);
  885. GlobalUnlock(hRes);
  886. goto LoadCIFail;
  887. }
  888. }
  889. #else
  890. /* Call kernel's resource handler instead of doing the stuff ourselves
  891. * because we use cached file handles that way. davidds
  892. */
  893. // For resources which are not preloaded, hRes will be NULL at this point.
  894. // For such cases, the default resource handler does the memory allocation
  895. // and returns a valid handle.
  896. // Fix for Bug #4257 -- 01/21/91 -- SANKAR
  897. if (!(hTempRes = lpDefaultResourceHandler(hRes, hResFile, hResIndex)))
  898. goto LoadCIFail;
  899. // We must use the handle returned by lpDefaultResourceHandler.
  900. hRes = hTempRes;
  901. lpIcon = (LPCURSORSHAPE)GlobalLock(hRes);
  902. #endif
  903. if (LoadCursorIconHandler2(hRes, lpIcon, wMemSize))
  904. return(hRes);
  905. LoadCIFail:
  906. /* If the loading of the resource fails, we MUST discard the memory we
  907. * reallocated above, or kernel will simply globallock the thing on the
  908. * next call to LockResource(), leaving invalid data in the object.
  909. */
  910. if (bNew)
  911. GlobalFree(hRes);
  912. else
  913. GlobalDiscard(hRes);
  914. return(NULL);
  915. }
  916. /*--------------------------------------------------------------------------*/
  917. /* */
  918. /* LoadCursorIconHandler2() - */
  919. /* */
  920. /* This handles all 2.x Cursors and Icons */
  921. /* */
  922. /*--------------------------------------------------------------------------*/
  923. HANDLE FAR PASCAL LoadCursorIconHandler2(hRes, lpIcon, wMemSize)
  924. register HANDLE hRes;
  925. LPCURSORSHAPE lpIcon;
  926. register WORD wMemSize;
  927. {
  928. BOOL fCrunch;
  929. BOOL fIcon;
  930. WORD wNewSize;
  931. BOOL fStretchInXdirection;
  932. BOOL fStretchInYdirection;
  933. dprintf(7,"LoadCursorIconHandler2");
  934. fIcon = (*(LPSTR)lpIcon == BMR_ICON);
  935. /* Is this a device dependant icon/cursor?. */
  936. fCrunch = (*((LPSTR)lpIcon+1) != BMR_DEVDEP);
  937. LCopyStruct((LPSTR)lpIcon+2, (LPSTR)lpIcon, wMemSize-2);
  938. fCrunch = fCrunch || (lpIcon->cx != GetSystemMetrics(SM_CXICON)) ||
  939. (lpIcon->cy != GetSystemMetrics(SM_CYICON));
  940. /* Only support monochrome cursors. */
  941. lpIcon->Planes = lpIcon->BitsPixel = 1;
  942. fStretchInXdirection = fStretchInYdirection = TRUE; // Assume we need stretching.
  943. if(fIcon)
  944. {
  945. if((oemInfo.cxIcon > STD_ICONWIDTH) && (lpIcon->cx <= oemInfo.cxIcon))
  946. fStretchInXdirection = FALSE; // No Need to stretch in X direction;
  947. if((oemInfo.cyIcon > STD_ICONHEIGHT) && (lpIcon->cy <= oemInfo.cyIcon))
  948. fStretchInYdirection = FALSE; // No need to stretch in Y direction;
  949. }
  950. else
  951. {
  952. if((oemInfo.cxCursor > STD_CURSORWIDTH) && (lpIcon->cx <= oemInfo.cxCursor))
  953. fStretchInXdirection = FALSE; // No need to stretch in X direction.
  954. if((oemInfo.cyCursor > STD_CURSORHEIGHT) && (lpIcon->cy <= oemInfo.cyCursor))
  955. fStretchInYdirection = FALSE; // No need to stretch in Y direction.
  956. }
  957. // Check if the Icon/Cursor needs to be stretched now or not
  958. if(!(fStretchInXdirection || fStretchInYdirection))
  959. {
  960. GlobalUnlock(hRes);
  961. return(hRes);
  962. }
  963. wNewSize = SizeReqd(fIcon, 1, 1, TRUE, 0, 0);
  964. /* Before we crunch, let us make sure we have a big enough resource. */
  965. if (fCrunch)
  966. {
  967. if (wNewSize > wMemSize)
  968. {
  969. GlobalUnlock(hRes);
  970. /* Make this non discardable so that kernel will try to move this
  971. * block when reallocing. DavidDS
  972. */
  973. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_NODISCARD);
  974. if (!GlobalReAlloc(hRes, (DWORD)wNewSize, 0))
  975. {
  976. /* So it gets discarded. Note that since the above realloc is
  977. * less than 64K, the handle won't change.
  978. */
  979. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_DISCARDABLE);
  980. return(NULL);
  981. }
  982. /* So it gets discarded */
  983. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_DISCARDABLE);
  984. if (!(lpIcon = (LPCURSORSHAPE)GlobalLock(hRes)))
  985. return(NULL);
  986. wMemSize = wNewSize;
  987. }
  988. }
  989. wNewSize = CrunchAndResize(lpIcon, fIcon, fCrunch, FALSE, TRUE);
  990. GlobalUnlock(hRes);
  991. /* Has it already been resized? */
  992. if (wNewSize < wMemSize)
  993. {
  994. /* Make it an exact fit. */
  995. if (!GlobalReAlloc(hRes, (DWORD)wNewSize, 0))
  996. return(NULL);
  997. }
  998. return(hRes);
  999. }
  1000. /*--------------------------------------------------------------------------*/
  1001. /* */
  1002. /* LoadDIBCursorHandler() - */
  1003. /* */
  1004. /* This is called when a Cursor in DIB format is loaded */
  1005. /* This converts the cursor into Old format and returns the handle */
  1006. /* */
  1007. /*--------------------------------------------------------------------------*/
  1008. HANDLE FAR PASCAL LoadDIBCursorHandler(hRes, hResFile, hResIndex)
  1009. HANDLE hRes;
  1010. HANDLE hResFile;
  1011. HANDLE hResIndex;
  1012. {
  1013. dprintf(7,"LoadDIBCursorIconHandler");
  1014. return(LoadDIBCursorIconHandler(hRes, hResFile, hResIndex, FALSE));
  1015. }
  1016. /*--------------------------------------------------------------------------*/
  1017. /* */
  1018. /* LoadDIBIconHandler() - */
  1019. /* */
  1020. /* This is called when an Icon in DIB format is loaded */
  1021. /* This converts the cursor into Old format and returns the handle */
  1022. /* */
  1023. /*--------------------------------------------------------------------------*/
  1024. HANDLE FAR PASCAL LoadDIBIconHandler(hRes, hResFile, hResIndex)
  1025. HANDLE hRes;
  1026. HANDLE hResFile;
  1027. HANDLE hResIndex;
  1028. {
  1029. dprintf(7,"LoadDIBIconHandler");
  1030. return(LoadDIBCursorIconHandler(hRes, hResFile, hResIndex, TRUE));
  1031. }
  1032. /*--------------------------------------------------------------------------*/
  1033. /* */
  1034. /* StretchIcon() - */
  1035. /* When this routine is called, lpIcon already has the monochrome */
  1036. /* AND bitmap properly sized. This routine adds the color XOR bitmap at */
  1037. /* end of lpIcon and updates the header with the values of the color */
  1038. /* info(bitcount and Planes); */
  1039. /* wOldSize : Contains the size of AND mask + CURSORSHAPE */
  1040. /* */
  1041. /* Returns: The new size ( Size of AND mask + XOR bitmap + CURSORSHAPE) */
  1042. /* */
  1043. /*--------------------------------------------------------------------------*/
  1044. WORD NEAR PASCAL StretchIcon(lpIcon, wOldSize, hXORbitmap, fStretchToSysMetrics)
  1045. LPCURSORSHAPE lpIcon;
  1046. WORD wOldSize;
  1047. register HBITMAP hXORbitmap;
  1048. BOOL fStretchToSysMetrics;
  1049. {
  1050. WORD wCount;
  1051. BITMAP bitmap;
  1052. register HBITMAP hNewBitmap;
  1053. dprintf(7,"StretchIcon");
  1054. GetObject(hXORbitmap, sizeof(BITMAP), (LPSTR)&bitmap);
  1055. if(fStretchToSysMetrics)
  1056. {
  1057. /* Do we need to resize things? */
  1058. if ((oemInfo.cxIcon != bitmap.bmWidth) || (oemInfo.cyIcon != bitmap.bmHeight))
  1059. {
  1060. hNewBitmap = StretchBitmap(bitmap.bmWidth, bitmap.bmHeight,
  1061. oemInfo.cxIcon, oemInfo.cyIcon, hXORbitmap,
  1062. bitmap.bmPlanes, bitmap.bmBitsPixel);
  1063. DeleteObject(hXORbitmap);
  1064. if (hNewBitmap == NULL)
  1065. return(0);
  1066. GetObject(hNewBitmap, sizeof(BITMAP), (LPSTR)&bitmap);
  1067. hXORbitmap = hNewBitmap;
  1068. }
  1069. }
  1070. /* Update the Planes and BitsPixels field with the color values */
  1071. lpIcon->Planes = bitmap.bmPlanes;
  1072. lpIcon->BitsPixel = bitmap.bmBitsPixel;
  1073. wCount = bitmap.bmWidthBytes * bitmap.bmHeight * bitmap.bmPlanes;
  1074. GetBitmapBits(hXORbitmap, (DWORD)wCount, (LPSTR)((LPSTR)lpIcon + wOldSize));
  1075. DeleteObject(hXORbitmap);
  1076. return(wCount + wOldSize);
  1077. }
  1078. /*--------------------------------------------------------------------------*/
  1079. /* */
  1080. /* LoadDIBCursorIconHandler() - */
  1081. /* */
  1082. /* This is called when a Cursor/Icon in DIB format is loaded */
  1083. /* This converts the cursor/icon internal format and returns the */
  1084. /* handle */
  1085. /* */
  1086. /*--------------------------------------------------------------------------*/
  1087. HANDLE NEAR PASCAL LoadDIBCursorIconHandler(hRes, hResFile, hResIndex, fIcon)
  1088. register HANDLE hRes;
  1089. HANDLE hResFile;
  1090. HANDLE hResIndex;
  1091. BOOL fIcon;
  1092. {
  1093. register int fh = 0;
  1094. BOOL bNew = FALSE;
  1095. WORD wMemBlkSize;
  1096. LPCURSORSHAPE lpCurSh;
  1097. HANDLE hTempRes;
  1098. dprintf(7,"LoadDIBCursorIconHandler");
  1099. wMemBlkSize = (WORD)SizeofResource(hResFile, hResIndex);
  1100. #if 1 // was 0 - NigelT
  1101. if (!hRes)
  1102. {
  1103. if (!(hRes = AllocResource(hResFile, hResIndex, 0L)))
  1104. goto LoadDIBFail;
  1105. fh = -1;
  1106. bNew = TRUE;
  1107. }
  1108. while (!(lpCurSh = (LPCURSORSHAPE)GlobalLock(hRes)))
  1109. {
  1110. if (!GlobalReAlloc(hRes, (DWORD)wMemBlkSize, 0))
  1111. goto LoadDIBFail;
  1112. else
  1113. fh = -1;
  1114. }
  1115. if (fh)
  1116. {
  1117. fh = AccessResource(hResFile, hResIndex);
  1118. if (fh != -1 && _lread(fh, (LPSTR)lpCurSh, wMemBlkSize) != 0xFFFF)
  1119. _lclose(fh);
  1120. else
  1121. {
  1122. if (fh != -1)
  1123. _lclose(fh);
  1124. GlobalUnlock(hRes);
  1125. goto LoadDIBFail;
  1126. }
  1127. }
  1128. #else
  1129. /* Call kernel's resource handler instead of doing the stuff ourselves
  1130. * because we use cached file handles that way. davidds
  1131. */
  1132. // For resources which are not preloaded, hRes will be NULL at this point.
  1133. // For such cases, the default resource handler does the memory allocation
  1134. // and returns a valid handle.
  1135. // Fix for Bug #4257 -- 01/21/91 -- SANKAR
  1136. if (!(hTempRes = lpDefaultResourceHandler(hRes, hResFile, hResIndex)))
  1137. goto LoadDIBFail;
  1138. // We must use the handle returned by lpDefaultResourceHandler.
  1139. hRes = hTempRes;
  1140. lpCurSh = (LPCURSORSHAPE)GlobalLock(hRes);
  1141. #endif
  1142. if (LoadDIBCursorIconHandler2(hRes, lpCurSh, wMemBlkSize, fIcon))
  1143. return(hRes);
  1144. LoadDIBFail:
  1145. /* if the loading of the resource fails, we MUST discard the memory we
  1146. * reallocated above, or kernel will simply globallock the thing on the
  1147. * next call to LockResource(), leaving invalid data in the object.
  1148. */
  1149. if (bNew)
  1150. FreeResource(hRes);
  1151. else
  1152. GlobalDiscard(hRes);
  1153. return(NULL);
  1154. }
  1155. /*--------------------------------------------------------------------------*/
  1156. /* */
  1157. /* LoadDIBCursorIconHandler2() - */
  1158. /* */
  1159. /* This is called when a Cursor/Icon in DIB format is loaded */
  1160. /* This converts the cursor/icon into Old format and returns the */
  1161. /* handle */
  1162. /* */
  1163. /* NOTE: All cursors(always monochrome) and Monochrome Icons are treated */
  1164. /* alike by this routine. Color Icons are treated as special case */
  1165. /* determined by the local flag "fMono". */
  1166. /* */
  1167. /*--------------------------------------------------------------------------*/
  1168. HANDLE FAR PASCAL LoadDIBCursorIconHandler2(hRes, lpCurSh, wMemBlkSize, fIcon)
  1169. register HANDLE hRes;
  1170. WORD wMemBlkSize;
  1171. LPCURSORSHAPE lpCurSh;
  1172. register BOOL fIcon;
  1173. {
  1174. HDC hDC;
  1175. BOOL fMono = FALSE;
  1176. WORD Width;
  1177. WORD Height;
  1178. WORD wCount;
  1179. WORD BitCount;
  1180. WORD Planes;
  1181. LPSTR lpBits;
  1182. BITMAP bitmap;
  1183. HBITMAP hBitmap;
  1184. WORD wNewSize;
  1185. HBITMAP hANDbitmap;
  1186. HBITMAP hXORbitmap;
  1187. LPWORD lpColorTable;
  1188. LPBITMAPINFOHEADER lpHeader;
  1189. LPBITMAPCOREHEADER lpHeader1 = 0;
  1190. BOOL fStretchToSysMetrics;
  1191. BOOL fStretchInXdirection;
  1192. BOOL fStretchInYdirection;
  1193. dprintf(7,"LoadDIBCursorIconHandler2");
  1194. lpHeader = (LPBITMAPINFOHEADER)lpCurSh;
  1195. if (!fIcon)
  1196. {
  1197. /* Skip over the cursor hotspot data in the first 2 words. */
  1198. lpHeader = (LPBITMAPINFOHEADER)((LPSTR)lpHeader + 4);
  1199. }
  1200. if ((WORD)lpHeader->biSize == sizeof(BITMAPCOREHEADER))
  1201. {
  1202. /* This is an "old form" DIB. This matches the PM 1.1 format. */
  1203. lpHeader1 = (LPBITMAPCOREHEADER)lpHeader;
  1204. Width = lpHeader1->bcWidth;
  1205. Height = lpHeader1->bcHeight;
  1206. BitCount = lpHeader1->bcBitCount;
  1207. Planes = lpHeader1->bcPlanes;
  1208. /* Calcluate the pointer to the Bits information */
  1209. /* First skip over the header structure */
  1210. lpColorTable = (LPWORD)(lpBits = (LPSTR)(lpHeader1 + 1));
  1211. /* Skip the color table entries, if any */
  1212. if (lpHeader1->bcBitCount != 24)
  1213. {
  1214. if (lpHeader1->bcBitCount == 1)
  1215. fMono = fCheckMono(lpBits, FALSE);
  1216. lpBits += (1 << (lpHeader1->bcBitCount)) * sizeof(RGBTRIPLE);
  1217. }
  1218. }
  1219. else
  1220. {
  1221. Width = (WORD)lpHeader->biWidth;
  1222. Height = (WORD)lpHeader->biHeight;
  1223. BitCount = lpHeader->biBitCount;
  1224. Planes = lpHeader->biPlanes;
  1225. /* Calcluate the pointer to the Bits information */
  1226. /* First skip over the header structure */
  1227. lpColorTable = (LPWORD)(lpBits = (LPSTR)(lpHeader + 1));
  1228. /* Skip the color table entries, if any */
  1229. if (lpHeader->biClrUsed != 0)
  1230. {
  1231. if (lpHeader->biClrUsed == 2)
  1232. fMono = fCheckMono(lpBits, TRUE);
  1233. lpBits += lpHeader->biClrUsed * sizeof(RGBQUAD);
  1234. }
  1235. else
  1236. {
  1237. if (lpHeader->biBitCount != 24)
  1238. {
  1239. if (lpHeader->biBitCount == 1)
  1240. fMono = fCheckMono(lpBits, TRUE);
  1241. lpBits += (1 << (lpHeader->biBitCount)) * sizeof(RGBQUAD);
  1242. }
  1243. }
  1244. }
  1245. // By default Stretch the icon/cursor to the dimensions in oemInfo;
  1246. // If this is FALSE, then the stretching will take place during DrawIcon();
  1247. fStretchInXdirection = TRUE;
  1248. fStretchInYdirection = TRUE;
  1249. // Check if the Icon/Cursor needs to be stretched to the dimensions in
  1250. // oemInfo now or not.
  1251. if(fIcon)
  1252. {
  1253. if((oemInfo.cxIcon > STD_ICONWIDTH) && (Width <= oemInfo.cxIcon))
  1254. fStretchInXdirection = FALSE; // No Need to stretch in X direction;
  1255. if((oemInfo.cyIcon > STD_ICONHEIGHT) && (Height <= oemInfo.cyIcon))
  1256. fStretchInYdirection = FALSE; // No need to stretch in Y direction;
  1257. }
  1258. else
  1259. {
  1260. if((oemInfo.cxCursor > STD_CURSORWIDTH) && (Width <= oemInfo.cxCursor))
  1261. fStretchInXdirection = FALSE; // No need to stretch in X direction.
  1262. if((oemInfo.cyCursor > STD_CURSORHEIGHT) && (Height <= oemInfo.cyCursor))
  1263. fStretchInYdirection = FALSE; // No need to stretch in Y direction.
  1264. }
  1265. fStretchToSysMetrics = fStretchInXdirection || fStretchInYdirection;
  1266. if (fMono)
  1267. {
  1268. /* Create a bitmap */
  1269. if (!(hBitmap = CreateBitmap(Width, Height, 1, 1, (LPSTR)NULL)))
  1270. {
  1271. GlobalUnlock(hRes);
  1272. return(NULL);
  1273. }
  1274. /* Convert the DIBitmap format into internal format */
  1275. SetDIBits(hdcBits, hBitmap, 0, Height, lpBits, (LPBITMAPINFO)lpHeader, DIB_RGB_COLORS);
  1276. // Cursors/Icons in DIB format have a height twice the actual height.
  1277. wNewSize = SizeReqd(fIcon, BitCount, Planes, fStretchToSysMetrics, Width, Height>>1);
  1278. }
  1279. else
  1280. {
  1281. /* The height is twice that of icons */
  1282. Height >>= 1;
  1283. if (lpHeader1)
  1284. lpHeader1->bcHeight = Height;
  1285. else
  1286. lpHeader->biHeight = Height;
  1287. /* Create the XOR bitmap Compatible with the current device */
  1288. hDC = GetScreenDC();
  1289. if (!(hXORbitmap = CreateCompatibleBitmap(hDC, Width, Height)))
  1290. {
  1291. InternalReleaseDC(hDC);
  1292. GlobalUnlock(hRes);
  1293. return(NULL);
  1294. }
  1295. InternalReleaseDC(hDC);
  1296. /* Convert the DIBitmap into internal format */
  1297. SetDIBits(hdcBits, hXORbitmap, 0, Height, lpBits,
  1298. (LPBITMAPINFO)lpHeader, DIB_RGB_COLORS);
  1299. GetObject(hXORbitmap, sizeof(BITMAP), (LPSTR)(&bitmap));
  1300. wNewSize = SizeReqd(fIcon, bitmap.bmBitsPixel, bitmap.bmPlanes,
  1301. fStretchToSysMetrics, Width, Height);
  1302. /* Create the monochrome AND bitmap */
  1303. if (!(hANDbitmap = CreateBitmap(Width, Height, 1, 1, (LPSTR)NULL)))
  1304. {
  1305. GlobalUnlock(hRes);
  1306. return(NULL);
  1307. }
  1308. /* Get the offset to the AND bitmap */
  1309. lpBits += (((Width * BitCount + 0x1F) & ~0x1F) >> 3) * Height;
  1310. /* Set the header with data for a monochrome bitmap */
  1311. Planes = BitCount = 1;
  1312. /* Set the color table for a monochrome bitmap */
  1313. *lpColorTable++ = 0;
  1314. *lpColorTable++ = 0xFF00;
  1315. *lpColorTable = 0xFFFF;
  1316. if (lpHeader1)
  1317. {
  1318. lpHeader1->bcWidth = Width;
  1319. lpHeader1->bcHeight = Height;
  1320. lpHeader1->bcPlanes = Planes;
  1321. lpHeader1->bcBitCount = BitCount;
  1322. }
  1323. else
  1324. {
  1325. lpHeader->biWidth = Width;
  1326. lpHeader->biHeight = Height;
  1327. lpHeader->biPlanes = Planes;
  1328. lpHeader->biBitCount = BitCount;
  1329. }
  1330. SetDIBits(hdcBits, hANDbitmap, 0, Height, lpBits,
  1331. (LPBITMAPINFO)lpHeader, DIB_RGB_COLORS);
  1332. hBitmap = hANDbitmap;
  1333. }
  1334. GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&bitmap);
  1335. if (fIcon)
  1336. {
  1337. lpCurSh->xHotSpot = 0;
  1338. lpCurSh->yHotSpot = 0;
  1339. }
  1340. /* The following lines are replaced by a single functon call
  1341. *
  1342. * lpCurSh->cx = bitmap.bmwidth;
  1343. * lpCurSh->cy = bitmap.bmHeight;
  1344. * lpCurSh->cbWidth = bitmap.bmWidthBytes;
  1345. * lpCurSh->Planes = bitmap.bmPlanes;
  1346. * lpCurSh->BitsPixel = bitmap.bmBitsPixel;
  1347. */
  1348. LCopyStruct((LPSTR)&(bitmap.bmWidth),
  1349. (LPSTR)&(lpCurSh->cx), (sizeof(WORD)) << 2);
  1350. /* Cursors in PM format have twice the actual height. */
  1351. if (fMono)
  1352. lpCurSh->cy = lpCurSh->cy >> 1;
  1353. wCount = bitmap.bmWidthBytes * bitmap.bmHeight * bitmap.bmPlanes;
  1354. lpBits = (LPSTR)(lpCurSh + 1);
  1355. /* Copy the bits in Bitmap into the resource */
  1356. GetBitmapBits(hBitmap, (DWORD)wCount, lpBits);
  1357. /* Delete the bitmap */
  1358. DeleteObject(hBitmap);
  1359. /* Before crunching, let us make sure we have a big enough resource */
  1360. if (wNewSize > wMemBlkSize)
  1361. {
  1362. GlobalUnlock(hRes);
  1363. /* Make this non discardable so that kernel will try to move this block
  1364. * when reallocing. DavidDS
  1365. */
  1366. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_NODISCARD);
  1367. if (!GlobalReAlloc(hRes, (DWORD)wNewSize, 0))
  1368. {
  1369. /* So it gets discarded. Note that since the above realloc is less
  1370. * than 64K, the handle won't change.
  1371. */
  1372. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_DISCARDABLE);
  1373. return(NULL);
  1374. }
  1375. GlobalReAlloc(hRes, 0L, GMEM_MODIFY | GMEM_DISCARDABLE);
  1376. if (!(lpCurSh = (LPCURSORSHAPE)GlobalLock(hRes)))
  1377. return(NULL);
  1378. wMemBlkSize = wNewSize;
  1379. }
  1380. wNewSize = CrunchAndResize(lpCurSh, fIcon, TRUE, !fMono, fStretchToSysMetrics);
  1381. if (!fMono)
  1382. {
  1383. if (!(wNewSize = StretchIcon(lpCurSh, wNewSize, hXORbitmap, fStretchToSysMetrics)))
  1384. {
  1385. GlobalUnlock(hRes);
  1386. return(NULL);
  1387. }
  1388. }
  1389. GlobalUnlock(hRes);
  1390. /* Does it need to be resized? */
  1391. if (wNewSize < wMemBlkSize)
  1392. {
  1393. if (!GlobalReAlloc(hRes, (DWORD)wNewSize, 0))
  1394. return(NULL);
  1395. }
  1396. return(hRes);
  1397. }
  1398. /*--------------------------------------------------------------------------*/
  1399. /* */
  1400. /* SizeReqd() - */
  1401. /* This returns the size of an Icon or Cursor after it is stretched */
  1402. /* or crunched */
  1403. /* */
  1404. /*--------------------------------------------------------------------------*/
  1405. WORD NEAR PASCAL SizeReqd(fIcon, BitCount, Planes, fUseSysMetrics, iWidth, iHeight)
  1406. BOOL fIcon;
  1407. WORD BitCount;
  1408. WORD Planes;
  1409. BOOL fUseSysMetrics;
  1410. int iWidth;
  1411. int iHeight;
  1412. {
  1413. WORD size;
  1414. dprintf(7,"SizeReqd");
  1415. if(fUseSysMetrics) //Use the dimensions in oemInfo; Else, use given dimensions
  1416. {
  1417. if(fIcon)
  1418. {
  1419. iWidth = oemInfo.cxIcon;
  1420. iHeight = oemInfo.cyIcon;
  1421. }
  1422. else
  1423. {
  1424. iWidth = oemInfo.cxCursor;
  1425. iHeight = oemInfo.cyCursor;
  1426. }
  1427. }
  1428. size = (((iWidth*BitCount+0x0F) & ~0x0F) >> 3) *
  1429. iHeight * Planes;
  1430. if ((BitCount == 1) && (Planes == 1))
  1431. size <<= 1;
  1432. else
  1433. size += (((iWidth+0x0F) & ~0x0F) >> 3)*iHeight;
  1434. return(size + sizeof(CURSORSHAPE));
  1435. }
  1436. #endif // NEEDED