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.

412 lines
11 KiB

  1. //*****************************************************************************
  2. //
  3. // LoadAccelerator - compatibility support.
  4. // So much code for such a thing.
  5. //
  6. // 23-Jul-92 NanduriR Created.
  7. //*****************************************************************************
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. MODNAME(waccel.c);
  11. extern ULONG SetCursorIconFlag(HAND16 hAccel16, BOOL bFlag);
  12. LPACCELALIAS lpAccelAlias = NULL;
  13. //*****************************************************************************
  14. // WU32LoadAccelerators -
  15. // This gets called from WU32NotifyWow. I use the familiar name WU32...
  16. // because this gets called indirectly in response to LoadAccelerator
  17. //
  18. // returs TRUE for success.
  19. //*****************************************************************************
  20. ULONG FASTCALL WU32LoadAccelerators(VPVOID vpData)
  21. {
  22. PLOADACCEL16 ploadaccel16;
  23. HACCEL hAccel;
  24. BOOL fReturn = (BOOL)FALSE;
  25. GETVDMPTR(vpData, sizeof(LOADACCEL16), ploadaccel16);
  26. if (FindAccelAlias((HANDLE)FETCHWORD(ploadaccel16->hAccel),
  27. HANDLE_16BIT)) {
  28. LOGDEBUG(0, ("AccelAlias already exists\n"));
  29. return (ULONG)TRUE;
  30. }
  31. if (hAccel = CreateAccel32(ploadaccel16->pAccel, ploadaccel16->cbAccel)) {
  32. fReturn = (BOOL)SetupAccelAlias(FETCHWORD(ploadaccel16->hInst),
  33. FETCHWORD(ploadaccel16->hAccel),
  34. hAccel, TRUE);
  35. }
  36. FREEVDMPTR(ploadaccel16);
  37. return (ULONG)fReturn;
  38. }
  39. //*****************************************************************************
  40. // SetupAccelAlias -
  41. // sets up the alias. the alias list is doubly linked. nothing fancy.
  42. //
  43. // returns pointer to the alias.
  44. //*****************************************************************************
  45. LPACCELALIAS SetupAccelAlias(
  46. HAND16 hInstance,
  47. HAND16 hAccel16,
  48. HAND32 hAccel32,
  49. BOOL f16
  50. ) {
  51. LPACCELALIAS lpT;
  52. WORD hTask16;
  53. hTask16 = CURRENTPTD()->htask16;
  54. lpT = FindAccelAlias((HANDLE)hAccel16, HANDLE_16BIT);
  55. if (lpT == (LPACCELALIAS)NULL) {
  56. lpT = malloc_w_small(sizeof(ACCELALIAS));
  57. if (lpT) {
  58. lpT->lpNext = lpAccelAlias;
  59. lpT->lpPrev = (LPACCELALIAS)NULL;
  60. if (lpAccelAlias)
  61. lpAccelAlias->lpPrev = lpT;
  62. lpAccelAlias = lpT;
  63. }
  64. }
  65. else {
  66. LOGDEBUG(0, ("SetupAccelAlias: Alias Already exists. how & why?\n"));
  67. WOW32ASSERT(FALSE);
  68. }
  69. if (lpT) {
  70. lpT->hInst = hInstance;
  71. lpT->hTask16 = CURRENTPTD()->htask16;
  72. lpT->h16 = hAccel16;
  73. lpT->h32 = hAccel32;
  74. lpT->f16 = (WORD)f16;
  75. // mark this so we can remove it from the alias list when
  76. // FreeResource() (in user.exe) calls GlobalFree() (in krnl386)
  77. SetCursorIconFlag(hAccel16, TRUE);
  78. }
  79. else {
  80. WOW32ASSERT(FALSE);
  81. }
  82. return (LPACCELALIAS)lpT;
  83. }
  84. //*****************************************************************************
  85. // DestroyAccelAlias -
  86. // Deletes the 32bit table and Frees the memory
  87. //
  88. // returns TRUE for success
  89. //*****************************************************************************
  90. BOOL DestroyAccelAlias(WORD hTask16)
  91. {
  92. WORD hCurTask16;
  93. LPACCELALIAS lpT;
  94. LPACCELALIAS lpTFree;
  95. hCurTask16 = CURRENTPTD()->htask16;
  96. lpT = lpAccelAlias;
  97. while (lpT) {
  98. if (lpT->hTask16 == hCurTask16) {
  99. if (lpT->lpPrev)
  100. lpT->lpPrev->lpNext = lpT->lpNext;
  101. if (lpT->lpNext)
  102. lpT->lpNext->lpPrev = lpT->lpPrev;
  103. if ( lpT->f16 ) {
  104. DestroyAcceleratorTable(lpT->h32);
  105. } else {
  106. // this function - DestroyAccelAlias- gets called during
  107. // taskexit time and the 16bit task cleanup code has already
  108. // freed this memory handle. so this callback is not needed.
  109. // - nanduri
  110. // WOWGlobalFree16( lpT->h16 );
  111. }
  112. lpTFree = lpT;
  113. lpT = lpT->lpNext;
  114. if (lpTFree == lpAccelAlias)
  115. lpAccelAlias = lpT;
  116. free_w_small(lpTFree);
  117. }
  118. else
  119. lpT = lpT->lpNext;
  120. }
  121. return TRUE;
  122. }
  123. //*****************************************************************************
  124. // FindAccelAlias -
  125. // maps 16 bit handle to 32bit handle and vice versa
  126. //
  127. // returns TRUE for success
  128. //*****************************************************************************
  129. LPACCELALIAS FindAccelAlias(HANDLE hAccel, UINT fSize)
  130. {
  131. WORD hCurTask16;
  132. LPACCELALIAS lpT;
  133. hCurTask16 = CURRENTPTD()->htask16;
  134. lpT = lpAccelAlias;
  135. while (lpT) {
  136. if (lpT->hTask16 == hCurTask16) {
  137. if (fSize & HANDLE_16BIT) {
  138. if (lpT->h16 == (HAND16)hAccel)
  139. return lpT;
  140. }
  141. else {
  142. if (lpT->h32 == (HAND32)hAccel)
  143. return lpT;
  144. }
  145. }
  146. lpT = lpT->lpNext;
  147. }
  148. return NULL;
  149. }
  150. //*****************************************************************************
  151. // GetAccelHandle32 -
  152. // Returns h32, given h16.
  153. //
  154. //*****************************************************************************
  155. HAND32 GetAccelHandle32(HAND16 h16)
  156. {
  157. LPACCELALIAS lpT;
  158. if (!(lpT = FindAccelAlias((HANDLE)(h16), HANDLE_16BIT))) {
  159. DWORD cbAccel16;
  160. VPVOID vpAccel16;
  161. HACCEL hAccel;
  162. if (vpAccel16 = RealLockResource16(h16, &cbAccel16)) {
  163. if (hAccel = CreateAccel32(vpAccel16, cbAccel16)) {
  164. lpT = SetupAccelAlias(CURRENTPTD()->hInst16, h16, hAccel, TRUE);
  165. }
  166. GlobalUnlock16(h16);
  167. }
  168. }
  169. return (lpT) ? lpT->h32 : (HAND32)NULL;
  170. }
  171. //*****************************************************************************
  172. // GetAccelHandle16 -
  173. // Returns h16, given h32.
  174. //
  175. //*****************************************************************************
  176. HAND16 GetAccelHandle16(HAND32 h32)
  177. {
  178. LPACCELALIAS lpT;
  179. HAND16 hAccel16;
  180. if (!(lpT = FindAccelAlias((HANDLE)(h32), HANDLE_32BIT))) {
  181. //
  182. // There isn't a corresponding 16-bit accelerator table handle already
  183. // so create one.
  184. //
  185. if ( (hAccel16 = CreateAccel16(h32)) != 0 ) {
  186. lpT = SetupAccelAlias(CURRENTPTD()->hInst16, hAccel16, h32, FALSE );
  187. }
  188. }
  189. return (lpT) ? lpT->h16 : (HAND16)NULL;
  190. }
  191. //*****************************************************************************
  192. // CreateAccel32 -
  193. // This gets called from WU32NotifyWow.
  194. //
  195. // returs TRUE for success.
  196. //*****************************************************************************
  197. HACCEL CreateAccel32(VPVOID vpAccel16, DWORD cbAccel16)
  198. {
  199. PSZ pAccel16;
  200. DWORD nElem16;
  201. LPACCEL lpAccel;
  202. HACCEL hAccel = (HACCEL)NULL;
  203. UINT i;
  204. #if DBG
  205. UINT LastKeyIndex = 0xffffffff;
  206. #endif
  207. //
  208. // pAccel16 is pointer to an array of records of length:
  209. // (BYTE+WORD+WORD)
  210. //
  211. GETVDMPTR(vpAccel16 , cbAccel16, pAccel16);
  212. if (pAccel16) {
  213. //
  214. // convert the 16bit accel table to 32bit format and create it.
  215. //
  216. nElem16 = cbAccel16 / (sizeof(BYTE) + 2 * sizeof(WORD));
  217. lpAccel = (LPACCEL)malloc_w(nElem16 * sizeof(ACCEL));
  218. if (lpAccel) {
  219. for (i=0; i<nElem16; ++i) {
  220. lpAccel[i].fVirt = *(LPBYTE)(pAccel16);
  221. #if DBG
  222. if ((lpAccel[i].fVirt & 0x80) && i < LastKeyIndex) {
  223. LastKeyIndex = i;
  224. }
  225. #endif
  226. ((LPBYTE)pAccel16)++;
  227. lpAccel[i].key = FETCHWORD(*(LPWORD)pAccel16);
  228. ((LPWORD)pAccel16)++;
  229. lpAccel[i].cmd = FETCHWORD(*(LPWORD)pAccel16);
  230. ((LPWORD)pAccel16)++;
  231. }
  232. #if DBG
  233. if (LastKeyIndex == 0xffffffff) {
  234. LOGDEBUG(LOG_ALWAYS, ("WOW::CreateAccel32 : no LastKey found in 16-bit haccel\n"));
  235. } else if (LastKeyIndex < nElem16-1) {
  236. LOGDEBUG(LOG_ALWAYS, ("WOW::CreateAccel32 : bogus LastKey flags ignored in 16-bit haccel\n"));
  237. }
  238. #endif
  239. hAccel = CreateAcceleratorTable(lpAccel, i);
  240. free_w(lpAccel);
  241. }
  242. FREEVDMPTR(pAccel16);
  243. }
  244. return hAccel;
  245. }
  246. //*****************************************************************************
  247. // CreateAccel16 -
  248. // This gets called from WU32NotifyWow.
  249. //
  250. // returns HACCEL16 for success.
  251. //*****************************************************************************
  252. HAND16 CreateAccel16(HACCEL hAccel32)
  253. {
  254. UINT iEntries;
  255. UINT cbSize;
  256. LPACCEL lpAccel32;
  257. HAND16 hAccel16;
  258. VPVOID vpAccel16;
  259. LPBYTE lpAccel16;
  260. LPBYTE lpAccel16Original;
  261. UINT i;
  262. iEntries = CopyAcceleratorTable( hAccel32, NULL, 0 );
  263. if ( iEntries == 0 ) { // Invalid hAccel32
  264. return( 0 );
  265. }
  266. lpAccel32 = (LPACCEL)malloc_w(iEntries * sizeof(ACCEL));
  267. if ( lpAccel32 == NULL ) {
  268. LOGDEBUG(LOG_ERROR, ("WOW::CreateAccel16 : Failed to alloc memory for 32-bit accel\n"));
  269. return( 0 );
  270. }
  271. iEntries = CopyAcceleratorTable( hAccel32, lpAccel32, iEntries );
  272. cbSize = iEntries * (sizeof(BYTE) + 2 * sizeof(WORD));
  273. vpAccel16 = GlobalAllocLock16( GMEM_MOVEABLE, cbSize, &hAccel16 );
  274. if ( vpAccel16 == 0 ) { // Out of 16-bit memory
  275. LOGDEBUG(LOG_ERROR, ("WOW::CreateAccel16 : Failed to alloc memory for 16-bit haccel\n"));
  276. free_w( lpAccel32 );
  277. return( 0 );
  278. }
  279. GETVDMPTR(vpAccel16, cbSize, lpAccel16 );
  280. WOW32ASSERT( lpAccel16 != NULL );
  281. lpAccel16Original = lpAccel16;
  282. //
  283. // Now iterate through the entries changing them and moving them into
  284. // the 16-bit memory.
  285. //
  286. i = 0;
  287. while ( i < iEntries ) {
  288. if ( i == iEntries-1 ) {
  289. // Last one, set the last bit
  290. *lpAccel16++ = lpAccel32[i].fVirt | 0x80;
  291. } else {
  292. *lpAccel16++ = lpAccel32[i].fVirt;
  293. }
  294. *((PWORD16)lpAccel16) = lpAccel32[i].key;
  295. lpAccel16 += sizeof(WORD);
  296. *((PWORD16)lpAccel16) = lpAccel32[i].cmd;
  297. lpAccel16 += sizeof(WORD);
  298. i++;
  299. }
  300. FLUSHVDMPTR(vpAccel16, cbSize, lpAccel16Original);
  301. FREEVDMPTR(lpAccel16Original);
  302. GlobalUnlock16( hAccel16 );
  303. return( hAccel16 );
  304. }
  305. // this gets called indirectly from GlobalFree() in krnl386.exe
  306. // via WK32WowCursorIconOp() in wcuricon.c
  307. void FreeAccelAliasEntry(LPACCELALIAS lpT) {
  308. if (lpT == lpAccelAlias)
  309. lpAccelAlias = lpT->lpNext;
  310. if (lpT->lpPrev)
  311. lpT->lpPrev->lpNext = lpT->lpNext;
  312. if (lpT->lpNext)
  313. lpT->lpNext->lpPrev = lpT->lpPrev;
  314. if ( lpT->f16 ) {
  315. DestroyAcceleratorTable(lpT->h32);
  316. } else {
  317. // this function - FreeAccelAliasEntry -- is being called
  318. // indirectly from GlobalFree() in krnl386. GlobalFree()
  319. // takes care of freeing h16 so this callback is not needed.
  320. // - a-craigj
  321. // WOWGlobalFree16( lpT->h16 );
  322. }
  323. free_w_small(lpT);
  324. }