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.

685 lines
20 KiB

  1. /*++
  2. *
  3. * WOW v1.0
  4. *
  5. * Copyright (c) 1991, Microsoft Corporation
  6. *
  7. * WRES16.C
  8. * WOW32 16-bit resource support
  9. *
  10. * History:
  11. * Created 11-Mar-1991 by Jeff Parsons (jeffpar)
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // BUGBUG: moved macros from mvdm.h and wo32.h
  17. // as they are not what they appear to be.
  18. // Watch out these macros increment the pointer arguments!!!!
  19. // 02-Feb-1994 Jonle
  20. //
  21. #define VALIDPUT(p) ((UINT)p>65535)
  22. #define PUTWORD(p,w) {if (VALIDPUT(p)) *(PWORD)p=w; ((PWORD)p)++; }
  23. #define PUTDWORD(p,d) {if (VALIDPUT(p)) *(PDWORD)p=d;((PDWORD)p)++;}
  24. #define PUTUDWORD(p,d) {if (VALIDPUT(p)) *(DWORD UNALIGNED *)p=d;((DWORD UNALIGNED *)p)++;}
  25. #define GETWORD(pb) (*((UNALIGNED WORD *)pb)++)
  26. #define GETDWORD(pb) (*((UNALIGNED DWORD *)pb)++)
  27. #define ADVGET(p,i) {(UINT)p+=i;}
  28. #define ADVPUT(p,i) {(UINT)p+=i;}
  29. #define ALIGNWORD(p) {(UINT)p+=( ((UINT)p)&(sizeof(WORD)-1));}
  30. #define ALIGNDWORD(p) {(UINT)p+=(-((INT)p)&(sizeof(DWORD)-1));}
  31. MODNAME(wres16.c);
  32. PRES presFirst; // pointer to first RES entry
  33. #ifdef DEBUG
  34. typedef struct _RTINFO { /* rt */
  35. LPSTR lpType; // predefined resource type
  36. PSZ pszName; // name of type
  37. } RTINFO, *PRTINFO;
  38. RTINFO artInfo[] = {
  39. {RT_CURSOR, "CURSOR"},
  40. {RT_BITMAP, "BITMAP"},
  41. {RT_ICON, "ICON"},
  42. {RT_MENU, "MENU"},
  43. {RT_DIALOG, "DIALOG"},
  44. {RT_STRING, "STRING"},
  45. {RT_FONTDIR, "FONTDIR"},
  46. {RT_FONT, "FONT"},
  47. {RT_ACCELERATOR, "ACCELERATOR"},
  48. {RT_RCDATA, "RCDATA"},
  49. {RT_MESSAGETABLE,"MESSAGETABLE"},
  50. {RT_GROUP_CURSOR,"CURSOR DIRECTORY"},
  51. {RT_GROUP_ICON, "ICON DIRECTORY"},
  52. };
  53. PSZ GetResourceType(LPSZ lpszType)
  54. {
  55. INT i;
  56. register PRTINFO prt;
  57. if (HIWORD(lpszType) != 0)
  58. return lpszType;
  59. for (prt=artInfo,i=NUMEL(artInfo); i>0; i--,prt++)
  60. if (prt->lpType == lpszType)
  61. return prt->pszName;
  62. return "UNKNOWN";
  63. }
  64. #endif
  65. /* Resource management functions
  66. */
  67. PRES AddRes16(HMOD16 hmod16, WORD wExeVer, HRESI16 hresinfo16, LPSZ lpszType)
  68. {
  69. register PRES pres;
  70. if (pres = malloc_w(sizeof(RES))) {
  71. // Initialize the structure
  72. pres->hmod16 = hmod16;
  73. pres->wExeVer = wExeVer;
  74. pres->flState = 0;
  75. pres->hresinfo16 = hresinfo16;
  76. pres->hresdata16 = 0;
  77. pres->lpszResType = lpszType;
  78. pres->pbResData = NULL;
  79. // And then link it in
  80. pres->presNext = presFirst;
  81. presFirst = pres;
  82. return pres;
  83. }
  84. return NULL;
  85. }
  86. VOID FreeRes16(PRES presFree)
  87. {
  88. register PRES pres, presPrev;
  89. presPrev = (PRES)(&presFirst);
  90. while (pres = presPrev->presNext) {
  91. if (pres == presFree)
  92. break;
  93. presPrev = pres;
  94. }
  95. // Changed from WOW32ASSERT by cmjones 11/3/97
  96. // This might be a bogus warning in that USER32!SplFreeResource() calls
  97. // W32FreeResource() twice on certain types of resources. The Warning
  98. // might be raised on the 2nd call after the resource was just freed.
  99. // The only known occurances are at the start of the Winstone '94
  100. // Quattro Pro test. This can safely be ignored if you see SplFreeResource
  101. // in the stack dump.
  102. WOW32WARNMSG((pres),("WOW::FreeRes16:Possible lost resource.\n"));
  103. if (pres) {
  104. presPrev->presNext = pres->presNext;
  105. if (pres->pbResData)
  106. UnlockResource16(pres);
  107. free_w(pres);
  108. }
  109. }
  110. VOID DestroyRes16(HMOD16 hmod16)
  111. {
  112. register PRES pres, presPrev;
  113. presPrev = (PRES)(&presFirst);
  114. while (pres = presPrev->presNext) {
  115. if (pres->hmod16 == hmod16) {
  116. LOGDEBUG(5,("Freeing resource info for current terminating task\n"));
  117. // Now basically do a FreeRes16
  118. presPrev->presNext = pres->presNext;
  119. if (pres->pbResData)
  120. UnlockResource16(pres);
  121. free_w(pres);
  122. } else {
  123. presPrev = pres;
  124. }
  125. }
  126. }
  127. PRES FindResource16(HMOD16 hmod16, LPSZ lpszName, LPSZ lpszType)
  128. {
  129. INT cb;
  130. PRES pres = NULL;
  131. VPVOID vp=0;
  132. PARM16 Parm16;
  133. VPSZ vpszName = 0, vpszType = 0;
  134. WORD wExpWinVer;
  135. if (HIWORD(lpszName) == 0) {
  136. vpszName = (VPSZ)lpszName;
  137. LOGDEBUG(5,(" Finding resource %lx, type %s(%lx)\n",
  138. lpszName, GetResourceType(lpszType), lpszType));
  139. } else {
  140. #ifdef FE_SB
  141. if (CURRENTPTD()->dwWOWCompatFlagsFE & WOWCF_FE_ARIRANG20_PRNDLG) {
  142. /*
  143. * In case of Korean Arirang2.0 word processor, it use wrong dialog ID
  144. * for Print or Print setup dialog. See dialog box ID on awpfont.dll.
  145. */
  146. if (!WOW32_strcmp(lpszName, "PRINTDLGTEMP"))
  147. vpszName = (VPSZ) 2;
  148. else if(!WOW32_strcmp(lpszName, "PRNSETUPDLGTEMP"))
  149. vpszName = (VPSZ) 1;
  150. else goto NOT_ARIRANG20;
  151. } else { // original code
  152. NOT_ARIRANG20:
  153. #endif
  154. cb = strlen(lpszName)+1;
  155. if (vpszName = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL))
  156. putstr16(vpszName, lpszName, cb);
  157. LOGDEBUG(5,(" Finding resource \"%s\", type %s(%lx)\n",
  158. lpszName, GetResourceType(lpszType), lpszType));
  159. #ifdef FE_SB
  160. }
  161. #endif
  162. }
  163. if (vpszName) {
  164. if (HIWORD(lpszType) == 0) { // predefined resource
  165. vpszType = (VPSZ)lpszType; // no doubt from MAKEINTRESOURCE
  166. } else {
  167. cb = strlen(lpszType)+1;
  168. if (vpszType = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL)) {
  169. putstr16(vpszType, lpszType, cb);
  170. }
  171. }
  172. if (vpszType) {
  173. Parm16.WndProc.wParam = hmod16;
  174. Parm16.WndProc.lParam = vpszName;
  175. Parm16.WndProc.wMsg = LOWORD(vpszType);
  176. Parm16.WndProc.hwnd = HIWORD(vpszType);
  177. CallBack16(RET_FINDRESOURCE, &Parm16, 0, &vp);
  178. wExpWinVer = LOWORD(Parm16.WndProc.lParam);
  179. if (HIWORD(vpszType))
  180. GlobalUnlockFree16(vpszType);
  181. }
  182. if (HIWORD(vpszName))
  183. GlobalUnlockFree16(vpszName);
  184. }
  185. if ((HRESI16)vp) {
  186. pres = AddRes16(hmod16,wExpWinVer,(HRESI16)vp, lpszType);
  187. }
  188. return pres;
  189. }
  190. PRES LoadResource16(HMOD16 hmod16, PRES pres)
  191. {
  192. VPVOID vp=0;
  193. PARM16 Parm16;
  194. DBG_UNREFERENCED_PARAMETER(hmod16);
  195. WOW32ASSERT(pres && hmod16 == pres->hmod16);
  196. Parm16.WndProc.wParam = pres->hmod16;
  197. Parm16.WndProc.lParam = pres->hresinfo16;
  198. CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vp);
  199. if (pres->hresdata16 = (HRESD16)vp)
  200. return pres;
  201. // BUGBUG -- On a LoadResource failure, WIN32 is not required to do a
  202. // corresponding FreeResource, so our RES structure will hang around until
  203. // task termination clean-up (which may be OK) -JTP
  204. return NULL;
  205. }
  206. BOOL FreeResource16(PRES pres)
  207. {
  208. VPVOID vp=0;
  209. PARM16 Parm16;
  210. WOW32ASSERT(pres);
  211. Parm16.WndProc.wParam = pres->hresdata16;
  212. CallBack16(RET_FREERESOURCE, &Parm16, 0, &vp);
  213. FreeRes16(pres);
  214. return (BOOL)vp;
  215. }
  216. LPBYTE LockResource16(register PRES pres)
  217. {
  218. DWORD cb, cb16;
  219. VPVOID vp=0;
  220. PARM16 Parm16;
  221. WOW32ASSERT(pres);
  222. Parm16.WndProc.wParam = pres->hresdata16;
  223. CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp);
  224. if (vp) {
  225. // Get size of 16-bit resource
  226. cb16 = Parm16.WndProc.lParam;
  227. LOGDEBUG(5,(" Locking/converting resource type %s(%lx)\n",
  228. GetResourceType(pres->lpszResType), pres->lpszResType));
  229. // Handle known resource types here
  230. if (pres->lpszResType) {
  231. switch((INT)pres->lpszResType) {
  232. case (INT)RT_MENU:
  233. // cb = ConvertMenu16(pres->wExeVer, NULL, vp, cb, cb16);
  234. cb = cb16 * sizeof(WCHAR); // see SizeofResource16
  235. if (cb && (pres->pbResData = malloc_w(cb)))
  236. ConvertMenu16(pres->wExeVer, pres->pbResData, vp, cb, cb16);
  237. return pres->pbResData;
  238. case (INT)RT_DIALOG:
  239. // cb = ConvertDialog16(NULL, vp, cb, cb16);
  240. cb = cb16 * sizeof(WCHAR); // see SizeofResource16
  241. if (cb && (pres->pbResData = malloc_w(cb)))
  242. ConvertDialog16(pres->pbResData, vp, cb, cb16);
  243. return pres->pbResData;
  244. case (INT)RT_ACCELERATOR:
  245. WOW32ASSERT(FALSE); // never should we come here.
  246. return NULL;
  247. // case (INT)RT_GROUP_CURSOR:
  248. // case (INT)RT_GROUP_ICON:
  249. // GETOPTPTR(vp, 0, lp);
  250. // return lp;
  251. }
  252. }
  253. // If we're still here, get desperate and return a simple 32-bit alias
  254. GETVDMPTR(vp, cb16, pres->pbResData);
  255. pres->flState |= RES_ALIASPTR;
  256. return pres->pbResData;
  257. }
  258. // If we're still here, nothing worked
  259. return NULL;
  260. }
  261. BOOL UnlockResource16(PRES pres)
  262. {
  263. VPVOID vp=0;
  264. PARM16 Parm16;
  265. WOW32ASSERT(pres);
  266. Parm16.WndProc.wParam = pres->hresdata16;
  267. CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp);
  268. if (pres->pbResData && !(pres->flState & RES_ALIASPTR))
  269. free_w(pres->pbResData);
  270. pres->pbResData = NULL;
  271. pres->flState &= ~RES_ALIASPTR;
  272. return (BOOL)vp;
  273. }
  274. DWORD SizeofResource16(HMOD16 hmod16, PRES pres)
  275. {
  276. VPVOID vp=0;
  277. DWORD cbData;
  278. PARM16 Parm16;
  279. DBG_UNREFERENCED_PARAMETER(hmod16);
  280. WOW32ASSERT(pres && hmod16 == pres->hmod16);
  281. Parm16.WndProc.wParam = pres->hmod16;
  282. Parm16.WndProc.lParam = pres->hresinfo16;
  283. CallBack16(RET_SIZEOFRESOURCE, &Parm16, 0, &vp);
  284. cbData = (DWORD)vp;
  285. /*
  286. * Adjust the size of the resource if they are different
  287. * between NT and Windows
  288. */
  289. // Handle known resource types here
  290. if (pres->lpszResType) {
  291. switch((INT)pres->lpszResType) {
  292. case (INT)RT_MENU:
  293. case (INT)RT_DIALOG:
  294. // If we need an exact count then we would have to enable this code
  295. // but currently the count is only used in USER to alloc enough space
  296. // in the client\server transition windows.
  297. // WARNING - if this code is re-enabled you must also change LockResource16
  298. // CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vpResLoad);
  299. // CallBack16(RET_LOCKRESOURCE, vpResLoad, 0, &vp);
  300. // if ((INT)pres->lpszResType == RT_MENU)
  301. // cbData = (DWORD)ConvertMenu16(pres->wExeVer, NULL, vp, cbData);
  302. // else
  303. // cbData = (DWORD)ConvertDialog16(NULL, vp, cbData);
  304. // CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp);
  305. cbData = (DWORD)((DWORD)vp * sizeof(WCHAR));
  306. break;
  307. case (INT)RT_STRING:
  308. cbData = (DWORD)((DWORD)vp * sizeof(WCHAR));
  309. break;
  310. }
  311. }
  312. return cbData;
  313. }
  314. /*
  315. * ConvertMenu16
  316. *
  317. * If pmenu32 is NULL then its just a size query
  318. *
  319. * Returns the number of bytes in the CONVERTED menu
  320. */
  321. DWORD ConvertMenu16(WORD wExeVer, PBYTE pmenu32, VPBYTE vpmenu16, DWORD cb, DWORD cb16)
  322. {
  323. WORD wVer, wOffset;
  324. PBYTE pmenu16, pmenu16Save;
  325. PBYTE pmenu32T = pmenu32;
  326. pmenu16 = GETVDMPTR(vpmenu16, cb16, pmenu16Save);
  327. wVer = 0;
  328. if (wExeVer >= 0x300)
  329. wVer = GETWORD(pmenu16);
  330. PUTWORD(pmenu32, wVer); // transfer versionNumber
  331. wOffset = 0;
  332. if (wExeVer >= 0x300)
  333. wOffset = GETWORD(pmenu16);
  334. PUTWORD(pmenu32, wOffset); // transfer offset
  335. ADVGET(pmenu16, wOffset); // and advance by offset
  336. ADVPUT(pmenu32, wOffset);
  337. ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32
  338. cb = pmenu32 - pmenu32T; // pmenu32 will == 4 for size queries
  339. cb += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16Save));
  340. FREEVDMPTR(pmenu16Save);
  341. RETURN(cb);
  342. }
  343. /*
  344. * ConvertMenuItems16
  345. *
  346. * Returns the number of bytes in the CONVERTED menu
  347. * Note: This can be called with ppmenu32==4 which means the caller is looking
  348. * for the size to allocate for the 32-bit menu structure.
  349. */
  350. DWORD ConvertMenuItems16(WORD wExeVer, PPBYTE ppmenu32, PPBYTE ppmenu16, VPBYTE vpmenu16)
  351. {
  352. INT cbAnsi;
  353. DWORD cbTotal = 0;
  354. UINT cbUni;
  355. WORD wOption, wID;
  356. PBYTE pmenu32 = *ppmenu32;
  357. PBYTE pmenu16 = *ppmenu16;
  358. PBYTE pmenu16T = pmenu16;
  359. PBYTE pmenu32T = pmenu32;
  360. do {
  361. if (wExeVer < 0x300)
  362. wOption = GETBYTE(pmenu16);
  363. else
  364. wOption = GETWORD(pmenu16);
  365. PUTWORD(pmenu32, wOption); // transfer mtOption
  366. if (!(wOption & MF_POPUP)) {
  367. wID = GETWORD(pmenu16);
  368. PUTWORD(pmenu32, wID); // transfer mtID
  369. }
  370. cbAnsi = strlen(pmenu16)+1;
  371. // If this is an ownerdraw menu don't copy the ANSI memu string to
  372. // Unicode. Put a 16:16 pointer into the 32-bit resource which
  373. // points to menu string instead. User will place this pointer in
  374. // MEASUREITEMSTRUCT->itemData before sending WM_MEASUREITEM. If it's a
  375. // NULL string User will place a NULL in MEASUREITEMSTRUCT->itemData.
  376. // Chess Master and Mavis Beacon Teaches Typing depend on this.
  377. if ((wOption & MFT_OWNERDRAW) && *pmenu16) {
  378. if (VALIDPUT(pmenu32)) {
  379. *(DWORD UNALIGNED *)pmenu32 = vpmenu16 + (pmenu16 - pmenu16T);
  380. }
  381. cbUni = sizeof(DWORD);
  382. }
  383. else {
  384. if (VALIDPUT(pmenu32)) {
  385. RtlMultiByteToUnicodeN((LPWSTR)pmenu32, MAXULONG, (PULONG)&cbUni, pmenu16, cbAnsi);
  386. }
  387. else {
  388. cbUni = cbAnsi * sizeof(WCHAR);
  389. }
  390. }
  391. ADVGET(pmenu16, cbAnsi);
  392. ADVPUT(pmenu32, cbUni);
  393. ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32
  394. if (wOption & MF_POPUP)
  395. cbTotal += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16T));
  396. } while (!(wOption & MF_END));
  397. *ppmenu32 = pmenu32;
  398. *ppmenu16 = pmenu16;
  399. return (pmenu32 - pmenu32T);
  400. }
  401. DWORD ConvertDialog16(PBYTE pdlg32, VPBYTE vpdlg16, DWORD cb, DWORD cb16)
  402. {
  403. BYTE b;
  404. WORD w;
  405. DWORD dwStyle;
  406. INT i, cItems;
  407. UINT cbAnsi;
  408. UINT cbUni;
  409. PBYTE pdlg16, pdlg16Save;
  410. PBYTE pdlg32T = pdlg32;
  411. pdlg16 = GETVDMPTR(vpdlg16, cb16, pdlg16Save);
  412. dwStyle = GETDWORD(pdlg16);
  413. PUTDWORD(pdlg32, dwStyle); // transfer style
  414. PUTDWORD(pdlg32, 0); // Add NEW extended style
  415. cItems = GETBYTE(pdlg16);
  416. PUTWORD(pdlg32, (WORD)cItems); // stretch count to WORD for WIN32
  417. for (i=0; i<4; i++) {
  418. w = GETWORD(pdlg16);
  419. PUTWORD(pdlg32, w); // transfer x & y, then cx & cy
  420. }
  421. //
  422. // the next three fields are all strings (possibly null)
  423. // menuname, classname, captiontext
  424. // the Menu string can be encoded as ff nn mm which
  425. // means that the menu id is ordinal mmnn
  426. //
  427. for (i=0; i<3; i++) {
  428. if (i==0 && *pdlg16 == 0xFF) { // special encoding of szMenuName
  429. GETBYTE(pdlg16); // advance past the ff byte
  430. PUTWORD(pdlg32, 0xffff); // copy the f word
  431. w = GETWORD(pdlg16); // get the menu ordinal
  432. PUTWORD(pdlg32, w); // transfer it
  433. } else { // ordinary string
  434. cbAnsi = strlen(pdlg16)+1;
  435. if (VALIDPUT(pdlg32)) {
  436. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  437. } else {
  438. cbUni = cbAnsi * sizeof(WCHAR);
  439. }
  440. ADVGET(pdlg16, cbAnsi);
  441. ADVPUT(pdlg32, cbUni);
  442. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  443. }
  444. }
  445. if (dwStyle & DS_SETFONT) {
  446. w = GETWORD(pdlg16);
  447. PUTWORD(pdlg32, w); // transfer cPoints
  448. cbAnsi = strlen(pdlg16)+1; // then szTypeFace
  449. if (VALIDPUT(pdlg32)) {
  450. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  451. #ifdef FE_SB
  452. // orignal source should be fixed.
  453. // We can't convert right Unicode string from Broken FaceName
  454. // string.
  455. // Converted Unicode String should be NULL terminated.
  456. // 1994.11.12 V-HIDEKK
  457. if( cbUni && ((LPWSTR)pdlg32)[cbUni/sizeof(WCHAR)-1] ){
  458. LOGDEBUG(0,(" ConvertDialog16: WARNING: BAD FaceName String\n End of Unicode String (%04x)\n", ((LPWSTR)pdlg32)[cbUni/2-1]));
  459. ((LPWSTR)pdlg32)[cbUni/sizeof(WCHAR)-1] = 0;
  460. }
  461. #endif // FE_SB
  462. } else {
  463. cbUni = cbAnsi * sizeof(WCHAR);
  464. }
  465. ADVGET(pdlg16, cbAnsi);
  466. ADVPUT(pdlg32, cbUni);
  467. }
  468. while (cItems--) {
  469. ALIGNDWORD(pdlg32); // items start on DWORD boundaries
  470. PUTDWORD(pdlg32, FETCHDWORD(*(PDWORD)(pdlg16+sizeof(WORD)*5)));
  471. PUTDWORD(pdlg32, 0); // Add NEW extended style
  472. for (i=0; i<5; i++) {
  473. w = GETWORD(pdlg16);
  474. PUTWORD(pdlg32, w); // transfer x & y, then cx & cy, then id
  475. }
  476. ADVGET(pdlg16, sizeof(DWORD)); // skip style, which we already copied
  477. //
  478. // get the class name could be string or encoded value
  479. // win16 encoding scheme: class is 1 byte with bit 0x80 set,
  480. // this byte == predefined class
  481. // win32 encoding: a word of ffff, followed by class (word)
  482. //
  483. if (*pdlg16 & 0x80) {
  484. PUTWORD(pdlg32, 0xFFFF); // NEW encoding marker 0xFFFF
  485. b = GETBYTE(pdlg16); // special encoding for predefined class
  486. PUTWORD(pdlg32, (WORD)b);
  487. } else {
  488. cbAnsi = strlen(pdlg16)+1;
  489. if (VALIDPUT(pdlg32)) { // transfer szClass
  490. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  491. } else {
  492. cbUni = cbAnsi * sizeof(WCHAR);
  493. }
  494. ADVGET(pdlg16, cbAnsi);
  495. ADVPUT(pdlg32, cbUni);
  496. }
  497. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  498. //
  499. // transfer the item text
  500. //
  501. if (*pdlg16 == 0xFF) { // special encoding
  502. GETBYTE(pdlg16);
  503. PUTWORD(pdlg32, 0xFFFF);
  504. w = GETWORD(pdlg16);
  505. PUTWORD(pdlg32, w);
  506. } else {
  507. cbAnsi = strlen(pdlg16)+1;
  508. if (VALIDPUT(pdlg32)) { // otherwise, just transfer szText
  509. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  510. } else {
  511. cbUni = cbAnsi * sizeof(WCHAR);
  512. }
  513. ADVGET(pdlg16, cbAnsi);
  514. ADVPUT(pdlg32, cbUni);
  515. }
  516. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  517. //
  518. // transfer the create params
  519. //
  520. b = GETBYTE(pdlg16);
  521. //
  522. // If the template has create params, we're going to get tricky.
  523. // When USER sends the WM_CREATE message to a control with
  524. // createparams, lParam points to the CREATESTRUCT, which
  525. // contains lpCreateParams. lpCreateParams needs to point
  526. // to the createparams in the DLGTEMPLATE. In order to
  527. // accomplish this, we store a 16:16 pointer to the 16-bit
  528. // DLGTEMPLATE's createparams in the 32-bit DLGTEMPLATE's
  529. // createparams. In other words, whenever the count of
  530. // bytes of createparams is nonzero (b != 0), we put 4
  531. // bytes of createparams in the 32-bit DLGTEMPLATE that
  532. // happen to be a 16:16 pointer to the createparams in
  533. // the 16-bit DLGTEMPLATE.
  534. //
  535. // The other half of this magic is accomplished in USERSRV's
  536. // xxxServerCreateDialog, which special-cases the creation
  537. // of controls in a WOW dialog box. USERSRV will pass the
  538. // DWORD pointed to by lpCreateParams instead of lpCreateParams
  539. // to CreateWindow. This DWORD is the 16:16 pointer to the
  540. // 16-bit DLGTEMPLATE's createparams.
  541. //
  542. // DaveHart 14-Mar-93
  543. //
  544. if (b != 0) {
  545. // store 32-bit createparams size (room for 16:16 ptr)
  546. PUTWORD(pdlg32, sizeof(pdlg16));
  547. //ALIGNDWORD(pdlg32);
  548. // store 16:16 pointer in 32-bit createparams
  549. PUTUDWORD(pdlg32, (DWORD)vpdlg16 + (DWORD)(pdlg16 - pdlg16Save));
  550. // point pdlg16 past createparams
  551. ADVGET(pdlg16, b);
  552. } else {
  553. // there are no createparams, store size of zero.
  554. PUTWORD(pdlg32, 0);
  555. //ALIGNDWORD(pdlg32);
  556. }
  557. }
  558. FREEVDMPTR(pdlg16Save);
  559. RETURN(pdlg32 - pdlg32T);
  560. }