Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

705 lines
21 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 wow32.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. if(pres == NULL) {
  197. return(NULL);
  198. }
  199. Parm16.WndProc.wParam = pres->hmod16;
  200. Parm16.WndProc.lParam = pres->hresinfo16;
  201. CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vp);
  202. if (pres->hresdata16 = (HRESD16)vp)
  203. return pres;
  204. // BUGBUG -- On a LoadResource failure, WIN32 is not required to do a
  205. // corresponding FreeResource, so our RES structure will hang around until
  206. // task termination clean-up (which may be OK) -JTP
  207. return NULL;
  208. }
  209. BOOL FreeResource16(PRES pres)
  210. {
  211. VPVOID vp=0;
  212. PARM16 Parm16;
  213. if(pres == NULL) {
  214. WOW32ASSERT(pres);
  215. return(FALSE);
  216. }
  217. Parm16.WndProc.wParam = pres->hresdata16;
  218. CallBack16(RET_FREERESOURCE, &Parm16, 0, &vp);
  219. FreeRes16(pres);
  220. return (BOOL)vp;
  221. }
  222. LPBYTE LockResource16(register PRES pres)
  223. {
  224. DWORD cb, cb16;
  225. VPVOID vp=0;
  226. PARM16 Parm16;
  227. WOW32ASSERT(pres);
  228. if(pres == NULL) {
  229. WOW32ASSERT(pres);
  230. return(NULL);
  231. }
  232. Parm16.WndProc.wParam = pres->hresdata16;
  233. CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp);
  234. if (vp) {
  235. // Get size of 16-bit resource
  236. cb16 = Parm16.WndProc.lParam;
  237. LOGDEBUG(5,(" Locking/converting resource type %s(%lx)\n",
  238. GetResourceType(pres->lpszResType), pres->lpszResType));
  239. // Handle known resource types here
  240. if (pres->lpszResType) {
  241. switch((INT)pres->lpszResType) {
  242. case (INT)RT_MENU:
  243. // cb = ConvertMenu16(pres->wExeVer, NULL, vp, cb, cb16);
  244. cb = cb16 * sizeof(WCHAR); // see SizeofResource16
  245. if (cb && (pres->pbResData = malloc_w(cb)))
  246. ConvertMenu16(pres->wExeVer, pres->pbResData, vp, cb, cb16);
  247. return pres->pbResData;
  248. case (INT)RT_DIALOG:
  249. // cb = ConvertDialog16(NULL, vp, cb, cb16);
  250. cb = cb16 * sizeof(WCHAR); // see SizeofResource16
  251. if (cb && (pres->pbResData = malloc_w(cb)))
  252. ConvertDialog16(pres->pbResData, vp, cb, cb16);
  253. return pres->pbResData;
  254. case (INT)RT_ACCELERATOR:
  255. WOW32ASSERT(FALSE); // never should we come here.
  256. return NULL;
  257. // case (INT)RT_GROUP_CURSOR:
  258. // case (INT)RT_GROUP_ICON:
  259. // GETOPTPTR(vp, 0, lp);
  260. // return lp;
  261. }
  262. }
  263. // If we're still here, get desperate and return a simple 32-bit alias
  264. GETVDMPTR(vp, cb16, pres->pbResData);
  265. pres->flState |= RES_ALIASPTR;
  266. return pres->pbResData;
  267. }
  268. // If we're still here, nothing worked
  269. return NULL;
  270. }
  271. BOOL UnlockResource16(PRES pres)
  272. {
  273. VPVOID vp=0;
  274. PARM16 Parm16;
  275. if(pres == NULL) {
  276. WOW32ASSERT(pres);
  277. return(FALSE);
  278. }
  279. Parm16.WndProc.wParam = pres->hresdata16;
  280. CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp);
  281. if (pres->pbResData && !(pres->flState & RES_ALIASPTR))
  282. free_w(pres->pbResData);
  283. pres->pbResData = NULL;
  284. pres->flState &= ~RES_ALIASPTR;
  285. return (BOOL)vp;
  286. }
  287. DWORD SizeofResource16(HMOD16 hmod16, PRES pres)
  288. {
  289. VPVOID vp=0;
  290. DWORD cbData;
  291. PARM16 Parm16;
  292. DBG_UNREFERENCED_PARAMETER(hmod16);
  293. WOW32ASSERT(pres && hmod16 == pres->hmod16);
  294. if(pres == NULL) {
  295. return(0);
  296. }
  297. Parm16.WndProc.wParam = pres->hmod16;
  298. Parm16.WndProc.lParam = pres->hresinfo16;
  299. CallBack16(RET_SIZEOFRESOURCE, &Parm16, 0, &vp);
  300. cbData = (DWORD)vp;
  301. /*
  302. * Adjust the size of the resource if they are different
  303. * between NT and Windows
  304. */
  305. // Handle known resource types here
  306. if (pres->lpszResType) {
  307. switch((INT)pres->lpszResType) {
  308. case (INT)RT_MENU:
  309. case (INT)RT_DIALOG:
  310. // If we need an exact count then we would have to enable this code
  311. // but currently the count is only used in USER to alloc enough space
  312. // in the client\server transition windows.
  313. // WARNING - if this code is re-enabled you must also change LockResource16
  314. // CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vpResLoad);
  315. // CallBack16(RET_LOCKRESOURCE, vpResLoad, 0, &vp);
  316. // if ((INT)pres->lpszResType == RT_MENU)
  317. // cbData = (DWORD)ConvertMenu16(pres->wExeVer, NULL, vp, cbData);
  318. // else
  319. // cbData = (DWORD)ConvertDialog16(NULL, vp, cbData);
  320. // CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp);
  321. cbData = (DWORD)((DWORD)vp * sizeof(WCHAR));
  322. break;
  323. case (INT)RT_STRING:
  324. cbData = (DWORD)((DWORD)vp * sizeof(WCHAR));
  325. break;
  326. }
  327. }
  328. return cbData;
  329. }
  330. /*
  331. * ConvertMenu16
  332. *
  333. * If pmenu32 is NULL then its just a size query
  334. *
  335. * Returns the number of bytes in the CONVERTED menu
  336. */
  337. DWORD ConvertMenu16(WORD wExeVer, PBYTE pmenu32, VPBYTE vpmenu16, DWORD cb, DWORD cb16)
  338. {
  339. WORD wVer, wOffset;
  340. PBYTE pmenu16, pmenu16Save;
  341. PBYTE pmenu32T = pmenu32;
  342. pmenu16 = GETVDMPTR(vpmenu16, cb16, pmenu16Save);
  343. wVer = 0;
  344. if (wExeVer >= 0x300)
  345. wVer = GETWORD(pmenu16);
  346. PUTWORD(pmenu32, wVer); // transfer versionNumber
  347. wOffset = 0;
  348. if (wExeVer >= 0x300)
  349. wOffset = GETWORD(pmenu16);
  350. PUTWORD(pmenu32, wOffset); // transfer offset
  351. ADVGET(pmenu16, wOffset); // and advance by offset
  352. ADVPUT(pmenu32, wOffset);
  353. ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32
  354. cb = pmenu32 - pmenu32T; // pmenu32 will == 4 for size queries
  355. cb += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16Save));
  356. FREEVDMPTR(pmenu16Save);
  357. RETURN(cb);
  358. }
  359. /*
  360. * ConvertMenuItems16
  361. *
  362. * Returns the number of bytes in the CONVERTED menu
  363. * Note: This can be called with ppmenu32==4 which means the caller is looking
  364. * for the size to allocate for the 32-bit menu structure.
  365. */
  366. DWORD ConvertMenuItems16(WORD wExeVer, PPBYTE ppmenu32, PPBYTE ppmenu16, VPBYTE vpmenu16)
  367. {
  368. INT cbAnsi;
  369. DWORD cbTotal = 0;
  370. UINT cbUni;
  371. WORD wOption, wID;
  372. PBYTE pmenu32 = *ppmenu32;
  373. PBYTE pmenu16 = *ppmenu16;
  374. PBYTE pmenu16T = pmenu16;
  375. PBYTE pmenu32T = pmenu32;
  376. do {
  377. if (wExeVer < 0x300)
  378. wOption = GETBYTE(pmenu16);
  379. else
  380. wOption = GETWORD(pmenu16);
  381. PUTWORD(pmenu32, wOption); // transfer mtOption
  382. if (!(wOption & MF_POPUP)) {
  383. wID = GETWORD(pmenu16);
  384. PUTWORD(pmenu32, wID); // transfer mtID
  385. }
  386. cbAnsi = strlen(pmenu16)+1;
  387. // If this is an ownerdraw menu don't copy the ANSI memu string to
  388. // Unicode. Put a 16:16 pointer into the 32-bit resource which
  389. // points to menu string instead. User will place this pointer in
  390. // MEASUREITEMSTRUCT->itemData before sending WM_MEASUREITEM. If it's a
  391. // NULL string User will place a NULL in MEASUREITEMSTRUCT->itemData.
  392. // Chess Master and Mavis Beacon Teaches Typing depend on this.
  393. if ((wOption & MFT_OWNERDRAW) && *pmenu16) {
  394. if (VALIDPUT(pmenu32)) {
  395. *(DWORD UNALIGNED *)pmenu32 = vpmenu16 + (pmenu16 - pmenu16T);
  396. }
  397. cbUni = sizeof(DWORD);
  398. }
  399. else {
  400. if (VALIDPUT(pmenu32)) {
  401. RtlMultiByteToUnicodeN((LPWSTR)pmenu32, MAXULONG, (PULONG)&cbUni, pmenu16, cbAnsi);
  402. }
  403. else {
  404. cbUni = cbAnsi * sizeof(WCHAR);
  405. }
  406. }
  407. ADVGET(pmenu16, cbAnsi);
  408. ADVPUT(pmenu32, cbUni);
  409. ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32
  410. if (wOption & MF_POPUP)
  411. cbTotal += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16T));
  412. } while (!(wOption & MF_END));
  413. *ppmenu32 = pmenu32;
  414. *ppmenu16 = pmenu16;
  415. return (pmenu32 - pmenu32T);
  416. }
  417. DWORD ConvertDialog16(PBYTE pdlg32, VPBYTE vpdlg16, DWORD cb, DWORD cb16)
  418. {
  419. BYTE b;
  420. WORD w;
  421. DWORD dwStyle;
  422. INT i, cItems;
  423. UINT cbAnsi;
  424. UINT cbUni;
  425. PBYTE pdlg16, pdlg16Save;
  426. PBYTE pdlg32T = pdlg32;
  427. pdlg16 = GETVDMPTR(vpdlg16, cb16, pdlg16Save);
  428. dwStyle = GETDWORD(pdlg16);
  429. PUTDWORD(pdlg32, dwStyle); // transfer style
  430. PUTDWORD(pdlg32, 0); // Add NEW extended style
  431. cItems = GETBYTE(pdlg16);
  432. PUTWORD(pdlg32, (WORD)cItems); // stretch count to WORD for WIN32
  433. for (i=0; i<4; i++) {
  434. w = GETWORD(pdlg16);
  435. PUTWORD(pdlg32, w); // transfer x & y, then cx & cy
  436. }
  437. //
  438. // the next three fields are all strings (possibly null)
  439. // menuname, classname, captiontext
  440. // the Menu string can be encoded as ff nn mm which
  441. // means that the menu id is ordinal mmnn
  442. //
  443. for (i=0; i<3; i++) {
  444. if (i==0 && *pdlg16 == 0xFF) { // special encoding of szMenuName
  445. ((PBYTE)pdlg16)++; // advance past the ff byte
  446. PUTWORD(pdlg32, 0xffff); // copy the f word
  447. w = GETWORD(pdlg16); // get the menu ordinal
  448. PUTWORD(pdlg32, w); // transfer it
  449. } else { // ordinary string
  450. cbAnsi = strlen(pdlg16)+1;
  451. if (VALIDPUT(pdlg32)) {
  452. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  453. } else {
  454. cbUni = cbAnsi * sizeof(WCHAR);
  455. }
  456. ADVGET(pdlg16, cbAnsi);
  457. ADVPUT(pdlg32, cbUni);
  458. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  459. }
  460. }
  461. if (dwStyle & DS_SETFONT) {
  462. w = GETWORD(pdlg16);
  463. PUTWORD(pdlg32, w); // transfer cPoints
  464. cbAnsi = strlen(pdlg16)+1; // then szTypeFace
  465. if (VALIDPUT(pdlg32)) {
  466. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  467. #ifdef FE_SB
  468. // orignal source should be fixed.
  469. // We can't convert right Unicode string from Broken FaceName
  470. // string.
  471. // Converted Unicode String should be NULL terminated.
  472. // 1994.11.12 V-HIDEKK
  473. if( cbUni && ((LPWSTR)pdlg32)[cbUni/sizeof(WCHAR)-1] ){
  474. LOGDEBUG(0,(" ConvertDialog16: WARNING: BAD FaceName String\n End of Unicode String (%04x)\n", ((LPWSTR)pdlg32)[cbUni/2-1]));
  475. ((LPWSTR)pdlg32)[cbUni/sizeof(WCHAR)-1] = 0;
  476. }
  477. #endif // FE_SB
  478. } else {
  479. cbUni = cbAnsi * sizeof(WCHAR);
  480. }
  481. ADVGET(pdlg16, cbAnsi);
  482. ADVPUT(pdlg32, cbUni);
  483. }
  484. while (cItems--) {
  485. ALIGNDWORD(pdlg32); // items start on DWORD boundaries
  486. PUTDWORD(pdlg32, FETCHDWORD(*(PDWORD)(pdlg16+sizeof(WORD)*5)));
  487. PUTDWORD(pdlg32, 0); // Add NEW extended style
  488. for (i=0; i<5; i++) {
  489. w = GETWORD(pdlg16);
  490. PUTWORD(pdlg32, w); // transfer x & y, then cx & cy, then id
  491. }
  492. ADVGET(pdlg16, sizeof(DWORD)); // skip style, which we already copied
  493. //
  494. // get the class name could be string or encoded value
  495. // win16 encoding scheme: class is 1 byte with bit 0x80 set,
  496. // this byte == predefined class
  497. // win32 encoding: a word of ffff, followed by class (word)
  498. //
  499. if (*pdlg16 & 0x80) {
  500. PUTWORD(pdlg32, 0xFFFF); // NEW encoding marker 0xFFFF
  501. b = GETBYTE(pdlg16); // special encoding for predefined class
  502. PUTWORD(pdlg32, (WORD)b);
  503. } else {
  504. cbAnsi = strlen(pdlg16)+1;
  505. if (VALIDPUT(pdlg32)) { // transfer szClass
  506. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  507. } else {
  508. cbUni = cbAnsi * sizeof(WCHAR);
  509. }
  510. ADVGET(pdlg16, cbAnsi);
  511. ADVPUT(pdlg32, cbUni);
  512. }
  513. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  514. //
  515. // transfer the item text
  516. //
  517. if (*pdlg16 == 0xFF) { // special encoding
  518. ((PBYTE)pdlg16)++;
  519. PUTWORD(pdlg32, 0xFFFF);
  520. w = GETWORD(pdlg16);
  521. PUTWORD(pdlg32, w);
  522. } else {
  523. cbAnsi = strlen(pdlg16)+1;
  524. if (VALIDPUT(pdlg32)) { // otherwise, just transfer szText
  525. RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi);
  526. } else {
  527. cbUni = cbAnsi * sizeof(WCHAR);
  528. }
  529. ADVGET(pdlg16, cbAnsi);
  530. ADVPUT(pdlg32, cbUni);
  531. }
  532. ALIGNWORD(pdlg32); // fix next field alignment for WIN32
  533. //
  534. // transfer the create params
  535. //
  536. b = GETBYTE(pdlg16);
  537. //
  538. // If the template has create params, we're going to get tricky.
  539. // When USER sends the WM_CREATE message to a control with
  540. // createparams, lParam points to the CREATESTRUCT, which
  541. // contains lpCreateParams. lpCreateParams needs to point
  542. // to the createparams in the DLGTEMPLATE. In order to
  543. // accomplish this, we store a 16:16 pointer to the 16-bit
  544. // DLGTEMPLATE's createparams in the 32-bit DLGTEMPLATE's
  545. // createparams. In other words, whenever the count of
  546. // bytes of createparams is nonzero (b != 0), we put 4
  547. // bytes of createparams in the 32-bit DLGTEMPLATE that
  548. // happen to be a 16:16 pointer to the createparams in
  549. // the 16-bit DLGTEMPLATE.
  550. //
  551. // The other half of this magic is accomplished in USERSRV's
  552. // xxxServerCreateDialog, which special-cases the creation
  553. // of controls in a WOW dialog box. USERSRV will pass the
  554. // DWORD pointed to by lpCreateParams instead of lpCreateParams
  555. // to CreateWindow. This DWORD is the 16:16 pointer to the
  556. // 16-bit DLGTEMPLATE's createparams.
  557. //
  558. // DaveHart 14-Mar-93
  559. //
  560. if (b != 0) {
  561. // store 32-bit createparams size (room for 16:16 ptr)
  562. PUTWORD(pdlg32, sizeof(pdlg16));
  563. //ALIGNDWORD(pdlg32);
  564. // store 16:16 pointer in 32-bit createparams
  565. PUTUDWORD(pdlg32, (DWORD)vpdlg16 + (DWORD)(pdlg16 - pdlg16Save));
  566. // point pdlg16 past createparams
  567. ADVGET(pdlg16, b);
  568. } else {
  569. // there are no createparams, store size of zero.
  570. PUTWORD(pdlg32, 0);
  571. //ALIGNDWORD(pdlg32);
  572. }
  573. }
  574. FREEVDMPTR(pdlg16Save);
  575. RETURN(pdlg32 - pdlg32T);
  576. }