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.

1160 lines
32 KiB

  1. //*****************************************************************************
  2. //
  3. // Cursor and Icon compatibility Support -
  4. //
  5. // Support for apps - which do a GlobalLock on Cursors and Icons to
  6. // create headaches for us.
  7. //
  8. // A compatibility issue.
  9. //
  10. //
  11. // 21-Apr-92 NanduriR Created.
  12. //
  13. //*****************************************************************************
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. MODNAME(wcuricon.c);
  17. extern void FreeAccelAliasEntry(LPACCELALIAS lpT);
  18. LPCURSORICONALIAS lpCIAlias = NULL;
  19. UINT cPendingCursorIconUpdates = 0;
  20. //*****************************************************************************
  21. //
  22. // W32CreateCursorIcon32 -
  23. //
  24. // Creates a 32bit Cursor or Icon given a WIN31 Cursor or Icon HANDLE.
  25. // The Cursor of Icon handle must correspond to an object that has
  26. // been created (like CreateIcon). That is because the format of a
  27. // resource cursor differs from that of a 'created' cursor.
  28. //
  29. // Returns the 32bit handle
  30. //
  31. //*****************************************************************************
  32. HANDLE W32CreateCursorIcon32(LPCURSORICONALIAS lpCIAliasIn)
  33. {
  34. HANDLE hT;
  35. PCURSORSHAPE16 pcurs16;
  36. UINT flType;
  37. int nWidth;
  38. int nHeight;
  39. int nPlanes;
  40. int nBitsPixel;
  41. DWORD nBytesAND;
  42. LPBYTE lpBitsAND;
  43. LPBYTE lpBitsXOR;
  44. int ScanLen16;
  45. pcurs16 = (PCURSORSHAPE16)lpCIAliasIn->pbDataNew;
  46. flType = lpCIAliasIn->flType;
  47. if (flType & HANDLE_TYPE_UNKNOWN) {
  48. if (PROBABLYCURSOR(FETCHWORD(pcurs16->BitsPixel),
  49. FETCHWORD(pcurs16->Planes)))
  50. flType = HANDLE_TYPE_CURSOR;
  51. else
  52. flType = HANDLE_TYPE_ICON;
  53. }
  54. nWidth = INT32(FETCHWORD(pcurs16->cx));
  55. nHeight = INT32(FETCHWORD(pcurs16->cy));
  56. nPlanes = 1;
  57. nBitsPixel = 1; // Monochrome
  58. // Get the AND mask bits
  59. ScanLen16 = (((nWidth*nBitsPixel)+15)/16) * 2 ; // bytes/scan in 16 bit world
  60. // effectively nBitsPixel is 1
  61. nBytesAND = ScanLen16*nHeight*nPlanes;
  62. lpBitsAND = (LPBYTE)pcurs16 + sizeof(CURSORSHAPE16);
  63. // Get the XOR mask bits
  64. if (flType == HANDLE_TYPE_ICON) {
  65. nPlanes = INT32(FETCHWORD(pcurs16->Planes));
  66. nBitsPixel = INT32(FETCHWORD(pcurs16->BitsPixel)); // the actual value
  67. }
  68. lpBitsXOR = (LPBYTE)lpBitsAND + nBytesAND;
  69. lpCIAliasIn->flType = (BYTE)flType;
  70. if (flType & HANDLE_TYPE_CURSOR) {
  71. hT = CreateCursor(HMODINST32(lpCIAliasIn->hInst16),
  72. (INT)FETCHWORD(pcurs16->xHotSpot),
  73. (INT)FETCHWORD(pcurs16->yHotSpot),
  74. nWidth, nHeight, lpBitsAND, lpBitsXOR);
  75. }
  76. else if (flType & HANDLE_TYPE_ICON) {
  77. hT = CreateIcon(HMODINST32(lpCIAliasIn->hInst16), nWidth, nHeight,
  78. (BYTE)nPlanes, (BYTE)nBitsPixel, lpBitsAND, lpBitsXOR);
  79. }
  80. return hT;
  81. }
  82. //*****************************************************************************
  83. //
  84. // W32Create16BitCursorIcon -
  85. //
  86. // Creates a WIN31 compatible Cursor or Icon given the full 16bit
  87. // definition of the object to be created.
  88. //
  89. //
  90. //*****************************************************************************
  91. HAND16 W32Create16BitCursorIcon(HAND16 hInst16, INT xHotSpot, INT yHotSpot,
  92. INT nWidth, INT nHeight,
  93. INT nPlanes, INT nBitsPixel,
  94. LPBYTE lpBitsAND, LPBYTE lpBitsXOR,
  95. INT nBytesAND, INT nBytesXOR )
  96. {
  97. WORD h16 = 0;
  98. WORD wTotalSize;
  99. PCURSORSHAPE16 pcshape16;
  100. VPVOID vp;
  101. LPBYTE lpT;
  102. UNREFERENCED_PARAMETER(hInst16);
  103. wTotalSize = (WORD)(sizeof(CURSORSHAPE16) + nBytesAND + nBytesXOR);
  104. vp = GlobalAllocLock16(GMEM_MOVEABLE | GMEM_ZEROINIT | GMEM_SHARE,
  105. wTotalSize, &h16);
  106. if (vp != (VPVOID)NULL) {
  107. GETVDMPTR(vp, wTotalSize, pcshape16);
  108. STOREWORD(pcshape16->xHotSpot, xHotSpot);
  109. STOREWORD(pcshape16->yHotSpot, yHotSpot);
  110. STOREWORD(pcshape16->cx, nWidth);
  111. STOREWORD(pcshape16->cy, nHeight);
  112. STOREWORD(pcshape16->cbWidth, (((nWidth + 0x0F) & ~0x0F) >> 3));
  113. pcshape16->Planes = (BYTE)nPlanes;
  114. pcshape16->BitsPixel = (BYTE)nBitsPixel;
  115. lpT = (LPBYTE)pcshape16 + sizeof(CURSORSHAPE16);
  116. RtlCopyMemory(lpT, lpBitsAND, nBytesAND);
  117. RtlCopyMemory(lpT+nBytesAND, lpBitsXOR, nBytesXOR);
  118. FLUSHVDMPTR(vp, wTotalSize, pcshape16);
  119. FREEVDMPTR(pcshape16);
  120. }
  121. GlobalUnlock16(h16);
  122. return (HAND16)h16;
  123. }
  124. //*****************************************************************************
  125. //
  126. // GetCursorIconAlias32 -
  127. //
  128. // Returns a 32bit handle given a 16bit Cursor or Icon HANDLE
  129. // Creates the 32bit Cursor or Icon if necessary.
  130. //
  131. // Returns the 32bit handle
  132. //
  133. //*****************************************************************************
  134. HANDLE GetCursorIconAlias32(HAND16 h16, UINT flType)
  135. {
  136. LPCURSORICONALIAS lpT;
  137. VPVOID vp;
  138. UINT cb;
  139. PCURSORSHAPE16 pcurs16;
  140. if (h16 == (HAND16)0)
  141. return (ULONG)NULL;
  142. lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
  143. if (lpT) {
  144. return lpT->h32;
  145. }
  146. else {
  147. //
  148. // BEGIN: Check for Bogus handle
  149. //
  150. if (BOGUSHANDLE(h16))
  151. return (HANDLE)NULL;
  152. #if defined(FE_SB)
  153. //In Excel95, XLVISEX.EXE use wrong cursor handle
  154. //that is already freed. So, we double check this handle
  155. //whether it is valid or not. 09/27/96 bklee.
  156. if (!FindCursorIconAliasInUse((ULONG)h16))
  157. return (HANDLE)NULL;
  158. #endif
  159. vp = RealLockResource16(h16, (PINT)&cb);
  160. if (vp == (VPVOID)NULL)
  161. return (ULONG)NULL;
  162. GETVDMPTR(vp, cb, pcurs16);
  163. if (pcurs16->cbWidth != (SHORT)(((pcurs16->cx + 0x0f) & ~0x0f) >> 3))
  164. return (ULONG)NULL;
  165. //
  166. // END: Check for Bogus handle
  167. //
  168. lpT = AllocCursorIconAlias();
  169. if (!lpT) {
  170. return (ULONG)NULL;
  171. }
  172. lpT->h16 = h16;
  173. lpT->hTask16 = CURRENTPTD()->htask16;
  174. lpT->vpData = vp;
  175. lpT->cbData = (WORD)cb;
  176. lpT->pbDataNew = (LPBYTE)pcurs16;
  177. lpT->pbDataOld = malloc_w(cb);
  178. if (lpT->pbDataOld) {
  179. RtlCopyMemory(lpT->pbDataOld, lpT->pbDataNew, cb);
  180. }
  181. lpT->h32 = (HAND32)W32CreateCursorIcon32(lpT);
  182. GlobalUnlock16(h16);
  183. FREEVDMPTR(pcurs16);
  184. lpT->pbDataNew = (LPBYTE)NULL;
  185. if (lpT->h32) {
  186. lpT->fInUse = TRUE;
  187. SetCursorIconFlag(h16, TRUE);
  188. }
  189. else
  190. lpT->fInUse = FALSE;
  191. return lpT->h32;
  192. }
  193. }
  194. //*****************************************************************************
  195. //
  196. // GetCursorIconAlias16 -
  197. //
  198. // Returns a 16bit handle given a 32bit Cursor or Icon HANDLE
  199. // Creates the 16bit Cursor or Icon if necessary.
  200. //
  201. // Returns the 16bit handle
  202. //
  203. //*****************************************************************************
  204. HAND16 GetCursorIconAlias16(HAND32 h32, UINT flType)
  205. {
  206. LPCURSORICONALIAS lpT;
  207. if (h32 == (HAND32)0)
  208. return (HAND16)NULL;
  209. lpT = FindCursorIconAlias((ULONG)h32, HANDLE_32BIT);
  210. if (lpT) {
  211. return lpT->h16;
  212. }
  213. else {
  214. HAND16 h16;
  215. // HACK:
  216. // From experience: numeric values of 32bit standard cursors and icons
  217. // are very small. so check for these handles.
  218. // we should not create aliases for standard cursors and
  219. // icons here.
  220. WOW32ASSERT((UINT)h32 >= 100);
  221. //
  222. // Always generate valid handles.
  223. //
  224. h16 = W32Create16BitCursorIconFrom32BitHandle(h32, (HAND16)NULL,
  225. (PUINT)NULL);
  226. if (h16) {
  227. h16 = SetupCursorIconAlias((HAND16)NULL, h32, h16, flType,
  228. NULL, (WORD)NULL);
  229. }
  230. return h16;
  231. }
  232. }
  233. //*****************************************************************************
  234. //
  235. // AllocCursorIconAlias -
  236. //
  237. // Allocates and reurns pointer to CURSORICONALIAS buffer.
  238. //
  239. //*****************************************************************************
  240. LPCURSORICONALIAS AllocCursorIconAlias()
  241. {
  242. LPCURSORICONALIAS lpT;
  243. for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
  244. if (!lpT->fInUse)
  245. break;
  246. }
  247. if (lpT == NULL) {
  248. lpT = (LPCURSORICONALIAS)malloc_w_small(sizeof(CURSORICONALIAS));
  249. if (lpT) {
  250. lpT->lpNext = lpCIAlias;
  251. lpCIAlias = lpT;
  252. }
  253. else {
  254. LOGDEBUG(0, ("AllocCursorIconAlias: malloc_w_small for alias failed\n"));
  255. }
  256. }
  257. if (lpT != NULL) {
  258. lpT->fInUse = TRUE;
  259. lpT->h16 = (HAND16)0;
  260. lpT->h32 = (HAND32)0;
  261. lpT->vpData = (VPVOID)NULL;
  262. lpT->cLock = 0;
  263. lpT->cbData = 0;
  264. lpT->pbDataOld = (LPBYTE)NULL;
  265. lpT->pbDataNew = (LPBYTE)NULL;
  266. lpT->lpszName = (LPBYTE)NULL;
  267. lpT->flType = HANDLE_TYPE_UNKNOWN;
  268. lpT->hInst16 = (HAND16)0;
  269. lpT->hMod16 = (HAND16)0;
  270. lpT->hTask16 = (HTASK16)0;
  271. lpT->hRes16 = 0;
  272. }
  273. return lpT;
  274. }
  275. //*****************************************************************************
  276. //
  277. // FindCursorIconAlias -
  278. //
  279. // Searches for the given handle and returns corresponding
  280. // LPCURSORICONALIAS.
  281. //
  282. //*****************************************************************************
  283. LPCURSORICONALIAS FindCursorIconAlias(ULONG hCI, UINT flHandleSize)
  284. {
  285. LPCURSORICONALIAS lpT;
  286. LPCURSORICONALIAS lpTprev;
  287. lpTprev = (LPCURSORICONALIAS)NULL;
  288. for (lpT = lpCIAlias; lpT != NULL; lpTprev = lpT, lpT = lpT->lpNext) {
  289. if (lpT->fInUse) {
  290. if ((flHandleSize == HANDLE_16BIT && lpT->h16 == (HAND16)hCI) ||
  291. (flHandleSize == HANDLE_32BIT && lpT->h32 == (HAND32)hCI))
  292. break;
  293. else if (flHandleSize == HANDLE_16BITRES && lpT->hRes16 &&
  294. (lpT->hRes16 == (HAND16)hCI))
  295. break;
  296. }
  297. }
  298. if (lpT) {
  299. if (lpTprev) {
  300. lpTprev->lpNext = lpT->lpNext;
  301. lpT->lpNext = lpCIAlias;
  302. lpCIAlias = lpT;
  303. }
  304. }
  305. return lpT;
  306. }
  307. #if defined(FE_SB)
  308. //*****************************************************************************
  309. //
  310. // FindCursorIconAliasInUse -
  311. //
  312. // Searches for the given handle and returns corresponding
  313. // lpT->fInUse.
  314. //
  315. // 09/27/96 bklee
  316. //*****************************************************************************
  317. BOOL FindCursorIconAliasInUse(ULONG hCI)
  318. {
  319. LPCURSORICONALIAS lpT;
  320. LPCURSORICONALIAS lpTprev;
  321. lpTprev = (LPCURSORICONALIAS)NULL;
  322. for (lpT = lpCIAlias; lpT != NULL; lpTprev = lpT, lpT = lpT->lpNext) {
  323. if (lpT->h16 == (HAND16)hCI)
  324. return lpT->fInUse;
  325. }
  326. return TRUE;
  327. }
  328. #endif
  329. //*****************************************************************************
  330. //
  331. // DeleteCursorIconAlias -
  332. //
  333. // Searches for the given handle and if a 16bit handle frees the memory
  334. // allocated for the Object. The alias table is not freed.
  335. //
  336. //*****************************************************************************
  337. BOOL DeleteCursorIconAlias(ULONG hCI, UINT flHandleSize)
  338. {
  339. LPCURSORICONALIAS lpT;
  340. WOW32ASSERT(flHandleSize == HANDLE_16BIT);
  341. for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
  342. if (lpT->fInUse && !(lpT->flType & HANDLE_TYPE_WOWGLOBAL)) {
  343. // Have we found the handle mapping?
  344. if (flHandleSize == HANDLE_16BIT && lpT->h16 == (HAND16)hCI) {
  345. if (lpT->hTask16) {
  346. // We don't want to free the handle mapping when
  347. // the handle corresponds to a 16-bit resource, i.e.
  348. // hRes16 is non-null.
  349. if (!(lpT->hRes16)) {
  350. SetCursorIconFlag(lpT->h16, FALSE);
  351. GlobalUnlockFree16(RealLockResource16((HMEM16)hCI, NULL));
  352. free_w(lpT->pbDataOld);
  353. lpT->fInUse = FALSE;
  354. return TRUE;
  355. }
  356. }
  357. else {
  358. WOW32ASSERT(FALSE);
  359. }
  360. break;
  361. }
  362. }
  363. }
  364. return FALSE;
  365. }
  366. //*****************************************************************************
  367. //
  368. // FreeCursorIconAlias -
  369. //
  370. // Frees all Cursors and Icons of the specified task.
  371. //
  372. //
  373. //*****************************************************************************
  374. BOOL FreeCursorIconAlias(HAND16 hand16, ULONG ulFlags)
  375. {
  376. LPCURSORICONALIAS lpT;
  377. for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
  378. if (lpT->fInUse &&
  379. (((ulFlags & CIALIAS_HMOD) && (lpT->hMod16 == hand16)) ||
  380. ((ulFlags & CIALIAS_HTASK) && (lpT->hTask16 == hand16)))) {
  381. if (ulFlags & CIALIAS_TASKISGONE) {
  382. // We're here if this function is called after the task
  383. // cleanup on the 16bit side... then we really can't
  384. // callback. Setting appropriate fields to NULL will
  385. // avoid callbacks, but will leak the corresponding
  386. // memory. The asserts will catch this on a checked
  387. // build.
  388. WOW32ASSERT(lpT->h16==(HAND16)NULL);
  389. WOW32ASSERT(lpT->hRes16==(HAND16)NULL);
  390. lpT->h16 = (HAND16)NULL;
  391. lpT->hRes16 = (HAND16)NULL;
  392. }
  393. InvalidateCursorIconAlias(lpT);
  394. }
  395. }
  396. return TRUE;
  397. }
  398. //*****************************************************************************
  399. //
  400. // SetupCursorIconAlias -
  401. //
  402. // Sets up association (alias) between a 32bit and a 16bit handle.
  403. // given both the handles.
  404. //
  405. //
  406. //*****************************************************************************
  407. HAND16 SetupCursorIconAlias(HAND16 hInst16, HAND32 h32, HAND16 h16, UINT flType,
  408. LPBYTE lpResName, WORD hRes16)
  409. {
  410. LPCURSORICONALIAS lpT;
  411. VPVOID vp;
  412. INT cb;
  413. lpT = AllocCursorIconAlias();
  414. // paranoid check for memory exaust
  415. if (!lpT) {
  416. return (HAND16)NULL;
  417. }
  418. lpT->fInUse = TRUE;
  419. lpT->h16 = h16;
  420. lpT->h32 = h32;
  421. lpT->flType = (BYTE)flType;
  422. if (!(flType & HANDLE_TYPE_WOWGLOBAL)) {
  423. lpT->hInst16 = hInst16;
  424. lpT->hMod16 = GETHMOD16(HMODINST32(hInst16));
  425. lpT->hTask16 = CURRENTPTD()->htask16;
  426. lpT->hRes16 = hRes16;
  427. vp = RealLockResource16(h16, &cb);
  428. if (vp == (VPVOID)NULL)
  429. return (HAND16)NULL;
  430. lpT->vpData = vp;
  431. lpT->cbData = (WORD)cb;
  432. GETVDMPTR(vp, cb, lpT->pbDataNew);
  433. lpT->pbDataOld = malloc_w(cb);
  434. if (lpT->pbDataOld) {
  435. RtlCopyMemory(lpT->pbDataOld, lpT->pbDataNew, cb);
  436. }
  437. if (hRes16) {
  438. lpT->lpszName = lpResName;
  439. if ((WORD)HIWORD(lpResName) != (WORD)NULL) {
  440. UINT cb;
  441. cb = strlen(lpResName)+1;
  442. if (lpT->lpszName = malloc_w_small(cb)) {
  443. memcpy (lpT->lpszName, lpResName, cb);
  444. }
  445. }
  446. }
  447. }
  448. // the alias has been setup. Now turn on the GAH_CURSORICON flag.
  449. SetCursorIconFlag(h16, TRUE);
  450. return h16;
  451. }
  452. //*****************************************************************************
  453. //
  454. // SetupResCursorIconAlias -
  455. //
  456. // Sets up association (alias) between a 32bit and a 16bit handle.
  457. // given the 32bit handle and a handle to a 16bit resource.
  458. //
  459. //
  460. //*****************************************************************************
  461. HAND16 SetupResCursorIconAlias(HAND16 hInst16, HAND32 h32, LPBYTE lpResName, WORD hRes16, UINT flType)
  462. {
  463. LPCURSORICONALIAS lpT;
  464. HAND16 h16 = 0;
  465. HAND16 h16Res = 0;
  466. UINT cb;
  467. if (hRes16) {
  468. // 16bit resource has been loaded. We always want to return the
  469. // SAME 16bit handle no matter howmany times the 'LoadIcon' or
  470. // LoadCursor has been called.
  471. h16Res = LOWORD(hRes16);
  472. lpT = FindCursorIconAlias(h16Res, HANDLE_16BITRES);
  473. }
  474. else {
  475. // Resource handle is NULL. The Resource must have been a
  476. // standard predefined resource like ARROW etc.
  477. lpT = FindCursorIconAlias((ULONG)h32, HANDLE_32BIT);
  478. flType |= HANDLE_TYPE_WOWGLOBAL;
  479. }
  480. if (lpT == NULL) {
  481. h16 = W32Create16BitCursorIconFrom32BitHandle(h32, hInst16, &cb);
  482. h16 = SetupCursorIconAlias(hInst16, h32, h16, flType, lpResName, hRes16);
  483. }
  484. else {
  485. if (lpT->flType & HANDLE_TYPE_WOWGLOBAL) {
  486. // eachtime we should get the same h32 from usersrv.
  487. //
  488. WOW32ASSERT(lpT->h32 == h32);
  489. }
  490. else {
  491. if (lpT->h32 != h32) {
  492. if (lpT->flType == HANDLE_TYPE_CURSOR)
  493. DestroyCursor(h32);
  494. else
  495. DestroyIcon(h32);
  496. }
  497. ReplaceCursorIcon(lpT);
  498. }
  499. h16 = lpT->h16;
  500. }
  501. return h16;
  502. }
  503. //*****************************************************************************
  504. //
  505. // SetCursorIconFlag -
  506. //
  507. // Sets/Clears the GAH_CURSORICONFLAG in the global arean header. This flag
  508. // is used to identify Cursors and Icon when they are GlobaLocked and
  509. // GlobalUnlocked
  510. //
  511. //*****************************************************************************
  512. ULONG SetCursorIconFlag(HAND16 h16, BOOL fSet)
  513. {
  514. PARM16 Parm16;
  515. VPVOID vp = 0;
  516. Parm16.WndProc.wParam = h16;
  517. Parm16.WndProc.wMsg = (WORD)fSet;
  518. CallBack16(RET_SETCURSORICONFLAG, &Parm16, 0, &vp);
  519. return (ULONG)0;
  520. }
  521. //*****************************************************************************
  522. //
  523. // UpdateCursorIcon -
  524. //
  525. // Compares the new object data with the old. If any of the bytes differ
  526. // the old object is replaced with the new.
  527. //
  528. //*****************************************************************************
  529. VOID UpdateCursorIcon()
  530. {
  531. LPCURSORICONALIAS lpT;
  532. UINT cbData;
  533. LPBYTE lpBitsNew, lpBitsOld;
  534. UINT i = 0;
  535. for (lpT = lpCIAlias; lpT != NULL ; lpT = lpT->lpNext) {
  536. if (lpT->fInUse && lpT->cLock) {
  537. GETVDMPTR(lpT->vpData, lpT->cbData, lpT->pbDataNew);
  538. if (lpT->hRes16) {
  539. if (lpT->flType == HANDLE_TYPE_ICON) {
  540. lpBitsNew = lpT->pbDataNew + sizeof(BITMAPINFOHEADER16);
  541. lpBitsOld = lpT->pbDataOld + sizeof(BITMAPINFOHEADER16);
  542. cbData = lpT->cbData - sizeof(BITMAPINFOHEADER16);
  543. }
  544. else {
  545. lpBitsNew = lpT->pbDataNew + sizeof(CURSORRESOURCE16);
  546. lpBitsOld = lpT->pbDataOld + sizeof(CURSORRESOURCE16);
  547. cbData = lpT->cbData - sizeof(CURSORRESOURCE16);
  548. }
  549. }
  550. else {
  551. lpBitsNew = lpT->pbDataNew + sizeof(CURSORSHAPE16);
  552. lpBitsOld = lpT->pbDataOld + sizeof(CURSORSHAPE16);
  553. cbData = lpT->cbData - sizeof(CURSORSHAPE16);
  554. }
  555. if (! RtlEqualMemory(lpBitsNew, lpBitsOld, cbData))
  556. ReplaceCursorIcon(lpT);
  557. if (cPendingCursorIconUpdates == ++i)
  558. break;
  559. }
  560. }
  561. }
  562. //*****************************************************************************
  563. //
  564. // ReplaceCursorIcon -
  565. //
  566. // Updates the current cursor or icon. Creates a new icon or cursor and
  567. // replaces the contents of the old handle with that of the new.
  568. //
  569. // returns TRUE for success.
  570. //
  571. //*****************************************************************************
  572. BOOL ReplaceCursorIcon(LPCURSORICONALIAS lpIn)
  573. {
  574. HANDLE hT32;
  575. if (lpIn != NULL) {
  576. // Get the data
  577. GETVDMPTR(lpIn->vpData, lpIn->cbData, lpIn->pbDataNew);
  578. // Create the object
  579. hT32 = (HAND32)W32CreateCursorIcon32(lpIn);
  580. // SetCursorConents will replace the contents of OLD cursor/icon
  581. // with that of the new handle and destroy the new handle
  582. SetCursorContents(lpIn->h32, hT32);
  583. // replace the old object data with the new
  584. RtlCopyMemory(lpIn->pbDataOld, lpIn->pbDataNew, lpIn->cbData);
  585. FREEVDMPTR(lpIn->pbDataNew);
  586. lpIn->pbDataNew = (LPBYTE)NULL;
  587. }
  588. return (BOOL)TRUE;
  589. }
  590. //*****************************************************************************
  591. //
  592. // WK32WowCursorIconOp -
  593. //
  594. // Gets called when/from GlobalLock or GlobalUnlock are called. The fLock
  595. // flag is TRUE if called from GlobalLock else it is FALSE.
  596. //
  597. //*****************************************************************************
  598. BOOL FASTCALL WK32WowCursorIconOp(PVDMFRAME pFrame)
  599. {
  600. PWOWCURSORICONOP16 prci16;
  601. HAND16 h16;
  602. LPCURSORICONALIAS lpT;
  603. BOOL fLock;
  604. WORD wFuncId;
  605. UINT cLockT;
  606. GETARGPTR(pFrame, sizeof(WOWCURSORICONOP16), prci16);
  607. wFuncId = FETCHWORD(prci16->wFuncId);
  608. h16 = (HAND16)FETCHWORD(prci16->h16);
  609. lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
  610. // This is a Cursor or Icon
  611. if (lpT != NULL) {
  612. if (wFuncId == FUN_GLOBALLOCK || wFuncId == FUN_GLOBALUNLOCK) {
  613. if (!(lpT->flType & HANDLE_TYPE_WOWGLOBAL)) {
  614. fLock = (wFuncId == FUN_GLOBALLOCK);
  615. // Store the current lockcount.
  616. cLockT = lpT->cLock;
  617. // Update the Lock count
  618. lpT->cLock = fLock ? ++lpT->cLock : --lpT->cLock;
  619. if (lpT->cLock == 0) {
  620. // New lock count == 0 implies that it was decremented from
  621. // 1 to 0 thereby impling that it was one of the cursors that
  622. // was being updated regularly.
  623. // Decrement the global count and update the cursor one last
  624. // time
  625. cPendingCursorIconUpdates--;
  626. ReplaceCursorIcon(lpT);
  627. }
  628. else if (fLock && cLockT == 0) {
  629. // If previous Lockcount was zero and the object is being locked
  630. // then it means that this is the very first time that the object
  631. // is being locked
  632. cPendingCursorIconUpdates++;
  633. }
  634. }
  635. }
  636. else if (wFuncId == FUN_GLOBALFREE) {
  637. // The h16 has not yet been GlobalFreed. We return TRUE if h16 can
  638. // be freed else FALSE. The h16 can be freed only if it is not a
  639. // global handle. ie, it doesn't correspond to a predefined cursor
  640. // Also we donot free the handle if h16 corresponds to a resource.
  641. // CorelDraw 3.0 calls FreeResource(h16) and then SetCursor(h16)
  642. // thus GPing.
  643. BOOL fFree;
  644. fFree = !((lpT->flType & HANDLE_TYPE_WOWGLOBAL) || lpT->hRes16);
  645. if (fFree) {
  646. // Set handle to NULL so that InvalidateCursorIconAlias
  647. // doesn't try to free it.
  648. lpT->h16 = 0;
  649. InvalidateCursorIconAlias(lpT);
  650. }
  651. return (BOOL)fFree;
  652. }
  653. else {
  654. LOGDEBUG(0, ("WK32WowCursorIconOp: Unknown Func Id\n"));
  655. }
  656. }
  657. // else if this is a GlobalFree call
  658. else if (wFuncId == FUN_GLOBALFREE) {
  659. // and if this is a handle to an accelerator
  660. if(lpT = (LPCURSORICONALIAS)FindAccelAlias((HANDLE)h16, HANDLE_16BIT)) {
  661. // free it from the accelerator alias list
  662. FreeAccelAliasEntry((LPACCELALIAS) lpT);
  663. // cause this hMem16 to really be free'd in 16-bit GlobalFree
  664. return TRUE;
  665. }
  666. }
  667. return TRUE;
  668. }
  669. //*****************************************************************************
  670. //
  671. // W32Create16BitResCursorIconFrom32BitHandle -
  672. //
  673. // Creates a WIN31 compatible Cursor or Icon given a 32bit cursor or icon
  674. // handle. This is primarily used to create a 16bit Cursor or Icon which
  675. // has been loaded from a 16bit resource.
  676. //
  677. //
  678. // returns 16bit handle
  679. //*****************************************************************************
  680. HAND16 W32Create16BitCursorIconFrom32BitHandle(HANDLE h32, HAND16 hInst16,
  681. PUINT pcbData)
  682. {
  683. HAND16 h16 = 0;
  684. ICONINFO iinfo;
  685. BITMAP bm;
  686. BITMAP bmClr;
  687. UINT nBytesAND = 0;
  688. UINT nBytesXOR = 0;
  689. LPBYTE lpBitsAND, lpBitsXOR;
  690. if (GetIconInfo(h32, &iinfo)) {
  691. if (GetObject(iinfo.hbmMask, sizeof(BITMAP), &bm)) {
  692. nBytesAND = GetBitmapBits(iinfo.hbmMask, 0, (LPBYTE)NULL);
  693. WOW32WARNMSG(nBytesAND,("WOW: W32C16BCIFBH: nBytesAND == 0\n"));
  694. if (iinfo.hbmColor) {
  695. GetObject(iinfo.hbmColor, sizeof(BITMAP), &bmClr);
  696. nBytesXOR = GetBitmapBits(iinfo.hbmColor, 0, (LPBYTE)NULL);
  697. WOW32WARNMSG(nBytesXOR,("WOW: W32C16BCIFBH: nBytesAND == 0\n"));
  698. }
  699. else {
  700. bm.bmHeight /= 2;
  701. nBytesAND /= 2;
  702. nBytesXOR = nBytesAND;
  703. }
  704. if (pcbData) {
  705. *pcbData = nBytesAND + nBytesXOR + sizeof(CURSORSHAPE16);
  706. }
  707. lpBitsAND = malloc_w(nBytesAND + nBytesXOR);
  708. if (lpBitsAND != NULL) {
  709. lpBitsXOR = lpBitsAND + nBytesAND;
  710. GetBitmapBits(iinfo.hbmMask,
  711. (iinfo.hbmColor) ? nBytesAND : (nBytesAND * 2),
  712. lpBitsAND);
  713. if (iinfo.hbmColor)
  714. GetBitmapBits(iinfo.hbmColor, nBytesXOR, lpBitsXOR);
  715. h16 = W32Create16BitCursorIcon(hInst16,
  716. iinfo.xHotspot, iinfo.yHotspot,
  717. bm.bmWidth, bm.bmHeight,
  718. (iinfo.hbmColor) ? bmClr.bmPlanes :
  719. bm.bmPlanes,
  720. (iinfo.hbmColor) ? bmClr.bmBitsPixel :
  721. bm.bmBitsPixel,
  722. lpBitsAND, lpBitsXOR,
  723. (INT)nBytesAND, (INT)nBytesXOR);
  724. free_w(lpBitsAND);
  725. }
  726. }
  727. DeleteObject(iinfo.hbmMask);
  728. if (iinfo.hbmColor) {
  729. DeleteObject(iinfo.hbmColor);
  730. }
  731. }
  732. return h16;
  733. }
  734. //*****************************************************************************
  735. //
  736. // GetClassCursorIconAlias32 -
  737. //
  738. // Returns a 32bit handle given a 16bit Cursor or Icon HANDLE
  739. // DOES NOT Create the 32bit Cursor or Icon if there is no alias.
  740. // This is called in RegisterClass only - to support those apps which
  741. // pass a bogus handle for WNDCLASS.hIcon.
  742. //
  743. // Returns the 32bit handle
  744. //
  745. //*****************************************************************************
  746. HANDLE GetClassCursorIconAlias32(HAND16 h16)
  747. {
  748. LPCURSORICONALIAS lpT;
  749. if (h16 == (HAND16)0)
  750. return (ULONG)NULL;
  751. lpT = FindCursorIconAlias((ULONG)h16, HANDLE_16BIT);
  752. if (lpT) {
  753. return lpT->h32;
  754. }
  755. else
  756. return (HANDLE)NULL;
  757. }
  758. //*****************************************************************************
  759. //
  760. // InvalidateCursorIconAlias -
  761. //
  762. // Frees the allocated objects.
  763. //
  764. //*****************************************************************************
  765. VOID InvalidateCursorIconAlias(LPCURSORICONALIAS lpT)
  766. {
  767. VPVOID vp=0;
  768. PARM16 Parm16;
  769. if (!lpT->fInUse)
  770. return;
  771. if (lpT->h16) {
  772. SetCursorIconFlag(lpT->h16, FALSE);
  773. GlobalUnlockFree16(RealLockResource16((HMEM16)lpT->h16, NULL));
  774. }
  775. if (lpT->hRes16) {
  776. Parm16.WndProc.wParam = (HAND16) lpT->hRes16;
  777. CallBack16(RET_FREERESOURCE, &Parm16, 0, &vp);
  778. }
  779. if (lpT->h32) {
  780. if (lpT->flType == HANDLE_TYPE_CURSOR)
  781. DestroyCursor(lpT->h32);
  782. else
  783. DestroyIcon(lpT->h32);
  784. }
  785. if (lpT->pbDataOld)
  786. free_w(lpT->pbDataOld);
  787. if (lpT->cLock)
  788. cPendingCursorIconUpdates--;
  789. if ((WORD)HIWORD(lpT->lpszName) != (WORD)NULL) {
  790. free_w_small ((PVOID)lpT->lpszName);
  791. }
  792. lpT->fInUse = FALSE;
  793. }
  794. //*****************************************************************************
  795. //
  796. // InitStdCursorIconAlias -
  797. //
  798. // Creates the aliases of standard cursors and icons.
  799. //
  800. // NOTES:
  801. //
  802. // The idea is to createaliases for all the standard cursors and icons to
  803. // make sure that we indeed generate valid handles.
  804. //
  805. // This problem cameup because of the following scenario
  806. // the app turbotax does the following:
  807. //
  808. // h16Cursor1 = GetClassWord(hwndEditControl, GCL_HCURSOR);
  809. // (bydefault, this is an I-beam)
  810. // .....
  811. // h16Cursor2 = LoadCursor(NULL, IDC_IBEAM);
  812. // Because of the way we create and maintain our 32-16 alias hCursor1 is a
  813. // a WOW bogus handle (ie > 0xf000) and since by default the "Edit" class is
  814. // registered with hCursor = IDC_IBEAM, the h32s are same ie.
  815. //
  816. // GetClassWord(hwndEditControl, GCL_HCURSOR) == LoadCursor(..IDC_IBEAM);
  817. //
  818. // Thus h16Cursor2 will be same as h16Cursor1 and that's a problem because we
  819. // are NOT returning a valid wow handle for a predefined cursor.
  820. //
  821. //
  822. // The solution is to createaliases for all standard cursors and icons during
  823. // init time so that we don't run into this problem. However I think this
  824. // approach as wasteful and am creating the alias for the only known case
  825. // ie IDC_IBEAM.
  826. //
  827. // - Nanduri Ramakrishna
  828. //*****************************************************************************
  829. DWORD InitCursorIds[] = {
  830. (DWORD)IDC_ARROW,
  831. (DWORD)IDC_IBEAM,
  832. (DWORD)IDC_WAIT,
  833. (DWORD)IDC_CROSS,
  834. (DWORD)IDC_UPARROW,
  835. (DWORD)IDC_SIZE,
  836. (DWORD)IDC_ICON,
  837. (DWORD)IDC_SIZENWSE,
  838. (DWORD)IDC_SIZENESW,
  839. (DWORD)IDC_SIZEWE,
  840. (DWORD)IDC_SIZENS
  841. };
  842. BOOL InitStdCursorIconAlias()
  843. {
  844. HCURSOR h32;
  845. UINT i;
  846. for (i = 0; i < (sizeof(InitCursorIds) / sizeof(DWORD)); i++) {
  847. //
  848. // Create the alias for each standard cursor in the list
  849. //
  850. h32 = (HCURSOR)LoadCursor((HINSTANCE)NULL, (LPCSTR)InitCursorIds[i]);
  851. WOW32ASSERT(h32);
  852. if (h32) {
  853. SetupResCursorIconAlias((HAND16)NULL, (HAND32)h32, NULL, (WORD)NULL,
  854. HANDLE_TYPE_CURSOR);
  855. }
  856. }
  857. //
  858. // Add similar lines for standard icons.
  859. //
  860. return TRUE;
  861. }
  862. //*****************************************************************************
  863. //
  864. // W32CheckIfAlreadyLoaded -
  865. //
  866. // returns h16 if a cursoricon has previously been loaded.
  867. //
  868. //*****************************************************************************
  869. HAND16 W32CheckIfAlreadyLoaded(VPVOID pData, WORD ResType)
  870. {
  871. LPCURSORICONALIAS lpT;
  872. PICONCUR16 parg16;
  873. PSZ psz;
  874. GETMISCPTR(pData, parg16);
  875. GETPSZIDPTR(parg16->lpStr, psz);
  876. ResType = (ResType == NW_LOADCURSOR) ? HANDLE_TYPE_CURSOR : HANDLE_TYPE_ICON;
  877. for (lpT = lpCIAlias; lpT != NULL; lpT = lpT->lpNext) {
  878. if (lpT->fInUse) {
  879. LPBYTE lpszNameT = lpT->lpszName;
  880. if (lpszNameT && (lpT->flType & ResType) &&
  881. lpT->hInst16 == parg16->hInst) {
  882. WOW32ASSERT(!(lpT->flType & HANDLE_TYPE_WOWGLOBAL));
  883. if (HIWORD(lpszNameT) && HIWORD(psz)) {
  884. if (!(WOW32_stricmp(psz, (LPSTR)lpszNameT)))
  885. break;
  886. }
  887. else if (lpszNameT == psz) {
  888. break;
  889. }
  890. }
  891. }
  892. }
  893. FREEPSZIDPTR(psz);
  894. FREEMISCPTR(parg16);
  895. if (lpT && lpT->cLock)
  896. ReplaceCursorIcon(lpT);
  897. return (lpT ? lpT->h16 : 0);
  898. }