diff options
Diffstat (limited to 'private/mvdm/wow32/wres16.c')
-rw-r--r-- | private/mvdm/wow32/wres16.c | 654 |
1 files changed, 654 insertions, 0 deletions
diff --git a/private/mvdm/wow32/wres16.c b/private/mvdm/wow32/wres16.c new file mode 100644 index 000000000..206d9b984 --- /dev/null +++ b/private/mvdm/wow32/wres16.c @@ -0,0 +1,654 @@ +/*++ + * + * WOW v1.0 + * + * Copyright (c) 1991, Microsoft Corporation + * + * WRES16.C + * WOW32 16-bit resource support + * + * History: + * Created 11-Mar-1991 by Jeff Parsons (jeffpar) +--*/ + + +#include "precomp.h" +#pragma hdrstop + +// +// BUGBUG: moved macros from mvdm.h and wo32.h +// as they are not what they appear to be. +// Watch out these macros increment the pointer arguments!!!! +// 02-Feb-1994 Jonle +// +#define VALIDPUT(p) ((UINT)p>65535) +#define PUTWORD(p,w) {if (VALIDPUT(p)) *(PWORD)p=w; ((PWORD)p)++; } +#define PUTDWORD(p,d) {if (VALIDPUT(p)) *(PDWORD)p=d;((PDWORD)p)++;} +#define PUTUDWORD(p,d) {if (VALIDPUT(p)) *(DWORD UNALIGNED *)p=d;((DWORD UNALIGNED *)p)++;} +#define GETWORD(pb) (*((UNALIGNED WORD *)pb)++) +#define GETDWORD(pb) (*((UNALIGNED DWORD *)pb)++) + +#define ADVGET(p,i) {(UINT)p+=i;} +#define ADVPUT(p,i) {(UINT)p+=i;} +#define ALIGNWORD(p) {(UINT)p+=( ((UINT)p)&(sizeof(WORD)-1));} +#define ALIGNDWORD(p) {(UINT)p+=(-((INT)p)&(sizeof(DWORD)-1));} + + +MODNAME(wres16.c); + +PRES presFirst; // pointer to first RES entry + +#ifdef DEBUG + +typedef struct _RTINFO { /* rt */ + LPSTR lpType; // predefined resource type + PSZ pszName; // name of type +} RTINFO, *PRTINFO; + +RTINFO artInfo[] = { + {RT_CURSOR, "CURSOR"}, + {RT_BITMAP, "BITMAP"}, + {RT_ICON, "ICON"}, + {RT_MENU, "MENU"}, + {RT_DIALOG, "DIALOG"}, + {RT_STRING, "STRING"}, + {RT_FONTDIR, "FONTDIR"}, + {RT_FONT, "FONT"}, + {RT_ACCELERATOR, "ACCELERATOR"}, + {RT_RCDATA, "RCDATA"}, + {RT_MESSAGETABLE,"MESSAGETABLE"}, + {RT_GROUP_CURSOR,"CURSOR DIRECTORY"}, + {RT_GROUP_ICON, "ICON DIRECTORY"}, +}; + +PSZ GetResourceType(LPSZ lpszType) +{ + INT i; + register PRTINFO prt; + + if (HIWORD(lpszType) != 0) + return lpszType; + for (prt=artInfo,i=NUMEL(artInfo); i>0; i--,prt++) + if (prt->lpType == lpszType) + return prt->pszName; + return "UNKNOWN"; +} + +#endif + + +/* Resource management functions + */ + +PRES AddRes16(HMOD16 hmod16, WORD wExeVer, HRESI16 hresinfo16, LPSZ lpszType) +{ + register PRES pres; + + if (pres = malloc_w(sizeof(RES))) { + + // Initialize the structure + pres->hmod16 = hmod16; + pres->wExeVer = wExeVer; + pres->flState = 0; + pres->hresinfo16 = hresinfo16; + pres->hresdata16 = 0; + pres->lpszResType = lpszType; + pres->pbResData = NULL; + + // And then link it in + pres->presNext = presFirst; + presFirst = pres; + return pres; + } + return NULL; +} + + +VOID FreeRes16(PRES presFree) +{ + register PRES pres, presPrev; + + presPrev = (PRES)(&presFirst); + while (pres = presPrev->presNext) { + if (pres == presFree) + break; + presPrev = pres; + } + WOW32ASSERT(pres); // not finding a pres would be rather distressing + if (pres) { + presPrev->presNext = pres->presNext; + if (pres->pbResData) + UnlockResource16(pres); + free_w(pres); + } +} + + +VOID DestroyRes16(HMOD16 hmod16) +{ + register PRES pres, presPrev; + + presPrev = (PRES)(&presFirst); + while (pres = presPrev->presNext) { + if (pres->hmod16 == hmod16) { + + LOGDEBUG(5,("Freeing resource info for current terminating task\n")); + + // Now basically do a FreeRes16 + presPrev->presNext = pres->presNext; + if (pres->pbResData) + UnlockResource16(pres); + free_w(pres); + } else { + presPrev = pres; + } + } +} + + +PRES FindResource16(HMOD16 hmod16, LPSZ lpszName, LPSZ lpszType) +{ + INT cb; + PRES pres = NULL; + VPVOID vp=0; + PARM16 Parm16; + VPSZ vpszName = 0, vpszType = 0; + WORD wExpWinVer; + + if (HIWORD(lpszName) == 0) { + vpszName = (VPSZ)lpszName; + LOGDEBUG(5,(" Finding resource %lx, type %s(%lx)\n", + lpszName, GetResourceType(lpszType), lpszType)); + } else { + cb = strlen(lpszName)+1; + if (vpszName = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL)) + putstr16(vpszName, lpszName, cb); + LOGDEBUG(5,(" Finding resource \"%s\", type %s(%lx)\n", + lpszName, GetResourceType(lpszType), lpszType)); + } + + if (vpszName) { + if (HIWORD(lpszType) == 0) { // predefined resource + vpszType = (VPSZ)lpszType; // no doubt from MAKEINTRESOURCE + } else { + cb = strlen(lpszType)+1; + if (vpszType = GlobalAllocLock16(GMEM_MOVEABLE, cb, NULL)) { + putstr16(vpszType, lpszType, cb); + } + } + if (vpszType) { + PCBVDMFRAME pCBFrame; + + Parm16.WndProc.wParam = hmod16; + Parm16.WndProc.lParam = vpszName; + Parm16.WndProc.wMsg = LOWORD(vpszType); + Parm16.WndProc.hwnd = HIWORD(vpszType); + CallBack16(RET_FINDRESOURCE, &Parm16, 0, &vp); + pCBFrame = CBFRAMEPTR(CURRENTPTD()->vpCBStack); + wExpWinVer = pCBFrame->wGenUse1; + FREEVDMPTR(pCBFrame); + if (HIWORD(vpszType)) + GlobalUnlockFree16(vpszType); + } + if (HIWORD(vpszName)) + GlobalUnlockFree16(vpszName); + } + + if ((HRESI16)vp) { + pres = AddRes16(hmod16,wExpWinVer,(HRESI16)vp, lpszType); + } + return pres; +} + + +PRES LoadResource16(HMOD16 hmod16, PRES pres) +{ + VPVOID vp=0; + PARM16 Parm16; + + DBG_UNREFERENCED_PARAMETER(hmod16); + WOW32ASSERT(pres && hmod16 == pres->hmod16); + + Parm16.WndProc.wParam = pres->hmod16; + Parm16.WndProc.lParam = pres->hresinfo16; + + CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vp); + + if (pres->hresdata16 = (HRESD16)vp) + return pres; + + // BUGBUG -- On a LoadResource failure, WIN32 is not required to do a + // corresponding FreeResource, so our RES structure will hang around until + // task termination clean-up (which may be OK) -JTP + return NULL; +} + + +BOOL FreeResource16(PRES pres) +{ + VPVOID vp=0; + PARM16 Parm16; + + WOW32ASSERT(pres); + + Parm16.WndProc.wParam = pres->hresdata16; + CallBack16(RET_FREERESOURCE, &Parm16, 0, &vp); + + FreeRes16(pres); + + return (BOOL)vp; +} + + +LPBYTE LockResource16(register PRES pres) +{ + DWORD cb, cb16; + VPVOID vp=0; + PARM16 Parm16; + WOW32ASSERT(pres); + + Parm16.WndProc.wParam = pres->hresdata16; + CallBack16(RET_LOCKRESOURCE, &Parm16, 0, &vp); + + if (vp) { + PCBVDMFRAME pCBFrame; + + // Get size of 16-bit resource + pCBFrame = CBFRAMEPTR(CURRENTPTD()->vpCBStack); + cb16 = pCBFrame->wGenUse2 | (LONG)pCBFrame->wGenUse1 << 16; + + LOGDEBUG(5,(" Locking/converting resource type %s(%lx)\n", + GetResourceType(pres->lpszResType), pres->lpszResType)); + + // Handle known resource types here + if (pres->lpszResType) { + + switch((INT)pres->lpszResType) { + + + case (INT)RT_MENU: + // cb = ConvertMenu16(pres->wExeVer, NULL, vp, cb, cb16); + cb = cb16 * sizeof(WCHAR); // see SizeofResource16 + if (cb && (pres->pbResData = malloc_w(cb))) + ConvertMenu16(pres->wExeVer, pres->pbResData, vp, cb, cb16); + return pres->pbResData; + + case (INT)RT_DIALOG: + // cb = ConvertDialog16(NULL, vp, cb, cb16); + cb = cb16 * sizeof(WCHAR); // see SizeofResource16 + if (cb && (pres->pbResData = malloc_w(cb))) + ConvertDialog16(pres->pbResData, vp, cb, cb16); + return pres->pbResData; + + case (INT)RT_ACCELERATOR: + WOW32ASSERT(FALSE); // never should we come here. + return NULL; + +// case (INT)RT_GROUP_CURSOR: +// case (INT)RT_GROUP_ICON: +// GETOPTPTR(vp, 0, lp); +// return lp; + } + } + + // If we're still here, get desperate and return a simple 32-bit alias + GETVDMPTR(vp, cb16, pres->pbResData); + pres->flState |= RES_ALIASPTR; + return pres->pbResData; + } + // If we're still here, nothing worked + return NULL; +} + + +BOOL UnlockResource16(PRES pres) +{ + VPVOID vp=0; + PARM16 Parm16; + + WOW32ASSERT(pres); + + Parm16.WndProc.wParam = pres->hresdata16; + CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp); + + if (pres->pbResData && !(pres->flState & RES_ALIASPTR)) + free_w(pres->pbResData); + pres->pbResData = NULL; + pres->flState &= ~RES_ALIASPTR; + + return (BOOL)vp; +} + + +DWORD SizeofResource16(HMOD16 hmod16, PRES pres) +{ + VPVOID vp=0; + DWORD cbData; + PARM16 Parm16; + + DBG_UNREFERENCED_PARAMETER(hmod16); + + WOW32ASSERT(pres && hmod16 == pres->hmod16); + + Parm16.WndProc.wParam = pres->hmod16; + Parm16.WndProc.lParam = pres->hresinfo16; + + CallBack16(RET_SIZEOFRESOURCE, &Parm16, 0, &vp); + + cbData = (DWORD)vp; + + /* + * Adjust the size of the resource if they are different + * between NT and Windows + */ + // Handle known resource types here + if (pres->lpszResType) { + + switch((INT)pres->lpszResType) { + + case (INT)RT_MENU: + case (INT)RT_DIALOG: + +// If we need an exact count then we would have to enable this code +// but currently the count is only used in USER to alloc enough space +// in the client\server transition windows. +// WARNING - if this code is re-enabled you must also change LockResource16 +// CallBack16(RET_LOADRESOURCE, &Parm16, 0, &vpResLoad); +// CallBack16(RET_LOCKRESOURCE, vpResLoad, 0, &vp); +// if ((INT)pres->lpszResType == RT_MENU) +// cbData = (DWORD)ConvertMenu16(pres->wExeVer, NULL, vp, cbData); +// else +// cbData = (DWORD)ConvertDialog16(NULL, vp, cbData); +// CallBack16(RET_UNLOCKRESOURCE, &Parm16, 0, &vp); + + cbData = (DWORD)((DWORD)vp * sizeof(WCHAR)); + break; + + case (INT)RT_STRING: + cbData = (DWORD)((DWORD)vp * sizeof(WCHAR)); + break; + } + } + + return cbData; +} + +/* + * ConvertMenu16 + * + * If pmenu32 is NULL then its just a size query + * + * Returns the number of bytes in the CONVERTED menu + */ + +DWORD ConvertMenu16(WORD wExeVer, PBYTE pmenu32, VPBYTE vpmenu16, DWORD cb, DWORD cb16) +{ + WORD wVer, wOffset; + PBYTE pmenu16, pmenu16Save; + PBYTE pmenu32T = pmenu32; + + pmenu16 = GETVDMPTR(vpmenu16, cb16, pmenu16Save); + wVer = 0; + if (wExeVer >= 0x300) + wVer = GETWORD(pmenu16); + PUTWORD(pmenu32, wVer); // transfer versionNumber + wOffset = 0; + if (wExeVer >= 0x300) + wOffset = GETWORD(pmenu16); + PUTWORD(pmenu32, wOffset); // transfer offset + ADVGET(pmenu16, wOffset); // and advance by offset + ADVPUT(pmenu32, wOffset); + ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32 + cb = pmenu32 - pmenu32T; // pmenu32 will == 4 for size queries + cb += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16Save)); + + FREEVDMPTR(pmenu16Save); + RETURN(cb); +} + + + +/* + * ConvertMenuItems16 + * + * Returns the number of bytes in the CONVERTED menu + * Note: This can be called with ppmenu32==4 which means the caller is looking + * for the size to allocate for the 32-bit menu structure. + */ + +DWORD ConvertMenuItems16(WORD wExeVer, PPBYTE ppmenu32, PPBYTE ppmenu16, VPBYTE vpmenu16) +{ + INT cbAnsi; + DWORD cbTotal = 0; + UINT cbUni; + WORD wOption, wID; + PBYTE pmenu32 = *ppmenu32; + PBYTE pmenu16 = *ppmenu16; + PBYTE pmenu16T = pmenu16; + PBYTE pmenu32T = pmenu32; + + do { + if (wExeVer < 0x300) + wOption = GETBYTE(pmenu16); + else + wOption = GETWORD(pmenu16); + PUTWORD(pmenu32, wOption); // transfer mtOption + if (!(wOption & MF_POPUP)) { + wID = GETWORD(pmenu16); + PUTWORD(pmenu32, wID); // transfer mtID + } + cbAnsi = strlen(pmenu16)+1; + + // If this is an ownerdraw menu don't copy the ANSI memu string to + // Unicode. Put a 16:16 pointer into the 32-bit resource which + // points to menu string instead. User will place this pointer in + // MEASUREITEMSTRUCT->itemData before sending WM_MEASUREITEM. If it's a + // NULL string User will place a NULL in MEASUREITEMSTRUCT->itemData. + // Chess Master and Mavis Beacon Teaches Typing depend on this. + if ((wOption & MFT_OWNERDRAW) && *pmenu16) { + if (VALIDPUT(pmenu32)) { + *(DWORD UNALIGNED *)pmenu32 = vpmenu16 + (pmenu16 - pmenu16T); + } + cbUni = sizeof(DWORD); + } + else { + if (VALIDPUT(pmenu32)) { + RtlMultiByteToUnicodeN((LPWSTR)pmenu32, MAXULONG, (PULONG)&cbUni, pmenu16, cbAnsi); + + } + else { + cbUni = cbAnsi * sizeof(WCHAR); + } + } + + ADVGET(pmenu16, cbAnsi); + ADVPUT(pmenu32, cbUni); + ALIGNWORD(pmenu32); // this is the DIFFERENCE for WIN32 + if (wOption & MF_POPUP) + cbTotal += ConvertMenuItems16(wExeVer, &pmenu32, &pmenu16, vpmenu16+(pmenu16 - pmenu16T)); + + + } while (!(wOption & MF_END)); + + *ppmenu32 = pmenu32; + *ppmenu16 = pmenu16; + + return (pmenu32 - pmenu32T); +} + + +DWORD ConvertDialog16(PBYTE pdlg32, VPBYTE vpdlg16, DWORD cb, DWORD cb16) +{ + BYTE b; + WORD w; + DWORD dwStyle; + INT i, cItems; + UINT cbAnsi; + UINT cbUni; + PBYTE pdlg16, pdlg16Save; + PBYTE pdlg32T = pdlg32; + + pdlg16 = GETVDMPTR(vpdlg16, cb16, pdlg16Save); + dwStyle = GETDWORD(pdlg16); + PUTDWORD(pdlg32, dwStyle); // transfer style + PUTDWORD(pdlg32, 0); // Add NEW extended style + + cItems = GETBYTE(pdlg16); + PUTWORD(pdlg32, (WORD)cItems); // stretch count to WORD for WIN32 + for (i=0; i<4; i++) { + w = GETWORD(pdlg16); + PUTWORD(pdlg32, w); // transfer x & y, then cx & cy + } + + // + // the next three fields are all strings (possibly null) + // menuname, classname, captiontext + // the Menu string can be encoded as ff nn mm which + // means that the menu id is ordinal mmnn + // + + for (i=0; i<3; i++) { + if (i==0 && *pdlg16 == 0xFF) { // special encoding of szMenuName + GETBYTE(pdlg16); // advance past the ff byte + PUTWORD(pdlg32, 0xffff); // copy the f word + w = GETWORD(pdlg16); // get the menu ordinal + PUTWORD(pdlg32, w); // transfer it + } else { // ordinary string + cbAnsi = strlen(pdlg16)+1; + if (VALIDPUT(pdlg32)) { + RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi); + } else { + cbUni = cbAnsi * sizeof(WCHAR); + } + ADVGET(pdlg16, cbAnsi); + ADVPUT(pdlg32, cbUni); + ALIGNWORD(pdlg32); // fix next field alignment for WIN32 + } + } + + if (dwStyle & DS_SETFONT) { + w = GETWORD(pdlg16); + PUTWORD(pdlg32, w); // transfer cPoints + cbAnsi = strlen(pdlg16)+1; // then szTypeFace + if (VALIDPUT(pdlg32)) { + RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi); + } else { + cbUni = cbAnsi * sizeof(WCHAR); + } + ADVGET(pdlg16, cbAnsi); + ADVPUT(pdlg32, cbUni); + + } + while (cItems--) { + ALIGNDWORD(pdlg32); // items start on DWORD boundaries + PUTDWORD(pdlg32, FETCHDWORD(*(PDWORD)(pdlg16+sizeof(WORD)*5))); + PUTDWORD(pdlg32, 0); // Add NEW extended style + + for (i=0; i<5; i++) { + w = GETWORD(pdlg16); + PUTWORD(pdlg32, w); // transfer x & y, then cx & cy, then id + } + + ADVGET(pdlg16, sizeof(DWORD)); // skip style, which we already copied + + // + // get the class name could be string or encoded value + // win16 encoding scheme: class is 1 byte with bit 0x80 set, + // this byte == predefined class + // win32 encoding: a word of ffff, followed by class (word) + // + + if (*pdlg16 & 0x80) { + PUTWORD(pdlg32, 0xFFFF); // NEW encoding marker 0xFFFF + b = GETBYTE(pdlg16); // special encoding for predefined class + PUTWORD(pdlg32, (WORD)b); + } else { + cbAnsi = strlen(pdlg16)+1; + if (VALIDPUT(pdlg32)) { // transfer szClass + RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi); + } else { + cbUni = cbAnsi * sizeof(WCHAR); + } + ADVGET(pdlg16, cbAnsi); + ADVPUT(pdlg32, cbUni); + } + ALIGNWORD(pdlg32); // fix next field alignment for WIN32 + + // + // transfer the item text + // + + if (*pdlg16 == 0xFF) { // special encoding + GETBYTE(pdlg16); + PUTWORD(pdlg32, 0xFFFF); + w = GETWORD(pdlg16); + PUTWORD(pdlg32, w); + } else { + cbAnsi = strlen(pdlg16)+1; + if (VALIDPUT(pdlg32)) { // otherwise, just transfer szText + RtlMultiByteToUnicodeN((LPWSTR)pdlg32, MAXULONG, (PULONG)&cbUni, pdlg16, cbAnsi); + } else { + cbUni = cbAnsi * sizeof(WCHAR); + } + ADVGET(pdlg16, cbAnsi); + ADVPUT(pdlg32, cbUni); + } + ALIGNWORD(pdlg32); // fix next field alignment for WIN32 + + // + // transfer the create params + // + + b = GETBYTE(pdlg16); + + // + // If the template has create params, we're going to get tricky. + // When USER sends the WM_CREATE message to a control with + // createparams, lParam points to the CREATESTRUCT, which + // contains lpCreateParams. lpCreateParams needs to point + // to the createparams in the DLGTEMPLATE. In order to + // accomplish this, we store a 16:16 pointer to the 16-bit + // DLGTEMPLATE's createparams in the 32-bit DLGTEMPLATE's + // createparams. In other words, whenever the count of + // bytes of createparams is nonzero (b != 0), we put 4 + // bytes of createparams in the 32-bit DLGTEMPLATE that + // happen to be a 16:16 pointer to the createparams in + // the 16-bit DLGTEMPLATE. + // + // The other half of this magic is accomplished in USERSRV's + // xxxServerCreateDialog, which special-cases the creation + // of controls in a WOW dialog box. USERSRV will pass the + // DWORD pointed to by lpCreateParams instead of lpCreateParams + // to CreateWindow. This DWORD is the 16:16 pointer to the + // 16-bit DLGTEMPLATE's createparams. + // + // DaveHart 14-Mar-93 + // + + if (b != 0) { + + // store 32-bit createparams size (room for 16:16 ptr) + + PUTWORD(pdlg32, sizeof(pdlg16)); + //ALIGNDWORD(pdlg32); + + // store 16:16 pointer in 32-bit createparams + + PUTUDWORD(pdlg32, (DWORD)vpdlg16 + (DWORD)(pdlg16 - pdlg16Save)); + + // point pdlg16 past createparams + + ADVGET(pdlg16, b); + + } else { + + // there are no createparams, store size of zero. + + PUTWORD(pdlg32, 0); + //ALIGNDWORD(pdlg32); + } + + } + FREEVDMPTR(pdlg16Save); + RETURN(pdlg32 - pdlg32T); +} |