/*++ * * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WUCLASS.C * WOW32 16-bit User API support * * History: * Created 07-Mar-1991 by Jeff Parsons (jeffpar) --*/ #include "precomp.h" #pragma hdrstop MODNAME(wuclass.c); extern HANDLE ghInstanceUser32; extern WORD gUser16hInstance; /*++ BOOL GetClassInfo(, , ) HANDLE ; LPSTR ; LPWNDCLASS ; The %GetClassInfo% function retrieves information about a window class. The parameter identifies the instance of the application that created the class, and the parameter identifies the window class. If the function locates the specified window class, it copies the %WNDCLASS% data used to register the window class to the %WNDCLASS% structure pointed to by the parameter. Identifies the instance of the application that created the class. To retrieve information on classes defined by Windows (such as buttons or list boxes), set hInstance to NULL. Points to a null-terminated string that contains the name of the class to find. If the high-order word of this parameter is NULL, the low-order word is assumed to be a value returned by the %MAKEINTRESOURCE% macro used when the class was created. Points to the %WNDCLASS% structure that will receive the class information. The return value is TRUE if the function found a matching class and successfully copied the data; the return value is FALSE if the function did not find a matching class. The %lpszClassName%, %lpszMenuName%, and %hInstance% members of the %WNDCLASS% structure are set by this function. The menu name is not stored internally and cannot be returned. The class name is already known since it is passed to this function. The %GetClassInfo% function returns all other fields with the values used when the class was registered. --*/ ULONG FASTCALL WU32GetClassInfo(PVDMFRAME pFrame) { ULONG ul; PSZ psz2, pszClass; WNDCLASS t3; register PGETCLASSINFO16 parg16; WORD w; HINSTANCE hInst; PWC pwc = NULL; PWNDCLASS16 pwc16; CHAR szAtomName[WOWCLASS_ATOM_NAME]; GETARGPTR(pFrame, sizeof(GETCLASSINFO16), parg16); GETPSZIDPTR(parg16->f2, psz2); if ( HIWORD(psz2) == 0 ) { pszClass = szAtomName; GetAtomName( (ATOM)psz2, pszClass, WOWCLASS_ATOM_NAME ); } else { pszClass = psz2; } // map hInst user16 to hMod user32 if(parg16->f1 == gUser16hInstance) { hInst = ghInstanceUser32; } else { hInst = HMODINST32(parg16->f1); } ul = GETBOOL16(GetClassInfo(hInst, pszClass, &t3)); // This fine piece of hackery mimicks the difference between the class list // search algorithms in Win3.1 & SUR. Essentially SUR checks the private, // public, and global class lists while Win3.1 only checks the private and // global lists. Note we are striving for Win3.1 compatibility here -- not // always the logical thing! Finding an existing *stale* class breaks some // apps! Bug #31269 a-craigj, GerardoB // Restrict this hack to PageMaker 50a for now if(CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FAKECLASSINFOFAIL) { if(ul && hInst) { // if this class wasn't registered by this app, AND it's not a global // class, then it must have come from the public list and this app // wouldn't know about it on Win3.1 -- so lie and say it doesn't exist! // Note: The high word is the *hModule* which is what Win3.1 AND NT save // with the class internally (not the hInstance!) if((HIWORD(t3.hInstance) != HIWORD(hInst)) && !(t3.style & CS_GLOBALCLASS)) { WOW32WARNMSGF(0,("\nWOW:GetClassInfo force failure hack:\n class = '%s' wc.hInstance = %X app_hInst = %X\n\n", pszClass, t3.hInstance, hInst)); ul = 0; } } } if (ul) { // // If the class is a 'standard' class, replace the class proc // with a thunk proc // GETVDMPTR(parg16->f3, sizeof(WNDCLASS16), pwc16); STOREWORD(pwc16->style, t3.style); if (!_stricmp(pszClass, "edit")) { STOREWORD(pwc16->style, (FETCHWORD(pwc16->style) & ~CS_GLOBALCLASS)); } STOREDWORD(pwc16->vpfnWndProc, 0); // if this class was registered by WOW if ( (DWORD)t3.lpfnWndProc & WNDPROC_WOW ) { pwc16->vpfnWndProc = (VPWNDPROC)((DWORD)t3.lpfnWndProc & WNDPROC_MASK); // // if the actual selector had the high bit on then we turned off // bit 2 of the selector (the LDT bit, which will always be on) // if (!((DWORD)pwc16->vpfnWndProc & WOWCLASS_VIRTUAL_NOT_BIT31)) { pwc16->vpfnWndProc |= (WNDPROC_WOW | WOWCLASS_VIRTUAL_NOT_BIT31); } // we need to subtract out our WOW DWORDS for WOW classes // (see GCW_CBCLSEXTRA notes in RegisterClass()) STORESHORT(pwc16->cbClsExtra, t3.cbClsExtra - (2 * sizeof(DWORD))); } else { pwc16->vpfnWndProc = GetThunkWindowProc((DWORD)t3.lpfnWndProc, pszClass, NULL, NULL); STORESHORT(pwc16->cbClsExtra, t3.cbClsExtra); } #ifdef OLD_WAY if (parg16->f1 || !(pwc16->vpfnWndProc = GetThunkWindowProc((DWORD)t3.lpfnWndProc, pszClass, NULL, NULL))) { pwc = FindClass16(pszClass, (HINST16)parg16->f1); STOREDWORD(pwc16->vpfnWndProc, pwc->vpfnWndProc); } #endif STORESHORT(pwc16->cbWndExtra, t3.cbWndExtra); // Win3.1 copies the hInst passed in by the app into the WNDCLASS struct // unless hInst == NULL, in which case they copy user's hInst if((!parg16->f1) || (t3.hInstance == ghInstanceUser32)) { w = gUser16hInstance; } else { w = VALIDHMOD(t3.hInstance); if(w != BOGUSGDT) { w = parg16->f1; } } STOREWORD(pwc16->hInstance, w); w = GETHICON16(t3.hIcon); STOREWORD(pwc16->hIcon, w); w = GETHCURSOR16(t3.hCursor); STOREWORD(pwc16->hCursor, w); w = ((ULONG)t3.hbrBackground > COLOR_ENDCOLORS) ? GETHBRUSH16(t3.hbrBackground) : (WORD)t3.hbrBackground; STOREWORD(pwc16->hbrBackground, w); // These are strange assignments. We don't keep the class name or // menu name in 16-bit memory. For class name, USER32 just returns // the value which is passed as the second parameter, which works // MOST of the time; we do the same. For the menu name, USER32 just // returns the value which was passed when the class was registered. // There are some situations where these psz's might go out of scope // and no longer be valid when the application attempts to use them. // IF YOU EVER FIND AN APPLICATION WHICH GETS THE WRONG // THING AND IT FAILS BECAUSE OF IT, SOME NASTY HACKING WILL HAVE // TO BE DONE AND IT SHOULD BE DONE IN USER32 ALSO... // -BobDay // if ( pwc = FindClass16(pszClass, (HINST16)parg16->f1)) { STOREDWORD(pwc16->vpszMenuName, pwc->vpszMenu); } else { STOREDWORD(pwc16->vpszMenuName, 0 ); } STOREDWORD(pwc16->vpszClassName, parg16->f2); FLUSHVDMPTR(parg16->f3, sizeof(WNDCLASS16), pwc16); FREEVDMPTR(pwc16); } FREEPSZIDPTR(psz2); FREEARGPTR(parg16); RETURN(ul); } /*++ LONG GetClassLong(, ) HWND ; int ; The %GetClassLong% function retrieves the long value specified by the parameter from the %WNDCLASS% structure of the window specified by the parameter. Identifies the window. Specifies the byte offset of the value to be retrieved. It can also be the following value: GCL_WNDPROC Retrieves a long pointer to the window function. GCL_MENUNAME Retrieves a long pointer to the menu name. The return value specifies the value retrieved from the %WNDCLASS% structure. To access any extra four-byte values allocated when the window-class structure was created, use a positive byte offset as the index specified by the parameter. The first four-byte value in the extra space is at offset zero, the next four-byte value is at offset 4, and so on. --*/ ULONG FASTCALL WU32GetClassLong(PVDMFRAME pFrame) { ULONG ul, flag; INT iOffset; HWND hwnd; register PWW pww; register PWC pwc; register PGETCLASSLONG16 parg16; GETARGPTR(pFrame, sizeof(GETCLASSLONG16), parg16); // Make sure Win32 didn't change offsets for GCL constants #if (GCL_WNDPROC != (-24) || GCL_MENUNAME != (-8)) #error Win16/Win32 GCL constants differ #endif // Make sure the 16-bit app is requesting allowable offsets iOffset = INT32(parg16->f2); WOW32ASSERT(iOffset >= 0 || iOffset == GCL_WNDPROC || iOffset == GCL_MENUNAME); hwnd = HWND32(parg16->f1); switch (iOffset) { case GCL_WNDPROC: { DWORD dwProc32; dwProc32 = GetClassLong(hwnd, iOffset); if ( dwProc32 & WNDPROC_WOW ) { if ( HIWORD(dwProc32) == WNDPROC_HANDLE ) { // // Class has a window proc which is really a handle // to a proc. This happens when there is some // unicode to ansi transition or vice versa. // pww = FindPWW( hwnd, WOWCLASS_UNKNOWN); if ( pww == NULL ) { ul = 0; } else { ul = GetThunkWindowProc(dwProc32,NULL,pww,hwnd); } } else { // // Class already has a 16:16 address // ul = dwProc32 & WNDPROC_MASK; // // if the actual selector had the high bit on then we turned off // bit 2 of the selector (the LDT bit, which will always be on) // if (!(ul & WOWCLASS_VIRTUAL_NOT_BIT31)) { ul |= (WNDPROC_WOW | WOWCLASS_VIRTUAL_NOT_BIT31); } } } else { // // Class has a 32-bit proc, return an allocated thunk // pww = FindPWW(hwnd, WOWCLASS_UNKNOWN); if ( pww == NULL ) { ul = 0; } else { ul = GetThunkWindowProc(dwProc32,NULL,pww,hwnd); } } } break; case GCL_MENUNAME: if ((pww = FindPWW(hwnd, WOWCLASS_UNKNOWN)) && (WOWCLASS_WIN16 == pww->iClass) && (pwc = FindPWC(hwnd))) { ul = pwc->vpszMenu; } else { ul = 0; } break; case GCL_CBCLSEXTRA: ul = GetClassLong(hwnd, GCL_CBCLSEXTRA); // verify that this class was registered by WOW // (see GCW_CBCLSEXTRA notes in thunk for RegisterClass()) if(GetClassLong(hwnd, GCL_WNDPROC) & WNDPROC_WOW) { // get the bozo flag iOffset = ul - sizeof(DWORD); flag = GetClassLong(hwnd, iOffset); // if bozo app flag is set, get the value the app saved // otherwise good little apps get cbClsExtra if(flag) { iOffset -= sizeof(DWORD); ul = GetClassLong(hwnd, iOffset); } else { ul -= (2 * sizeof(DWORD)); // account for our WOW DWORDs } } break; default: ul = GetClassLong(hwnd, iOffset); break; } FREEARGPTR(parg16); RETURN(ul); } /*++ WORD GetClassWord(, ) HWND ; int ; The %GetClassWord% function retrieves the word that is specified by the parameter from the %WNDCLASS% structure of the window specified by the parameter. Identifies the window. Specifies the byte offset of the value to be retrieved. It can also be one of the following values: GCL_CBCLSEXTRA Tells how many bytes of additional class information you have. For information on how to access this memory, see the following "Comments" section. GCL_CBWNDEXTRA Tells how many bytes of additional window information you have. For information on how to access this memory, see the following<>Comments section. GCL_HBRBACKGROUND Retrieves a handle to the background brush. GCL_HCURSOR Retrieves a handle to the cursor. GCL_HICON Retrieves a handle to the icon. GCL_HMODULE Retrieves a handle to the module. GCL_STYLE Retrieves the window-class style bits. The return value specifies the value retrieved from the %WNDCLASS% structure. To access any extra two-byte values allocated when the window-class structure was created, use a positive byte offset as the index specified by the parameter, starting at zero for the first two-byte value in the extra space, 2 for the next two-byte value and so on. --*/ ULONG FASTCALL WU32GetClassWord(PVDMFRAME pFrame) { ULONG ul, flag; HWND hwnd; INT iOffset; register PGETCLASSWORD16 parg16; GETARGPTR(pFrame, sizeof(GETCLASSWORD16), parg16); // Make sure Win32 didn't change offsets #if (GCL_HBRBACKGROUND != (-10) || GCL_HCURSOR != (-12) || GCL_HICON != (-14) || GCL_HMODULE != (-16) || GCL_CBWNDEXTRA != (-18) || GCL_CBCLSEXTRA != (-20) || GCL_STYLE != (-26)) #error Win16/Win32 class-word constants differ #endif // Make sure the 16-bit app is requesting allowable offsets // (It's just assertion code, so it doesn't have to be pretty! -JTP) iOffset = INT32(parg16->f2); WOW32ASSERT(iOffset >= 0 || iOffset == GCL_HBRBACKGROUND || iOffset == GCL_HCURSOR || iOffset == GCL_HICON || iOffset == GCL_HMODULE || iOffset == GCL_CBWNDEXTRA || iOffset == GCL_CBCLSEXTRA || iOffset == GCL_STYLE || iOffset == GCW_ATOM); hwnd = HWND32(parg16->f1); switch(iOffset) { case GCL_HBRBACKGROUND: ul = GetClassLong(hwnd, iOffset); if (ul > COLOR_ENDCOLORS) ul = GETHBRUSH16(ul); break; case GCL_HCURSOR: ul = GETHCURSOR16((HAND32)GetClassLong(hwnd, iOffset)); break; case GCL_HICON: ul = GETHICON16((HAND32)GetClassLong(hwnd, iOffset)); break; case GCL_HMODULE: ul = GetGCL_HMODULE(hwnd); break; case GCL_CBWNDEXTRA: case GCL_STYLE: ul = GetClassLong(hwnd, iOffset); break; case GCL_CBCLSEXTRA: ul = GetClassLong(hwnd, GCL_CBCLSEXTRA); // verify that this class was registered by WOW // (see GCW_CBCLSEXTRA notes in thunk for RegisterClass()) if(GetClassLong(hwnd, GCL_WNDPROC) & WNDPROC_WOW) { // get the bozo flag iOffset = ul - sizeof(DWORD); flag = GetClassLong(hwnd, iOffset); // if bozo app flag is set, get the value the app saved // otherwise good little apps get cbClsExtra if(flag) { iOffset -= sizeof(DWORD); ul = GetClassWord(hwnd, iOffset); } else { ul -= (2 * sizeof(DWORD)); // account for our WOW DWORDs } } break; default: ul = GetClassWord(hwnd, iOffset); break; } FREEARGPTR(parg16); RETURN(ul); } /*++ BOOL RegisterClass() LPWNDCLASS ; The %RegisterClass% function registers a window class for subsequent use in calls to the %CreateWindow% function. The window class has the attributes defined by the contents of the structure pointed to by the parameter. If two classes with the same name are registered, the second attempt fails and the information for that class is ignored. Points to a %WNDCLASS% structure. The structure must be filled with the appropriate class attributes before being passed to the function. See the following "Comments" section for details. The return value specifies whether the window class is registered. It is TRUE if the class is registered. Otherwise, it is FALSE. The callback function must use the Pascal calling conventions and must be declared %FAR%. Callback Function: BOOL FAR PASCAL (, , , ) HWND ; WORD ; WORD; DWORD; is a placeholder for the application-supplied function name. The actual name must be exported by including it in an %EXPORTS% statement in the application's module-definition file. Specifies the message number. Specifies additional message-dependent information. Specifies additional message-dependent information. The window function returns the result of the message processing. The possible return values depend on the actual message sent. --*/ ULONG FASTCALL WU32RegisterClass(PVDMFRAME pFrame) { ULONG ul; WNDCLASS t1; VPSZ vpszMenu; PSZ pszMenu; PSZ pszClass; register PREGISTERCLASS16 parg16; CHAR szAtomName[WOWCLASS_ATOM_NAME]; WC wc; GETARGPTR(pFrame, sizeof(REGISTERCLASS16), parg16); GETWNDCLASS16(parg16->vpWndClass, &t1); // Fix up the window words for apps that have hardcode values and did not // use the value from GetClassInfo when superclassing system proc. // Some items have been expanded from a WORD to a DWORD bug 22014 // t1.cbWndExtra = (t1.cbWndExtra + 3) & ~3; // Some apps call SetClassWord()and SetClassLong() with the GCW_CBCLSEXTRA // offset specified and clobber the cbClsExtra in the class structure on // Win3.1 and retreive the value later (Wall Street Analyst, PC Anywhere are // known culprits). Win'95 allows this for apps whose WinVer is less than // 4.0. NT can't allow it without exposing the kernel to problems. What // we do is add 2 extra DWORDs of class extra bytes to any classes that are // created by WOW. We use the 1st DWORD to save the value the app passed to // us and the 2nd DWORD as a flag that specifies that the bozo app did this. // When an app calls GetClassXXXX(GWC_CBCLSEXTRA) we test the flag and // return the appropriate value -- either cbClsExtra or the bozo value. t1.cbClsExtra += (2 * sizeof(DWORD)); vpszMenu = (VPSZ)t1.lpszMenuName; if (HIWORD(t1.lpszMenuName) != 0) { GETPSZPTR(t1.lpszMenuName, pszMenu); t1.lpszMenuName = pszMenu; } if (HIWORD(t1.lpszClassName) == 0) { pszClass = szAtomName; GetAtomName( (ATOM)t1.lpszClassName, pszClass, WOWCLASS_ATOM_NAME); } else { GETPSZPTR(t1.lpszClassName, pszClass); } t1.lpszClassName = pszClass; ul = 0; wc.vpszMenu = vpszMenu; wc.vpfnWndProc = (VPWNDPROC)t1.lpfnWndProc; t1.lpfnWndProc = (WNDPROC)((DWORD)t1.lpfnWndProc | WNDPROC_WOW); // // FEATURE-O-RAMA // // if the selector already has the high bit on then turn off bit 2 // of the selector (the LDT bit, which should always be on). we // need a way to not blindly strip off the high bit in our wndproc. // if ((DWORD)wc.vpfnWndProc & WNDPROC_WOW) { WOW32ASSERT((DWORD)t1.lpfnWndProc & WOWCLASS_VIRTUAL_NOT_BIT31); (DWORD)t1.lpfnWndProc &= ~WOWCLASS_VIRTUAL_NOT_BIT31; } // Validate hbrBackground, because apps can pass an invalid handle. // The GetGDI32 returns a non-null value even if h16 is invalid. // // if hbrBackground is not valid we set it to NULL if the apps // ExpWinVer is < 3.1. This behaviour is identical to WIN31 behaviour. // // We need to do this validation here because USER32 will fail // RegisterClass() if hbrBackground is not valid. // // known culprits: QuickCase:W (that comes with QcWin) // class "iconbutton". if ((DWORD)t1.hbrBackground > (DWORD)(COLOR_ENDCOLORS) && GetObjectType(t1.hbrBackground) != OBJ_BRUSH) { if ((WORD)W32GetExpWinVer((HANDLE) LOWORD(t1.hInstance) ) < 0x030a) t1.hbrBackground = (HBRUSH)NULL; } ul = GETBOOL16((pfnOut.pfnRegisterClassWOWA)(&t1, (DWORD *)&wc)); if (!ul) { LOGDEBUG(LOG_ALWAYS,("WOW: RegisterClass failed (\"%s\")\n", (LPSZ)pszClass)); // WOW32ASSERT(ul); } FREEPSZPTR(pszClass); FREEPSZPTR(pszMenu); FREEARGPTR(parg16); RETURN(ul); } /*++ LONG SetClassLong(, , ) HWND ; int ; DWORD ; The %SetClassLong% function replaces the long value specified by the parameter in the %WNDCLASS% structure of the window specified by the parameter. Identifies the window. Specifies the byte offset of the word to be changed. It can also be one of the following values: GCL_MENUNAME Sets a new long pointer to the menu GCL_WNDPROC Sets a new long pointer to the window function. Specifies the replacement value. The return value specifies the previous value of the specified long integer. If the %SetClassLong% function and GCL_WNDPROC index are used to set a window function, the given function must have the window-function form and be exported in the module-definition file. See the %RegisterClass% function earlier in this chapter for details. Calling %SetClassLong% with the GCL_WNDPROC index creates a subclass of the window class that affects all windows subsequently created with the class. See Chapter 1, Window Manager Interface Functions, for more information on window subclassing. An application should not attempt to create a window subclass for standard Windows controls such as combo boxes and buttons. To access any extra two-byte values allocated when the window-class structure was created, use a positive byte offset as the index specified by the parameter, starting at zero for the first two-byte value in the extra space, 2 for the next two-byte value and so on. --*/ ULONG FASTCALL WU32SetClassLong(PVDMFRAME pFrame) { ULONG ul, flag; INT iOffset; PSZ pszMenu; register PWC pwc; register PSETCLASSLONG16 parg16; GETARGPTR(pFrame, sizeof(SETCLASSLONG16), parg16); // Make sure Win32 didn't change offsets for GCL constants #if (GCL_MENUNAME != (-8) || GCL_WNDPROC != (-24)) #error Win16/Win32 GCL constants differ #endif // Make sure the 16-bit app is requesting allowable offsets iOffset = INT32(parg16->f2); WOW32ASSERT(iOffset >= 0 || iOffset == GCL_WNDPROC || iOffset == GCL_MENUNAME); ul = 0; switch (iOffset) { case GCL_WNDPROC: { DWORD dwWndProc32Old; DWORD dwWndProc32New; PWW pww; // Look to see if the new 16:16 proc is a thunk for a 32-bit proc. dwWndProc32New = IsThunkWindowProc(LONG32(parg16->f3), NULL ); if ( dwWndProc32New != 0 ) { // // They are attempting to set the window proc to an existing // 16-bit thunk that is really just a thunk for a 32-bit // routine. We can just set it back to the 32-bit routine. // dwWndProc32Old = SetClassLong(HWND32(parg16->f1), GCL_WNDPROC, (LONG)dwWndProc32New); SETWC(HWND32(parg16->f1), GCL_WOWvpfnWndProc, 0); } else { // // They are attempting to set it to a real 16:16 proc. // LONG l; l = LONG32(parg16->f3); // // FEATURE-O-RAMA // // if the selector already has the high bit on then turn off bit 2 // of the selector (the LDT bit, which should always be on). we // need a way to not blindly strip off the high bit in our wndproc. // if (l & WNDPROC_WOW) { WOW32ASSERT(l & WOWCLASS_VIRTUAL_NOT_BIT31); l &= ~WOWCLASS_VIRTUAL_NOT_BIT31; } dwWndProc32Old = SetClassLong(HWND32(parg16->f1), GCL_WNDPROC, l | WNDPROC_WOW ); SETWC(HWND32(parg16->f1), GCL_WOWvpfnWndProc, LONG32(parg16->f3)); } if ( dwWndProc32Old & WNDPROC_WOW ) { if ( HIWORD(dwWndProc32Old) == WNDPROC_HANDLE ) { // // If the return value is a handle, then just thunk it. // pww = FindPWW(HWND32(parg16->f1), WOWCLASS_UNKNOWN); if ( pww == NULL ) { ul = 0; } else { ul = GetThunkWindowProc(dwWndProc32Old, NULL, pww, HWND32(parg16->f1)); } } else { // // Previous proc was a 16:16 proc // ul = dwWndProc32Old & WNDPROC_MASK; // // if the actual selector had the high bit on then we turned off // bit 2 of the selector (the LDT bit, which will always be on) // if (!(ul & WOWCLASS_VIRTUAL_NOT_BIT31)) { ul |= (WNDPROC_WOW | WOWCLASS_VIRTUAL_NOT_BIT31); } } } else { // // Previous proc was a 32-bit proc, use an allocated thunk // pww = FindPWW(HWND32(parg16->f1), WOWCLASS_UNKNOWN); if ( pww == NULL ) { ul = 0; } else { ul = GetThunkWindowProc(dwWndProc32Old, NULL, pww, HWND32(parg16->f1)); } } } break; case GCL_MENUNAME: if (pwc = FindPWC(HWND32(parg16->f1))) { ul = pwc->vpszMenu; GETPSZPTR(parg16->f3, pszMenu); SETWC(HWND32(parg16->f1), GCL_WOWvpszMenu, parg16->f3); SetClassLong(HWND32(parg16->f1), GCL_MENUNAME, (LONG)pszMenu); FREEPSZPTR(pszMenu); } break; case GCL_CBCLSEXTRA: // apps shouldn't do this but of course some do! // (see GCW_CBCLSEXTRA notes in thunk for RegisterClass()) WOW32WARNMSG(0, ("WOW:SetClassLong(): app changing cbClsExtra!")); // only allow this to be set by classes registered via WOW if(GetClassLong(HWND32(parg16->f1), GCL_WNDPROC) & WNDPROC_WOW) { ul = WORD32(parg16->f3); // set the bozo flag & save the value the app passed us iOffset = GetClassLong(HWND32(parg16->f1), GCL_CBCLSEXTRA); iOffset -= sizeof(DWORD); flag = SetClassLong(HWND32(parg16->f1), iOffset, 1); iOffset -= sizeof(DWORD); ul = SetClassLong(HWND32(parg16->f1), iOffset, ul); // SetClassLong() returns the "previous" value. // if this is the first time the app pulls this stunt it will // get back the original cbClsExtra, otherwise it will get back // the value it stored here on the previous call. if(!flag) { ul = iOffset; // the WOW DWORDs have already been subtracted } } else { ul = 0; // no can do for non-WOW classes } break; default: ul = SetClassLong(HWND32(parg16->f1), iOffset, LONG32(parg16->f3)); break; } FREEARGPTR(parg16); RETURN(ul); } /*++ WORD SetClassWord(, , ) HWND ; int ; WORD ; The %SetClassWord% function replaces the word specified by the parameter in the %WNDCLASS% structure of the window specified by the parameter. Identifies the window. Specifies the byte offset of the word to be changed. It can also be one of the following values: GCL_CBCLSEXTRA Sets two new bytes of additional window-class data. GCL_CBWNDEXTRA Sets two new bytes of additional window-class data. GCL_HBRBACKGROUND Sets a new handle to a background brush. GCL_HCURSOR Sets a new handle to a cursor. GCL_HICON Sets a new handle to an icon. GCL_STYLE Sets a new style bit for the window class. Specifies the replacement value. The return value specifies the previous value of the specified word. The %SetClassWord% function should be used with care. For example, it is possible to change the background color for a class by using %SetClassWord%, but this change does not cause all windows belonging to the class to be repainted immediately. To access any extra four-byte values allocated when the window-class structure was created, use a positive byte offset as the index specified by the parameter, starting at zero for the first four-byte value in the extra space, 4 for the next four-byte value and so on. --*/ ULONG FASTCALL WU32SetClassWord(PVDMFRAME pFrame) { ULONG ul, flag; HWND hwnd; INT iOffset; register PSETCLASSWORD16 parg16; GETARGPTR(pFrame, sizeof(SETCLASSWORD16), parg16); // Make sure Win32 didn't change offsets #if (GCL_HBRBACKGROUND != (-10) || GCL_HCURSOR != (-12) || GCL_HICON != (-14) || GCL_CBWNDEXTRA != (-18) || GCL_CBCLSEXTRA != (-20) || GCL_STYLE != (-26)) #error Win16/Win32 GCW constants differ #endif // Make sure the 16-bit app is requesting allowable offsets // (It's just assertion code, so it doesn't have to be pretty! -JTP) iOffset = INT32(parg16->f2); WOW32ASSERT(iOffset >= 0 || iOffset == GCL_HBRBACKGROUND || iOffset == GCL_HCURSOR || iOffset == GCL_HICON || iOffset == GCL_CBWNDEXTRA || iOffset == GCL_CBCLSEXTRA || iOffset == GCL_STYLE) hwnd = HWND32(parg16->f1); ul = WORD32(parg16->f3); switch(iOffset) { case GCL_HBRBACKGROUND: if (ul > COLOR_ENDCOLORS) ul = (LONG) HBRUSH32(ul); ul = SetClassLong(hwnd, iOffset, (LONG) ul); if (ul > COLOR_ENDCOLORS) ul = GETHBRUSH16(ul); break; case GCL_HCURSOR: ul = GETHCURSOR16(SetClassLong(hwnd, iOffset, (LONG)HCURSOR32(ul))); break; case GCL_HICON: ul = GETHICON16(SetClassLong(hwnd, iOffset, (LONG)HICON32(ul))); break; case GCL_HMODULE: ul = 0; // not allowed to set this break; case GCL_CBWNDEXTRA: case GCL_STYLE: ul = SetClassLong(hwnd, iOffset, (LONG)ul); break; case GCL_CBCLSEXTRA: // apps shouldn't do this but of course some do! // (see GCW_CBCLSEXTRA notes in thunk for RegisterClass()) WOW32WARNMSG(0, ("WOW:SetClassWord(): app changing cbClsExtra!")); // only allow this to be set by classes registered via WOW if(GetClassLong(hwnd, GCL_WNDPROC) & WNDPROC_WOW) { // set the bozo flag iOffset = GetClassLong(hwnd, GCL_CBCLSEXTRA); iOffset -= sizeof(DWORD); flag = SetClassLong(hwnd, iOffset, 1); // save the value the app passed iOffset -= sizeof(DWORD); ul = (WORD)SetClassWord(hwnd, iOffset, LOWORD(ul)); // SetClassWord() returns the "previous" value. // if this is the first time the app pulls this stunt it will // get back the original cbClsExtra, otherwise it will get back // the value it stored here on the previous call. if(!flag) { ul = iOffset; // the WOW DWORDs have already been subtracted } } else { ul = 0; // no can do for non-WOW classes } break; default: ul = SetClassWord(hwnd, iOffset, (WORD)ul); break; } FREEARGPTR(parg16); RETURN(ul); } /*++ BOOL UnregisterClass(, ) The %UnregisterClass% function removes the window class specified by from the window-class table, freeing the storage required for the class. Points to a null-terminated string containing the class name. This class name must have been previously registered by calling the RegisterClass function with a valid hInstance field in the %WNDCLASS% structure parameter. Predefined classes, such as dialog-box controls, may not be unregistered. Identifies the instance of the module that created the class. The return value is TRUE if the function successfully removed the window class from the window-class table. It is FALSE if the class could not be found or if a window exists that was created with the class. Before using this function, destroy all windows created with the specified class. --*/ ULONG FASTCALL WU32UnregisterClass(PVDMFRAME pFrame) { ULONG ul; PSZ psz1, pszClass; register PUNREGISTERCLASS16 parg16; CHAR szAtomName[WOWCLASS_ATOM_NAME]; GETARGPTR(pFrame, sizeof(UNREGISTERCLASS16), parg16); GETPSZIDPTR(parg16->vpszClass, psz1); if ( HIWORD(psz1) == 0 ) { pszClass = szAtomName; GetAtomName( (ATOM)psz1, pszClass, WOWCLASS_ATOM_NAME ); } else { pszClass = psz1; } #ifdef WOWEDIT if (!_stricmp(pszClass, "Edit")) pszClass = "WOWEdit"; #endif ul = GETBOOL16(UnregisterClass( pszClass, HMODINST32(parg16->hInstance) )); FREEPSZPTR(psz1); FREEARGPTR(parg16); RETURN(ul); }