/*++ * * WOW v1.0 * * Copyright (c) 1991, Microsoft Corporation * * WUSER.C * WOW32 16-bit User API support * * History: * Created 07-Mar-1991 by Jeff Parsons (jeffpar) --*/ #define OEMRESOURCE #include "precomp.h" #pragma hdrstop MODNAME(wuser.c); extern HANDLE hmodWOW32; /*++ HDC BeginPaint(, ) HWND ; LPPAINTSTRUCT ; The %BeginPaint% function prepares the given window for painting and fills the paint structure pointed to by the parameter with information about the painting. The paint structure contains a handle to the device context for the window, a %RECT% structure that contains the smallest rectangle that completely encloses the update region, and a flag that specifies whether or not the background has been erased. The %BeginPaint% function automatically sets the clipping region of the device context to exclude any area outside the update region. The update region is set by the %InvalidateRect% or %InvalidateRgn% functions and by the system after sizing, moving, creating, scrolling, or any other operation that affects the client area. If the update region is marked for erasing, %BeginPaint% sends a WM_ERASEBKGND message to the window. An application should not call the %BeginPaint% function except in response to a WM_PAINT message. Each %BeginPaint% call must have a matching call to the %EndPaint% function. Identifies the window to be repainted. Points to the %PAINTSTRUCT% structure that is to receive painting information, such as the device context for the window and the update rectangle. The return value identifies the device context for the specified window. If the caret is in the area to be painted, the %BeginPaint% function automatically hides the caret to prevent it from being erased. --*/ ULONG FASTCALL WU32BeginPaint(PVDMFRAME pFrame) { ULONG ul; PAINTSTRUCT t2; register PBEGINPAINT16 parg16; VPVOID vpPaint; GETARGPTR(pFrame, sizeof(BEGINPAINT16), parg16); vpPaint = parg16->vpPaint; ul = GETHDC16(BeginPaint( HWND32(parg16->hwnd), &t2 )); putpaintstruct16(vpPaint, &t2); W32FixPaintRect (vpPaint, &t2); FREEARGPTR(parg16); RETURN(ul); } /*++ HICON CreateIcon(, , , , , , ) HANDLE ; int ; int ; BYTE ; BYTE ; LPSTR ; LPSTR ; This function creates an icon that has specified width, height, colors, and bit patterns. Identifies an instance of the module creating the icon. Specifies the width in pixels of the icon. Specifies the height in pixels of the icon. Specifies the number of planes in the XOR mask of the icon. Specifies the number of bits per pixel in the XOR mask of the icon. Points to an array of bytes that contains the bit values for the AND mask of the icon. This array must specify a monochrome mask. Points to an array of bytes that contains the bit values for the XOR mask of the icon. This can be the bits of a monochrome or device-dependent color bitmap. The return value identifies an icon if the function is successful. Otherwise, it is NULL. --*/ ULONG FASTCALL WU32CreateIcon(PVDMFRAME pFrame) { ULONG ul; register PCREATEICON16 parg16; int nWidth; int nHeight; BYTE nPlanes; BYTE nBitsPixel; DWORD nBytesAND; DWORD nBytesXOR; LPBYTE lpBitsAND; LPBYTE lpBitsXOR; int ScanLen16; HANDLE h32; HAND16 h16; HAND16 hInst16; GETARGPTR(pFrame, sizeof(CREATEICON16), parg16); hInst16 = parg16->f1; nWidth = INT32(parg16->f2); nHeight = INT32(parg16->f3); /* ** Convert the AND mask bits */ nPlanes = 1; /* MONOCHROME BITMAP */ nBitsPixel = 1; /* MONOCHROME BITMAP */ ScanLen16 = (((nWidth*nBitsPixel)+15)/16) * 2 ; // bytes/scan in 16 bit world nBytesAND = ScanLen16*nHeight*nPlanes; GETVDMPTR(parg16->f6, nBytesAND, lpBitsAND); /* ** Convert the XOR mask bits */ nPlanes = BYTE32(parg16->f4); nBitsPixel = BYTE32(parg16->f5); ScanLen16 = (((nWidth*nBitsPixel)+15)/16) * 2 ; // bytes/scan in 16 bit world nBytesXOR = ScanLen16*nHeight*nPlanes; GETVDMPTR(parg16->f7, nBytesXOR, lpBitsXOR); h32 = (HANDLE)CreateIcon(HMODINST32(hInst16), nWidth, nHeight, nPlanes, nBitsPixel, lpBitsAND, lpBitsXOR); if (h32) { h16 = (HAND16)W32Create16BitCursorIcon(hInst16, nWidth/2, nHeight/2, nWidth, nHeight, nPlanes, nBitsPixel, lpBitsAND, lpBitsXOR, nBytesAND, nBytesXOR); ul = SetupCursorIconAlias(hInst16, h32, h16, HANDLE_TYPE_ICON, NULL, (WORD)NULL); } else { ul = 0; } FREEPSZPTR(lpBitsAND); FREEPSZPTR(lpBitsXOR); FREEARGPTR(parg16); RETURN(ul); } /*++ BOOL DestroyIcon() HICON ; This function destroys an icon that was previously created by the %CreateIcon% function and frees any memory that the icon occupied. It should not be used to destroy any icon that was not created with the %CreateIcon% function. Identifies the icon to be destroyed. The icon must not be in current use. The return value is TRUE if the function was successful. It is FALSE if the function failed. --*/ ULONG FASTCALL WU32DestroyIcon(PVDMFRAME pFrame) { ULONG ul; register PDESTROYICON16 parg16; GETARGPTR(pFrame, sizeof(DESTROYICON16), parg16); if (ul = GETBOOL16(DestroyIcon(HICON32(parg16->f1)))) FREEHICON16(parg16->f1); FREEARGPTR(parg16); RETURN(ul); } ULONG FASTCALL WU32DragDetect(PVDMFRAME pFrame) { ULONG ul; POINT pt; register PDRAGDETECT16 parg16; GETARGPTR(pFrame, sizeof(*parg16), parg16); COPYPOINT16(parg16->pt, pt); ul = (ULONG) DragDetect( HWND32(parg16->hwnd), pt ); FREEARGPTR(parg16); RETURN(ul); } /*++ void DrawFocusRect(, ) HDC ; LPRECT ; The %DrawFocusRect% function draws a rectangle in the style used to indicate focus. Identifies the device context. Points to a %RECT% structure that specifies the coordinates of the rectangle to be drawn. This function does not return a value. Since this is an XOR function, calling this function a second time with the same rectangle removes the rectangle from the display. The rectangle drawn by this function cannot be scrolled. To scroll an area containing a rectangle drawn by this function, call %DrawFocusRect% to remove the rectangle from the display, scroll the area, and then call %DrawFocusRect% to draw the rectangle in the new position. --*/ ULONG FASTCALL WU32DrawFocusRect(PVDMFRAME pFrame) { RECT t2; register PDRAWFOCUSRECT16 parg16; GETARGPTR(pFrame, sizeof(DRAWFOCUSRECT16), parg16); WOW32VERIFY(GETRECT16(parg16->f2, &t2)); DrawFocusRect( HDC32(parg16->f1), &t2 ); FREEARGPTR(parg16); RETURN(0); } /*++ int DrawText(, , , , ) HDC ; LPSTR ; int ; LPRECT ; WORD ; The %DrawText% function draws formatted text in the rectangle specified by the parameter. It formats text by expanding tabs into appropriate spaces, justifying text to the left, right, or center of the given rectangle, and breaking text into lines that fit within the given rectangle. The type of formatting is specified by the parameter. The %DrawText% function uses the device context's selected font, text color, and background color to draw the text. Unless the DT_NOCLIP format is used, %DrawText% clips the text so that the text does not appear outside the given rectangle. All formatting is assumed to have multiple lines unless the DT_SINGLELINE format is given. Identifies the device context. Points to the string to be drawn. If the parameter is -1, the string must be null-terminated. Specifies the number of bytes in the string. If is -1, then is assumed to be a long pointer to a null-terminated string and %DrawText% computes the character count automatically. Points to a %RECT% structure that contains the rectangle (in logical coordinates) in which the text is to be formatted. Specifies the method of formatting the text. It can be any combination of the following values: DT_BOTTOM Specifies bottom-justified text. This value must be combined with DT_SINGLELINE. DT_CALCRECT Determines the width and height of the rectangle. If there are multiple lines of text, %DrawText% will use the width of the rectangle pointed to by the parameter and extend the base of the rectangle to bound the last line of text. If there is only one line of text, %DrawText% will modify the right side of the rectangle so that it bounds the last character in the line. In either case, %DrawText% returns the height of the formatted text but does not draw the text. DT_CENTER Centers text horizontally. DT_EXPANDTABS Expands tab characters. The default number of characters per tab is eight. DT_EXTERNALLEADING Includes the font external leading in line height. Normally, external leading is not included in the height of a line of text. DT_LEFT Aligns text flush-left. DT_NOCLIP Draws without clipping. %DrawText% is somewhat faster when DT_NOCLIP is used. DT_NOPREFIX Turns off processing of prefix characters. Normally, %DrawText% interprets the mnemonic-prefix character & as a directive to underscore the character that follows, and the mnemonic-prefix characters && as a directive to print a single &. By specifying DT_NOPREFIX, this processing is turned off. DT_RIGHT Aligns text flush-right. DT_SINGLELINE Specifies single line only. Carriage returns and linefeeds do not break the line. DT_TABSTOP Sets tab stops. The high-order byte of the parameter is the number of characters for each tab. The default number of characters per tab is eight. DT_TOP Specifies top-justified text (single line only). DT_VCENTER Specifies vertically centered text (single line only). DT_WORDBREAK Specifies word breaking. Lines are automatically broken between words if a word would extend past the edge of the rectangle specified by the parameter. A carriage return/line sequence will also break the line. Note that the DT_CALCRECT, DT_EXTERNALLEADING, DT_INTERNAL, DT_NOCLIP, and DT_NOPREFIX values cannot be used with the DT_TABSTOP value: The return value specifies the height of the text. If the selected font is too large for the specified rectangle, the %DrawText% function does not attempt to substitute a smaller font. --*/ ULONG FASTCALL WU32DrawText(PVDMFRAME pFrame) { ULONG ul; PSTR pstr2; RECT t4; register PDRAWTEXT16 parg16; GETARGPTR(pFrame, sizeof(DRAWTEXT16), parg16); GETVARSTRPTR(parg16->vpString, INT32(parg16->nCount), pstr2); WOW32VERIFY(GETRECT16(parg16->vpRect, &t4)); ul = GETINT16(DrawText( HDC32(parg16->hdc), pstr2, INT32(parg16->nCount), &t4, WORD32(parg16->wFormat) )); PUTRECT16(parg16->vpRect, &t4); FREESTRPTR(pstr2); FREEARGPTR(parg16); RETURN(ul); } /*++ void EndPaint(, ) HWND ; LPPAINTSTRUCT ; The %EndPaint% function marks the end of painting in the given window. The %EndPaint% function is required for each call to the %BeginPaint% function, but only after painting is complete. Identifies the window that is repainted. Points to a %PAINTSTRUCT% structure that contains the painting information retrieved by the %BeginPaint% function. This function does not return a value. If the caret was hidden by the %BeginPaint% function, %EndPaint% restores the caret to the screen. --*/ ULONG FASTCALL WU32EndPaint(PVDMFRAME pFrame) { PAINTSTRUCT t2; register PENDPAINT16 parg16; GETARGPTR(pFrame, sizeof(ENDPAINT16), parg16); getpaintstruct16(parg16->vpPaint, &t2); EndPaint( HWND32(parg16->hwnd), &t2 ); FREEARGPTR(parg16); RETURN(0); } #define MAX_WIN16_PROP_TEXT 256 /* Taken from Win 3.1 - winprops.c */ static VPVOID vpEnumPropsProc; static VPVOID vpString; INT W32EnumPropsFunc( HWND hwnd, LPSTR lpString, HANDLE hData ) { PARM16 Parm16; LONG lReturn; VPVOID vp; if ( HIWORD(lpString) == 0 ) { vp = (DWORD)lpString; } else { INT cb; vp = vpString; cb = strlen(lpString)+1; if ( cb > MAX_WIN16_PROP_TEXT-1 ) { cb = MAX_WIN16_PROP_TEXT-1; } putstr16(vpString, lpString, cb); } Parm16.EnumPropsProc.hwnd = GETHWND16(hwnd); Parm16.EnumPropsProc.vpString = vp; Parm16.EnumPropsProc.hData = GETHANDLE16(hData); CallBack16(RET_ENUMPROPSPROC, &Parm16, vpEnumPropsProc, (PVPVOID)&lReturn); return (SHORT)lReturn; } /*++ int EnumProps(, ) HWND ; FARPROC ; The %EnumProps% function enumerates all entries in the property list of the specified window. It enumerates the entries by passing them, one by one, to the callback function specified by . %EnumProps% continues until the last entry is enumerated or the callback function returns zero. Identifies the window whose property list is to be enumerated. Specifies the procedure-instance address of the callback function. See the following Comments section for details. The return value specifies the last value returned by the callback function. It is -1 if the function did not find a property for enumeration. An application can remove only those properties which it has added. It should not remove properties added by other applications or by Windows itself. The following restrictions apply to the callback function: 1 The callback function must not yield control or do anything that might yield control to other tasks. 2 The callback function can call the %RemoveProp% function. However, the %RemoveProp% function can remove only the property passed to the callback function through the callback function's parameters. 3 A callback function should not attempt to add properties. The address passed in the parameter must be created by using the %MakeProcInstance% function. Fixed Data Segments: The callback function must use the Pascal calling convention and must be declared %FAR%. In applications and dynamic libraries with fixed data segments and in dynamic libraries with moveable data segments that do not contain a stack, the callback function must have the form shown below. Callback Function: int FAR PASCAL (, , ) HWND ; LPSTR ; HANDLE ; 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. Identifies a handle to the window that contains the property list. Points to the null-terminated string associated with the data handle when the application called the%SetProp% function to set the property. If the application passed an atom instead of a string to the %SetProp% function, the parameter contains the atom in its low-order word, and the high-order word is zero. Identifies the data handle. The callback function can carry out any desired task. It must return a nonzero value to continue enumeration, or a zero value to stop it. Moveable Data Segments: The callback function must use the Pascal calling convention and must be declared %FAR%. In applications with moveable data segments and in dynamic libraries whose moveable data segments also contain a stack, the callback function must have the form shown below. Callback Function: int FAR PASCAL (, , , ) HWND ; WORD ; PSTR ; HANDLE ; 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. Identifies a handle to the window that contains the property list. Specifies a dummy parameter. Points to the null-terminated string associated with the data handle when the application called the %SetProp% function to set the property. If the application passed an atom instead of a string to the %SetProp% function, the parameter contains the atom. Identifies the data handle. The callback function can carry out any desired task. It should return a nonzero value to continue enumeration, or a zero value to stop it. The alternate form above is required since movement of the data will invalidate any long pointer to a variable on the stack, such as the parameter. The data segment typically moves if the callback function allocates more space in the local heap than is currently available. --*/ ULONG FASTCALL WU32EnumProps(PVDMFRAME pFrame) { ULONG ul; HWND hwnd; register PENUMPROPS16 parg16; GETARGPTR(pFrame, sizeof(ENUMPROPS16), parg16); hwnd = HWND32(parg16->f1); vpEnumPropsProc = parg16->f2; vpString = malloc16(MAX_WIN16_PROP_TEXT); // 16-bit memory may have moved - invalidate flat pointers FREEARGPTR(parg16); FREEVDMPTR(pFrame); if (vpString) { ul = GETINT16(EnumProps(hwnd,(PROPENUMPROC)W32EnumPropsFunc)); free16(vpString); } else { ul = (ULONG)-1; } RETURN(ul); } /*++ int FillWindow(, , , ) HWND ; HWND ; HDC ; HBRUSH ; The %FillWindow% function paints a given window by using the specified brush. Identifies the parent of the window to be painted. Identifies the window to be painted. Identifies the device context. Identifies the brush used to fill the rectangle. --*/ ULONG FASTCALL WU32FillWindow(PVDMFRAME pFrame) { register PFILLWINDOW16 parg16; GETARGPTR(pFrame, sizeof(FILLWINDOW16), parg16); (pfnOut.pfnFillWindow)( HWND32(parg16->f1), HWND32(parg16->f2), HDC32(parg16->f3), HBRUSH32(parg16->f4) ); FREEARGPTR(parg16); RETURN(0); } /*++ int FillRect(, , ) HDC ; LPRECT ; HBRUSH ; The %FillRect% function fills a given rectangle by using the specified brush. The %FillRect% function fills the complete rectangle, including the left and top borders, but does not fill the right and bottom borders. Identifies the device context. Points to a %RECT% structure that contains the logical coordinates of the rectangle to be filled. Identifies the brush used to fill the rectangle. Although the %FillRect% function return type is an integer, the return value is not used and has no meaning. The brush must have been created previously by using either the %CreateHatchBrush%, %CreatePatternBrush%, or %CreateSolidBrush% function, or retrieved using the %GetStockObject% function. When filling the specified rectangle, the %FillRect% function does not include the rectangle's right and bottom sides. GDI fills a rectangle up to, but does not include, the right column and bottom row, regardless of the current mapping mode. %FillRect% compares the values of the %top%, %bottom%, %left%, and %right% members of the specified rectangle. If %bottom% is less than or equal to %top%, or if %right% is less than or equal to %left%, the rectangle is not drawn. --*/ ULONG FASTCALL WU32FillRect(PVDMFRAME pFrame) { ULONG ul; RECT t2; register PFILLRECT16 parg16; GETARGPTR(pFrame, sizeof(FILLRECT16), parg16); WOW32VERIFY(GETRECT16(parg16->f2, &t2)); ul = GETINT16(FillRect( HDC32(parg16->f1), &t2, HBRUSH32(parg16->f3) )); FREEARGPTR(parg16); RETURN(ul); } /*++ int FrameRect(, , ) HDC ; LPRECT ; HBRUSH ; The %FrameRect% function draws a border around the rectangle specified by the parameter. The %FrameRect% function uses the given brush to draw the border. The width and height of the border is always one logical unit. Identifies the device context of the window. Points to a %RECT% structure that contains the logical coordinates of the upper-left and lower-right corners of the rectangle. Identifies the brush to be used for framing the rectangle. Although the return value type is integer, its contents should be ignored. The brush identified by the parameter must have been created previously by using the %CreateHatchBrush%, %CreatePatternBrush%, or %CreateSolidBrush% function. If the %bottom% member is less than or equal to the %top% member, or if the %right% member is less than or equal to the %left% member, the rectangle is not drawn. --*/ ULONG FASTCALL WU32FrameRect(PVDMFRAME pFrame) { ULONG ul; RECT t2; register PFRAMERECT16 parg16; GETARGPTR(pFrame, sizeof(FRAMERECT16), parg16); WOW32VERIFY(GETRECT16(parg16->f2, &t2)); ul = GETINT16(FrameRect( HDC32(parg16->f1), &t2, HBRUSH32(parg16->f3) )); FREEARGPTR(parg16); RETURN(ul); } /*++ HDC GetDC() HWND ; The %GetDC% function retrieves a handle to a display context for the client area of the given window. The display context can be used in subsequent GDI functions to draw in the client area. The %GetDC% function retrieves a common, class, or private display context depending on the class style specified for the given window. For common display contexts, %GetDC% assigns default attributes to the context each time it is retrieved. For class and private contexts, %GetDC% leaves the previously assigned attributes unchanged. Identifies the window whose display context is to be retrieved. The return value identifies the display context for the given window's client area if the function is successful. Otherwise, it is NULL. After painting with a common display context, the %ReleaseDC% function must be called to release the context. Class and private display contexts do not have to be released. Since only five common display contexts are available at any given time, failure to release a display context can prevent other applications from accessing a display context. --*/ ULONG FASTCALL WU32GetDC(PVDMFRAME pFrame) { ULONG ul; register PGETDC16 parg16; HAND16 htask16 = pFrame->wTDB; GETARGPTR(pFrame, sizeof(GETDC16), parg16); if (CACHENOTEMPTY()) { ReleaseCachedDCs(htask16, parg16->f1, 0, 0, SRCHDC_TASK16_HWND16); } CURRENTPTD()->ulLastDesktophDC = 0; ul = GETHDC16(GetDC( HWND32(parg16->f1) )); if (ul) { // Some apps such as MSWORKS and MS PUBLISHER use some wizard code that accepts // a hDC or a hWnd as a parameter and attempt to figure out what type of handle // it is by using the IsWindow() call. Since both handles come from different // handle spaces they may end up the same value and this wizard code will end // up writing to the DC for a random window. By ORing in a 1 we ensure that the // handle types will never share the same value since all hWnds are even. Note // that this hack is also made in WG32CreateCompatibleDC() // // Note that there are some apps that use the lower 2 bits of the hDC for their // own purposes. if (CURRENTPTD()->dwWOWCompatFlags & WOWCF_UNIQUEHDCHWND) { ul = ul | 1; } else if ((CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_FIXDCFONT4MENUSIZE) && (parg16->f1 == 0)) { // WP tutorial assumes that the font selected in the hDC for desktop window // (ie, result of GetDC(NULL)) is the same font as the font selected for // drawing the menu. Unfortunetly in SUR this is not true as the user can // select any font for the menu. So we remember the hDC returned for GetDC(0) // and check for it in GetTextExtentPoint. If the app does try to use it we // find the hDC for the current menu window and substitute that. When the app // does another GetDC or ReleaseDC we forget the hDC returned for the original // GetDC(0). CURRENTPTD()->ulLastDesktophDC = ul; } StoreDC(htask16, parg16->f1, (HAND16)ul); } FREEARGPTR(parg16); RETURN(ul); } /*++ void GetScrollRange(, , , ) HWND ; int ; LPINT ; LPINT ; The %GetScrollRange% function copies the current minimum and maximum scroll-bar positions for the given scroll bar to the locations specified by the and parameters. If the given window does not have standard scroll bars or is not a scroll-bar control, then the %GetScrollRange% function copies zero to and . Identifies a window that has standard scroll bars or a scroll-bar control, depending on the value of the nBar parameter. Specifies an integer value that identifies which scroll bar to retrieve. It can be one of the following values: SB_CTL Retrieves the position of a scroll-bar control; in this case, the hwnd parameter must be the handle of a scroll-bar control. SB_HORZ Retrieves the position of a window's horizontal scroll bar. SB_VERT Retrieves the position of a window's vertical scroll bar. Points to the integer variable that is to receive the minimum position. Points to the integer variable that is to receive the maximum position. This function does not return a value. The default range for a standard scroll bar is 0 to 100. The default range for a scroll-bar control is empty (both values are zero). --*/ ULONG FASTCALL WU32GetScrollRange(PVDMFRAME pFrame) { INT t3; INT t4; register PGETSCROLLRANGE16 parg16; GETARGPTR(pFrame, sizeof(GETSCROLLRANGE16), parg16); GetScrollRange( HWND32(parg16->f1), INT32(parg16->f2), &t3, &t4 ); PUTINT16(parg16->f3, t3); PUTINT16(parg16->f4, t4); FREEARGPTR(parg16); RETURN(0); } /*++ ULONG GetTimerResolution(VOID) This function has no parameters. The Win 3.0 & 3.1 code just return 1000. Contacts on this: NeilK DarrinM The return value is always 1000. --*/ ULONG FASTCALL WU32GetTimerResolution(PVDMFRAME pFrame) { UNREFERENCED_PARAMETER(pFrame); RETURN(1000L); } /*++ BOOL GetUpdateRect(, , ) HWND ; LPRECT ; BOOL ; The %GetUpdateRect% function retrieves the coordinates of the smallest rectangle that completely encloses the update region of the given window. If the window was created with the CS_OWNDC style and the mapping mode is not MM_TEXT, the %GetUpdateRect% function gives the rectangle in logical coordinates. Otherwise, %GetUpdateRect% gives the rectangle in client coordinates. If there is no update region, %GetUpdateRect% makes the rectangle empty (sets all coordinates to zero). The parameter specifies whether %GetUpdateRect% should erase the background of the update region. If is TRUE and the update region is not empty, the background is erased. To erase the background, %GetUpdateRect% sends a WM_ERASEBKGND message to the given window. Identifies the window whose update region is to be retrieved. Points to the %RECT% structure that is to receive the client coordinates of the enclosing rectangle. Specifies whether the background in the update region is to be erased. The return value specifies the status of the update region of the given window. It is TRUE if the update region is not empty. Otherwise, it is FALSE. The update rectangle retrieved by the %BeginPaint% function is identical to that retrieved by the %GetUpdateRect% function. %BeginPaint% automatically validates the update region, so any call to %GetUpdateRect% made immediately after the %BeginPaint% call retrieves an empty update region. --*/ ULONG FASTCALL WU32GetUpdateRect(PVDMFRAME pFrame) { ULONG ul; RECT t2; register PGETUPDATERECT16 parg16; GETARGPTR(pFrame, sizeof(GETUPDATERECT16), parg16); ul = GETBOOL16(GetUpdateRect( HWND32(parg16->f1), &t2, BOOL32(parg16->f3) )); PUTRECT16(parg16->f2, &t2); FREEARGPTR(parg16); RETURN(ul); } ULONG FASTCALL WU32GlobalAddAtom(PVDMFRAME pFrame) { ULONG ul; PSZ psz1; UINT dw1; register PGLOBALADDATOM16 parg16; GETARGPTR(pFrame, sizeof(GLOBALADDATOM16), parg16); dw1 = UINT32(parg16->f1); if (!HIWORD(dw1)) { // // If the hiword is zero, it's not a pointer. // Instead, it's an integer and we either return // the integer passed (if it's not a valid atom // value), or zero (if it is a valid atom value). // if (!dw1 || dw1 >= 0xc000) { ul = 0; } else { ul = dw1; } } else { GETPSZPTR(parg16->f1, psz1); ul = GETATOM16(GlobalAddAtom( psz1 )); FREEPSZPTR(psz1); } FREEARGPTR(parg16); RETURN(ul); } ULONG FASTCALL WU32GlobalDeleteAtom(PVDMFRAME pFrame) { // Envoy viewer (part of PerfectOffice) has a bug in GlobalDeleteAtom // where it expects the wrong return value (the app thought 0 was // failure while its for success). This causes the app to go in an // infinite loop trying to delete a global object. This app works on // Win3.1 because Win3.1 returns some garbage in AX if the atom is // already deleted which takes this app out of the loop. On Win95 and // NT3.51 that is not the case and 0 is always returned. The following // comaptibility fix mimics the win3.1 behavior for this app. ULONG ul; static USHORT envoyHandle16=0; static BOOL fFoundEnvoyAtom = FALSE; BOOL IsEnvoy; CHAR envoyString [32]; register PGLOBALDELETEATOM16 parg16; GETARGPTR(pFrame, sizeof(GLOBALDELETEATOM16), parg16); IsEnvoy = (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_GLOBALDELETEATOM); if (IsEnvoy){ if (!fFoundEnvoyAtom && GlobalGetAtomName (ATOM32(parg16->f1), envoyString, 32) && !WOW32_stricmp (envoyString, "SomeEnvoyViewerIsRunning")) { envoyHandle16 = parg16->f1; } } ul = GETATOM16(GlobalDeleteAtom( ATOM32(parg16->f1) )); if (IsEnvoy){ if (envoyHandle16 && !fFoundEnvoyAtom) { fFoundEnvoyAtom = TRUE; } else if (fFoundEnvoyAtom) { if (envoyHandle16 == parg16->f1) { envoyHandle16 = 0; fFoundEnvoyAtom = FALSE; ul = parg16->f1; } } } FREEARGPTR(parg16); RETURN(ul); } ULONG FASTCALL WU32GlobalGetAtomName(PVDMFRAME pFrame) { ULONG ul = 0; PSZ psz2; register PGLOBALGETATOMNAME16 parg16; GETARGPTR(pFrame, sizeof(GLOBALGETATOMNAME16), parg16); ALLOCVDMPTR(parg16->f2, parg16->f3, psz2); if (parg16->f1) { ul = GETWORD16(GlobalGetAtomName(ATOM32(parg16->f1), psz2, INT32(parg16->f3))); FLUSHVDMPTR(parg16->f2, strlen(psz2)+1, psz2); } else { *psz2 = '\0'; } FREEVDMPTR(psz2); FREEARGPTR(parg16); RETURN(ul); } /*++ BOOL GrayString(, , , , , , , , ) HDC ; HBRUSH ; FARPROC ; DWORD ; int ; int ; int ; int ; int ; The %GrayString% function draws gray text at the given location. The %GrayString% function draws gray text by writing the text in a memory bitmap, graying the bitmap, and then copying the bitmap to the display. The function grays the text regardless of the selected brush and background. %GrayString% uses the font currently selected for the device context specified by the parameter. If the parameter is NULL, GDI uses the %TextOut% function, and the parameter is assumed to be a long pointer to the character string to be output. If the characters to be output cannot be handled by %TextOut% (for example, the string is stored as a bitmap), the application must supply its own output function. Identifies the device context. Identifies the brush to be used for graying. Is the procedure-instance address of the application-supplied function that will draw the string, or, if the %TextOut% function is to be used to draw the string, it is a NULL pointer. See the following Comments section for details. Specifies a long pointer to data to be passed to the output function. If the parameter is NULL, must be a long pointer to the string to be output. Specifies the number of characters to be output. If the parameter is zero, %GrayString% calculates the length of the string (assuming that is a pointer to the string). If is -1 and the function pointed to by returns zero, the image is shown but not grayed. Specifies the logical -coordinate of the starting position of the rectangle that encloses the string. Specifies the logical -coordinate of the starting position of the rectangle that encloses the string. Specifies the width (in logical units) of the rectangle that encloses the string. If the parameter is zero, %GrayString% calculates the width of the area, assuming is a pointer to the string. Specifies the height (in logical units) of the rectangle that encloses the string. If the parameter is zero, %GrayString% calculates the height of the area, assuming is a pointer to the string. The return value specifies the outcome of the function. It is TRUE if the string is drawn. A return value of FALSE means that either the %TextOut% function or the application-supplied output function returned FALSE, or there was insufficient memory to create a memory bitmap for graying. An application can draw grayed strings on devices that support a solid gray color, without calling the %GrayString% function. The system color COLOR_GRAYTEXT is the solid-gray system color used to draw disabled text. The application can call the %GetSysColor% function to retrieve the color value of COLOR_GRAYTEXT. If the color is other than zero (black), the application can call the %SetTextColor% to set the text color to the color value and then draw the string directly. If the retrieved color is black, the application must call %GrayString% to gray the text. The callback function must use the Pascal calling convention and must be declared %FAR%. Callback Function: BOOL FAR PASCAL (, , ) HDC ; DWORD ; int ; is a placeholder for the application-supplied callback function name. The actual name must be exported by including it in an %EXPORTS% statement in the application's module-definition file. Identifies a memory device context with a bitmap of at least the width and height specified by the nWidth and nHeight parameters, respectively. Points to the character string to be drawn. Specifies the number of characters to be output. The return value must be TRUE to indicate success. Otherwise, it is FALSE. This output function () must draw an image relative to the coordinates (0,0) rather than (). The address passed as the parameter must be created by using the %MakeProcInstance% function, and the output function name must be exported; it must be explicitly defined in an %EXPORTS% statement of the application's module-definition file. The MM_TEXT mapping mode must be selected before using this function. --*/ BOOL W32GrayStringProc(HDC hDC,PGRAYSTRINGDATA pGray, int n) { INT iReturn; PARM16 Parm16; WOW32ASSERT(pGray); if (pGray->fResetLengthToZero) n = 0; LOGDEBUG(12,(" Graystring callback function, n = %d, hdc = %lx, %lx\n",n,hDC,pGray->dwUserParam)); Parm16.GrayStringProc.n = (SHORT)n; Parm16.GrayStringProc.data = pGray->dwUserParam; pGray->hdc=Parm16.GrayStringProc.hdc = GETHDC16(hDC); CallBack16(RET_GRAYSTRINGPROC, &Parm16, pGray->vpfnGrayStringProc, (PVPVOID)&iReturn); LOGDEBUG(12,(" Graystring callback function returns %x\n",iReturn)); return (BOOL)((SHORT)iReturn); } ULONG FASTCALL WU32GrayString(PVDMFRAME pFrame) { ULONG ul=0; PSZ psz2; HDC hdc; INT n,wid,hgt; VPVOID vpfn; VPVOID vpstr; GRAYSTRINGDATA Gray; register PGRAYSTRING16 parg16; GETARGPTR(pFrame, sizeof(GRAYSTRING16), parg16); hdc=HDC32(parg16->f1); vpfn = DWORD32(parg16->f3); vpstr = DWORD32(parg16->f4); n=INT32(parg16->f5); wid=INT32(parg16->f8); hgt=INT32(parg16->f9); if ( HIWORD(vpfn) ) { // SQLWin/repowin passes junk in low word Gray.fResetLengthToZero = FALSE; if( n==0 ) { n = 1; // Prevent USER from doing strlen on &Gray below if ( HIWORD(vpstr) != 0 ) { // Blow off small integers right away GETVDMPTR(vpstr, 0, psz2); // This might assert on mips, ignore it! if ( psz2 ) { try { n = strlen(psz2); if (!n) { n = 1; Gray.fResetLengthToZero = TRUE; } } except( EXCEPTION_EXECUTE_HANDLER ) { } } FREEVDMPTR( psz2 ); } } if ( wid == 0 || hgt == 0) { if ( HIWORD(vpstr) != 0 ) { GETVDMPTR(vpstr, 0, psz2); // This might assert on mips, ignore it! if (psz2) { SIZE size; try { GetTextExtentPointA(hdc, (LPCSTR)psz2, n, &size); wid = size.cx; hgt = size.cy; } except (EXCEPTION_EXECUTE_HANDLER) { } } FREEVDMPTR( psz2 ); } } Gray.vpfnGrayStringProc = DWORD32(parg16->f3); Gray.dwUserParam = vpstr; Gray.hdc = 0; LOGDEBUG(12,(" Graystring with callback %lx n,w,h = %d,%d,%d\n", vpstr,n,wid,hgt)); ul = GETBOOL16(GrayString(hdc, HBRUSH32(parg16->f2), (GRAYSTRINGPROC)W32GrayStringProc, (DWORD)&Gray, n, INT32(parg16->f6), INT32(parg16->f7), wid, hgt)); } else { GETPSZPTR(vpstr, psz2); #ifdef DOESNT_USER_DO_THIS if( n==0 ) { n=strlen(psz2); } if( ((wid == 0) || (hgt == 0)) ) { GetTextExtentPoint(hdc,psz2,n,&sz); wid=sz.cx; hgt=sz.cy; } #endif ul = GETBOOL16(GrayString(hdc, HBRUSH32(parg16->f2), NULL, (DWORD)psz2, n, INT32(parg16->f6), INT32(parg16->f7), wid, hgt)); FREEPSZPTR(psz2); } FREEARGPTR(parg16); RETURN(ul); } /*++ void InvalidateRect(, , ) HWND ; LPRECT ; BOOL ; The %InvalidateRect% function invalidates the client area within the given rectangle by adding that rectangle to the window's update region. The invalidated rectangle, along with all other areas in the update region, is marked for painting when the next WM_PAINT message occurs. The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs, or the region is validated by using the %ValidateRect% or %ValidateRgn% function. The parameter specifies whether the background within the update area is to be erased when the update region is processed. If is TRUE, the background is erased when the %BeginPaint% function is called; if is FALSE, the background remains unchanged. If is TRUE for any part of the update region, the background in the entire region is erased, not just in the given part. Identifies the window whose update region is to be modified. Points to a %RECT% structure that contains the rectangle (in client coordinates) to be added to the update region. If the parameter is NULL, the entire client area is added to the region. Specifies whether the background within the update region is to be erased. This function does not return a value. Windows sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window. --*/ ULONG FASTCALL WU32InvalidateRect(PVDMFRAME pFrame) { RECT t2, *p2; register PINVALIDATERECT16 parg16; GETARGPTR(pFrame, sizeof(INVALIDATERECT16), parg16); p2 = GETRECT16(parg16->f2, &t2); InvalidateRect( HWND32(parg16->f1), p2, BOOL32(parg16->f3) ); FREEARGPTR(parg16); RETURN(1); // Win 3.x always returned 1 as a side-effect of jmping to // IRedrawWindow [core\user\wmupdate.c] - MarkRi 5/93 } /*++ void InvalidateRgn(, , ) HWND ; HRGN ; BOOL ; The %InvalidateRgn% function invalidates the client area within the given region by adding it to the current update region of the given window. The invalidated region, along with all other areas in the update region, is marked for painting when the next WM_PAINT message occurs. The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs, or the region is validated by using the %ValidateRect% or %ValidateRgn% function. The parameter specifies whether the background within the update area is to be erased when the update region is processed. If is TRUE, the background is erased when the %BeginPaint% function is called; if is FALSE, the background remains unchanged. If is TRUE for any part of the update region, the background in the entire region is erased, not just in the given part. Identifies the window whose update region is to be modified. Identifies the region to be added to the update region. The region is assumed to have client coordinates. Specifies whether the background within the update region is to be erased. This function does not return a value. Windows sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window. The given region must have been previously created by using one of the region functions (for more information, see Chapter 1, Window Manager Interface Functions). --*/ ULONG FASTCALL WU32InvalidateRgn(PVDMFRAME pFrame) { register PINVALIDATERGN16 parg16; GETARGPTR(pFrame, sizeof(INVALIDATERGN16), parg16); InvalidateRgn( HWND32(parg16->f1), HRGN32(parg16->f2), BOOL32(parg16->f3) ); FREEARGPTR(parg16); RETURN(1); // Win 3.x always returned 1 as a side-effect of jmping to // IRedrawWindow [core\user\wmupdate.c] - MarkRi 5/93 } /*++ void InvertRect(, ) HDC ; LPRECT ; The %InvertRect% function inverts the contents of the given rectangle. On monochrome displays, the %InvertRect% function makes white pixels black, and black pixels white. On color displays, the inversion depends on how colors are generated for the display. Calling %InvertRect% twice with the same rectangle restores the display to its previous colors. Identifies the device context. Points to a %RECT% structure that contains the logical coordinates of the rectangle to be inverted. This function does not return a value. The %InvertRect% function compares the values of the %top%, %bottom%, %left%, and %right% members of the specified rectangle. If %bottom% is less than or equal to %top%, or if %right% is less than or equal to %left%, the rectangle is not drawn. --*/ ULONG FASTCALL WU32InvertRect(PVDMFRAME pFrame) { RECT t2; register PINVERTRECT16 parg16; GETARGPTR(pFrame, sizeof(INVERTRECT16), parg16); WOW32VERIFY(GETRECT16(parg16->f2, &t2)); InvertRect( HDC32(parg16->f1), &t2 ); FREEARGPTR(parg16); RETURN(0); } ULONG FASTCALL WU32LoadBitmap(PVDMFRAME pFrame) { ULONG ul = 0; PSZ psz2; register PLOADBITMAP16 parg16; LPBYTE pResData = NULL; GETARGPTR(pFrame, sizeof(LOADBITMAP16), parg16); GETPSZIDPTR(parg16->f2, psz2); GETMISCPTR(parg16->f3, pResData); ul = GETHBITMAP16((pfnOut.pfnWOWLoadBitmapA)(HINSTRES32(parg16->f1), psz2, pResData, parg16->f4)); FREEMISCPTR(pResData); FREEPSZIDPTR(psz2); FREEARGPTR(parg16); RETURN(ul); } /*++ int ReleaseDC(, ) HWND ; HDC ; The %ReleaseDC% function releases a device context, freeing it for use by other applications. The effect of the %ReleaseDC% function depends on the device-context type. It only frees common and window device contexts. It has no effect on class or private device contexts. Identifies the window whose device context is to be released. Identifies the device context to be released. The return value specifies whether the device context is released. It is 1 if the device context is released. Otherwise, it is zero. The application must call the %ReleaseDC% function for each call to the %GetWindowDC% function and for each call to the %GetDC% function that retrieves a common device context. --*/ ULONG FASTCALL WU32ReleaseDC(PVDMFRAME pFrame) { ULONG ul; register PRELEASEDC16 parg16; HAND16 htask16 = CURRENTPTD()->htask16; GETARGPTR(pFrame, sizeof(RELEASEDC16), parg16); CURRENTPTD()->ulLastDesktophDC = 0; CacheReleasedDC(htask16, parg16->f1, parg16->f2); ul = TRUE; FREEARGPTR(parg16); RETURN(ul); } /*++ BOOL ScrollDC(, , , , , , ) HDC ; int ; int ; LPRECT ; LPRECT ; HRGN ; LPRECT ; The %ScrollDC% function scrolls a rectangle of bits horizontally and vertically. The parameter points to the rectangle to be scrolled, the parameter specifies the number of units to be scrolled horizontally, and the parameter specifies the number of units to be scrolled vertically. Identifies the device context that contains the bits to be scrolled. Specifies the number of horizontal scroll units. Specifies the number of vertical scroll units. Points to the %RECT% structure that contains the coordinates of the scrolling rectangle. Points to the %RECT% structure that contains the coordinates of the clipping rectangle. When this rectangle is smaller than the original pointed to by , scrolling occurs only in the smaller rectangle. Identifies the region uncovered by the scrolling process. The %ScrollDC% function defines this region; it is not necessarily a rectangle. Points to the %RECT% structure that, upon return, contains the coordinates of the rectangle that bounds the scrolling update region. This is the largest rectangular area that requires repainting. This value specifies the outcome of the function. It is TRUE if scrolling is executed. Otherwise, it is FALSE. If the parameter is NULL, Windows does not compute the update rectangle. If both the and parameters are NULL, Windows does not compute the update region. If is not NULL, Windows assumes that it contains a valid region handle to the region uncovered by the scrolling process (defined by the %ScrollDC% function). An application should use the %ScrollWindow% function when it is necessary to scroll the entire client area of a window. Otherwise, it should use %ScrollDC%. --*/ ULONG FASTCALL WU32ScrollDC(PVDMFRAME pFrame) { ULONG ul; RECT t4; RECT t5; RECT t7; register PSCROLLDC16 parg16; GETARGPTR(pFrame, sizeof(SCROLLDC16), parg16); ul = GETBOOL16(ScrollDC( HDC32(parg16->f1), INT32(parg16->f2), INT32(parg16->f3), GETRECT16(parg16->f4, &t4), GETRECT16(parg16->f5, &t5), HRGN32(parg16->f6), &t7 )); PUTRECT16(parg16->f7, &t7); FREEARGPTR(parg16); RETURN(ul); } /*++ HWND SetCapture() HWND ; The %SetCapture% function causes all subsequent mouse input to be sent to the window specified by the parameter, regardless of the position of the cursor. Identifies the window that is to receive the mouse input. The return value identifies the window that previously received all mouse input. It is NULL if there is no such window. When the window no longer requires all mouse input, the application should call the %ReleaseCapture% function so that other windows can receive mouse input. --*/ ULONG FASTCALL WU32SetCapture(PVDMFRAME pFrame) { ULONG ul; register PSETCAPTURE16 parg16; GETARGPTR(pFrame, sizeof(SETCAPTURE16), parg16); // MS Works Ver 3.0B has an unintialized local variable. We need to make // sure it see's a positive int value in the location on the stack where we // write the 32-bit thunk address for fast dispatching to this thunk. if (CURRENTPTD()->dwWOWCompatFlagsEx & WOWCFEX_SETCAPSTACK) { // wCallID has already been used for dispatch so we can overwrite it. // Note: This will cause the logging on checked builds show ISCHILD() // as the return API instead of SetCapture(). // For folks grepping for this: SetCapture() : IsChild() pFrame->wCallID = 0x100; } ul = GETHWND16(SetCapture(HWND32(parg16->f1))); FREEARGPTR(parg16); RETURN(ul); } ULONG FASTCALL WU32SetEventHook(PVDMFRAME pFrame) { PTD ptd; PTDB pTDB; DWORD dwButtonPushed; #ifdef FE_SB CHAR szErrorMessage[256]; #else // !FE_SB CHAR szErrorMessage[200]; #endif // !FE_SB char szModName[9]; char szTitle[100]; register PSETEVENTHOOK16 parg16; GETARGPTR(pFrame, sizeof(SETEVENTHOOK16), parg16); // Retail Build ptd = CURRENTPTD(); if (ptd->dwFlags & TDF_FORCETASKEXIT) { goto SetEventHookExit; } pTDB = (PVOID)SEGPTR(ptd->htask16,0); RtlCopyMemory(szModName, pTDB->TDB_ModName, sizeof(szModName)-1); szModName[sizeof(szModName)-1] = 0; if (!LoadString(hmodWOW32, iszEventHook, szErrorMessage, sizeof(szErrorMessage)/sizeof(CHAR))) { szErrorMessage[0] = 0; } if (!LoadString(hmodWOW32, iszApplication, szTitle, sizeof(szTitle)/sizeof(CHAR))) { szTitle[0] = 0; } strcat(szTitle, szModName); dwButtonPushed = WOWSysErrorBox( szTitle, szErrorMessage, SEB_CLOSE | SEB_DEFBUTTON, 0, SEB_IGNORE ); if (dwButtonPushed != 3) { // // If user typed Cancel or Any of the above fail, // force the task to die. // GETFRAMEPTR(ptd->vpStack, pFrame); pFrame->wRetID = RET_FORCETASKEXIT; ptd->dwFlags |= TDF_FORCETASKEXIT; } SetEventHookExit: FREEARGPTR(parg16); RETURN(0); } /*++ void SetKeyboardState() LPBYTE ; The %SetKeyboardState% function copies the 256 bytes pointed to by the parameter into the Windows keyboard-state table. Points to an array of 256 bytes that contains keyboard key states. This function does not return a value. In many cases, an application should call the %GetKeyboardState% function first to initialize the 256-byte array. The application should then change the desired bytes. %SetKeyboardState% sets the LEDs and BIOS flags for the ^NUMLOCK^, ^CAPSLOCK^, and ^SCROLL LOCK^ keys according to the toggle state of the VK_NUMLOCK, VK_CAPITAL, and VK_OEM_SCROLL entries of the array. For more information, see the description of %GetKeyboardState%, earlier in this chapter. --*/ ULONG FASTCALL WU32SetKeyboardState(PVDMFRAME pFrame) { PBYTE p1; register PSETKEYBOARDSTATE16 parg16; GETARGPTR(pFrame, sizeof(SETKEYBOARDSTATE16), parg16); GETVDMPTR(parg16->f1, 256, p1); SetKeyboardState( p1 ); FREEVDMPTR(p1); FREEARGPTR(parg16); RETURN(0); } /*++ void SetSysColors(, , ) int ; LPINT ; LPDWORD ; The %SetSysColors% function sets the system colors for one or more display elements. Display elements are the various parts of a window and the Windows display that appear on the system display screen. The %SetSysColors% function sends a WM_SYSCOLORCHANGE message to all windows to inform them of the change in color. It also directs Windows to repaint the affected portions of all currently visible windows. Specifies the number of display elements in the array. Points to an array of integers that specify the display elements to be changed. For a list of possible display elements, see the following "Comments" section. Points to an array of unsigned long integers that contains the new RGB color value for each display element in the array. This function does not return a value. The %SetSysColors% function changes the current Windows session only. The new colors are not saved when Windows terminates. The following is the list of display elements that may be used in the array of display elements pointed to by the parameter: COLOR_ACTIVEBORDER Active window border. COLOR_ACTIVECAPTION Active window caption. COLOR_APPWORKSPACE Background color of multiple document interface (MDI) applications. COLOR_BACKGROUND Desktop. COLOR_BTNFACE Face shading on push buttons. COLOR_BTNSHADOW Edge shading on push buttons. COLOR_BTNTEXT Text on push buttons. COLOR_CAPTIONTEXT Text in caption, size box, scroll-bar arrow box. COLOR_GRAYTEXT Grayed (disabled) text. This color is set to 0 if the current display driver does not support a solid gray color. COLOR_HIGHLIGHT Items selected item in a control. COLOR_HIGHLIGHTTEXT Text of item selected in a control. COLOR_INACTIVEBORDER Inactive window border. COLOR_INACTIVECAPTION Inactive window caption. COLOR_INACTIVECAPTIONTEXT Color of text in an inactive caption. COLOR_MENU Menu background. COLOR_MENUTEXT Text in menus. COLOR_SCROLLBAR Scroll-bar gray area. COLOR_WINDOW Window background. COLOR_WINDOWFRAME Window frame. COLOR_WINDOWTEXT Text in windows. --*/ #define SSC_BUF_SIZE 256 ULONG FASTCALL WU32SetSysColors(PVDMFRAME pFrame) { PINT p2; PDWORD p3; register PSETSYSCOLORS16 parg16; INT BufElements[SSC_BUF_SIZE]; GETARGPTR(pFrame, sizeof(SETSYSCOLORS16), parg16); p2 = STACKORHEAPALLOC(INT32(parg16->f1) * sizeof(INT), sizeof(BufElements), BufElements); getintarray16(parg16->f2, INT32(parg16->f1), p2); GETDWORDARRAY16(parg16->f3, INT32(parg16->f1), p3); if (SetSysColors( INT32(parg16->f1), p2, p3 ) == FALSE) { #ifndef i386 PDWORD p4; ULONG BufRGB [SSC_BUF_SIZE]; // On RISC platforms, SetSysColors could fail if the third parameter // is unaligned. We need to check that and copy it to an aligned // buffer before making this call. Win16 SetSysColor never fails // so on x86 if this ever fails under NT, it will just pass through. if ((ULONG)p3 & 3) { p4 = STACKORHEAPALLOC(INT32(parg16->f1) * sizeof(INT), sizeof(BufRGB), BufRGB); RtlMoveMemory ((PVOID)p4, (CONST VOID *)p3, INT32(parg16->f1) * sizeof(ULONG)); SetSysColors( INT32(parg16->f1), p2, p4 ); STACKORHEAPFREE(p4, BufRGB); } #endif } FREEDWORDARRAY16(p3); STACKORHEAPFREE(p2, BufElements); FREEARGPTR(parg16); RETURN(0); } /*++ void InvalidateRect(, , ) HWND ; LPRECT ; BOOL ; The %InvalidateRect% function invalidates the client area within the given rectangle by adding that rectangle to the window's update region. The invalidated rectangle, along with all other areas in the update region, is marked for painting when the next WM_PAINT message occurs. The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs, or the region is validated by using the %ValidateRect% or %ValidateRgn% function. The parameter specifies whether the background within the update area is to be erased when the update region is processed. If is TRUE, the background is erased when the %BeginPaint% function is called; if is FALSE, the background remains unchanged. If is TRUE for any part of the update region, the background in the entire region is erased, not just in the given part. Identifies the window whose update region is to be modified. Points to a %RECT% structure that contains the rectangle (in client coordinates) to be added to the update region. If the parameter is NULL, the entire client area is added to the region. Specifies whether the background within the update region is to be erased. This function does not return a value. Windows sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window. --*/ ULONG FASTCALL WU32ValidateRect(PVDMFRAME pFrame) { RECT t2, *p2; register PVALIDATERECT16 parg16; GETARGPTR(pFrame, sizeof(VALIDATERECT16), parg16); p2 = GETRECT16(parg16->f2, &t2); ValidateRect( HWND32(parg16->f1), p2 ); FREEARGPTR(parg16); RETURN(1); // Win 3.x always returned 1 as a side-effect of jmping to // IRedrawWindow [core\user\wmupdate.c] - MarkRi 5/93 } /*++ void InvalidateRgn(, , ) HWND ; HRGN ; BOOL ; The %InvalidateRgn% function invalidates the client area within the given region by adding it to the current update region of the given window. The invalidated region, along with all other areas in the update region, is marked for painting when the next WM_PAINT message occurs. The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs, or the region is validated by using the %ValidateRect% or %ValidateRgn% function. The parameter specifies whether the background within the update area is to be erased when the update region is processed. If is TRUE, the background is erased when the %BeginPaint% function is called; if is FALSE, the background remains unchanged. If is TRUE for any part of the update region, the background in the entire region is erased, not just in the given part. Identifies the window whose update region is to be modified. Identifies the region to be added to the update region. The region is assumed to have client coordinates. Specifies whether the background within the update region is to be erased. This function does not return a value. Windows sends a WM_PAINT message to a window whenever its update region is not empty and there are no other messages in the application queue for that window. The given region must have been previously created by using one of the region functions (for more information, see Chapter 1, Window Manager Interface Functions). --*/ ULONG FASTCALL WU32ValidateRgn(PVDMFRAME pFrame) { register PVALIDATERGN16 parg16; GETARGPTR(pFrame, sizeof(VALIDATERGN16), parg16); ValidateRgn( HWND32(parg16->f1), HRGN32(parg16->f2) ); FREEARGPTR(parg16); RETURN(1); // Win 3.x always returned 1 as a side-effect of jmping to // IRedrawWindow [core\user\wmupdate.c] - MarkRi 5/93 } /*++ BOOL WinHelp(, , , ) HWND ; LPSTR ; WORD ; DWORD ; This function invokes the Windows Help application and passes optional data indicating the nature of the help requested by the application. The application specifies the name and, where required, the directory path of the help file which the Help application is to display. Identifies the window requesting help. Points to a null-terminated string containing the directory path, if needed, and the name of the help file which the Help application is to display. Specifies the type of help requested. It may be any one of the following values: HELP_CONTEXT Displays help for a particular context identified by a 32-bit unsigned integer value in dwData. HELP_HELPONHELP Displays help for using the help application itself. If the parameter is set to HELP_HELPONHELP, %WinHelp% ignores the and parameters. HELP_INDEX Displays the index of the specified help file. An application should use this value only for help files with a single index. It should not use this value with HELP_SETINDEX. HELP_MULTIKEY Displays help for a key word in an alternate keyword table. HELP_QUIT Notifies the help application that the specified help file is no longer in use. HELP_SETINDEX Sets the context specified by the parameter as the current index for the help file specified by the parameter. This index remains current until the user accesses a different help file. To help ensure that the correct index remains set, the application should call %WinHelp% with set to HELP_SETINDEX (with specifying the corresponding context identifier) following each call to %WinHelp% with set to HELP_CONTEXT. An application should use this value only for help files with more than one index. It should not use this value with HELP_INDEX. %DWORD% Specifies the context or key word of the help requested. If is HELP_CONTEXT, is a 32-bit unsigned integer containing a context-identifier number. If is HELP_KEY, is a long pointer to a null-terminated string that contains a key word identifying the help topic. If is HELP_MULTIKEY, is a long pointer to a %MULTIKEYHELP% structure. Otherwise, is ignored and should be set to NULL. The return value specifies the outcome of the function. It is TRUE if the function was successful. Otherwise it is FALSE. The application must call %WinHelp% with set to HELP_QUIT before closing the window that requested the help. The Help application will not actually terminate until all applications that have requested help have called %WinHelp% with set to HELP_QUIT. --*/ /*++ RAID bug # 394455 05/19/2001 alexsm Some applications were having problems finding and displaying their helpfiles via the 16 bit winhelp. These issues can be fixed by redirecting the calls to winhlp32. This redirection is activitated by the WOWCFEX_USEWINHELP32 compat flag. The flag is checked in the IWinHelp() function in user.exe. It redirects the call, along with its parameters, to this 32 bit thunk. --*/ ULONG FASTCALL WU32WinHelp(PVDMFRAME pFrame) { ULONG ul; PSZ psz2; register PWIN32WINHELP16 parg16; DWORD dwCommand; DWORD dwData; UINT cb; MULTIKEYHELP *lpmkey; PMULTIKEYHELP16 pmkey16; HELPWININFO hwinfo; PHELPWININFO16 phwinfo16; UpdateDosCurrentDirectory(DIR_DOS_TO_NT); GETARGPTR(pFrame, sizeof(WIN32WINHELP16), parg16); GETPSZPTR(parg16->f2, psz2); dwCommand = WORD32(parg16->f3); switch (dwCommand) { case HELP_KEY: case HELP_COMMAND: case HELP_PARTIALKEY: GETPSZPTR(parg16->f4, (PSZ)dwData); break; case HELP_HELPONHELP: // // some apps (eg multimedia raid#) pass along a help file name which confuses winhlp32.exe // by definition the help gfile name parameter is meaningless. // psz2 = NULL; dwData = 0; break; case HELP_MULTIKEY: GETVDMPTR(parg16->f4, sizeof(MULTIKEYHELP16), pmkey16); cb = FETCHWORD(pmkey16->mkSize); FREEVDMPTR(pmkey16); GETVDMPTR(parg16->f4, cb, pmkey16); // // It is my understanding that 'mkSize' is the total // data length and NOT just sizeof(MULTIKEYHELP) // cb += sizeof(MULTIKEYHELP) - sizeof(MULTIKEYHELP16); lpmkey = (MULTIKEYHELP *)malloc_w(cb); if (lpmkey) { lpmkey->mkSize = cb; lpmkey->mkKeylist = pmkey16->mkKeylist; strcpy(lpmkey->szKeyphrase, pmkey16->szKeyphrase); } FREEVDMPTR(pmkey16); dwData = (DWORD)lpmkey; break; case HELP_SETWINPOS: GETVDMPTR(parg16->f4, sizeof(HELPWININFO16), phwinfo16); hwinfo.wStructSize = (int)(FETCHWORD(phwinfo16->wStructSize) + (sizeof(HELPWININFO) - sizeof(HELPWININFO16))); hwinfo.x = (int)FETCHSHORT(phwinfo16->x); hwinfo.y = (int)FETCHSHORT(phwinfo16->y); hwinfo.dx = (int)FETCHSHORT(phwinfo16->dx); hwinfo.dy = (int)FETCHSHORT(phwinfo16->dy); hwinfo.wMax = (int)FETCHSHORT(phwinfo16->wMax); hwinfo.rgchMember[0] = (CHAR)phwinfo16->rgchMember[0]; hwinfo.rgchMember[1] = (CHAR)phwinfo16->rgchMember[1]; FREEVDMPTR(phwinfo16); dwData = (DWORD)&hwinfo; break; default: dwData = DWORD32(parg16->f4); break; } LOGDEBUG(LOG_WARNING, ("WU32Winhelp: Paramaters passed to WinHelp():/nHwnd=%x psz2=%x dwCommand=%x dwData=%x", parg16->f1, psz2, dwCommand, dwData)); ul = GETBOOL16(WinHelp(HWND32(parg16->f1), psz2, dwCommand, dwData)); switch (dwCommand) { case HELP_KEY: case HELP_COMMAND: case HELP_PARTIALKEY: FREEPSZPTR((PSZ)dwData); break; case HELP_MULTIKEY: if (lpmkey) free_w(lpmkey); break; case HELP_SETWINPOS: break; default: break; } FREEPSZPTR(psz2); FREEARGPTR(parg16); RETURN(ul); } #pragma pack(1) // // win16 Module Table structure (based off of ne header) // see wow16\inc\newexe.inc // typedef struct _NE_MODULE { USHORT ne_magic; // Magic number USHORT ne_usage; // usage count of module USHORT ne_enttab; // Offset of Entry Table USHORT ne_pnextexe; // sel next module table USHORT ne_pautodata; // offset autodata seg table USHORT ne_pfileinfo; // offset load file info USHORT ne_flags; // Flag word USHORT ne_autodata; // Automatic data segment number USHORT ne_heap; // Initial heap allocation USHORT ne_stack; // Initial stack allocation ULONG ne_csip; // Initial CS:IP setting ULONG ne_sssp; // Initial SS:SP setting USHORT ne_cseg; // Count of file segments USHORT ne_cmod; // Entries in Module Reference Table USHORT ne_cbnrestab; // Size of non-resident name table USHORT ne_segtab; // Offset of Segment Table USHORT ne_rsrctab; // Offset of Resource Table USHORT ne_restab; // Offset of resident name table USHORT ne_modtab; // Offset of Module Reference Table USHORT ne_imptab; // Offset of Imported Names Table ULONG ne_nrestab; // Offset of Non-resident Names Table USHORT ne_cmovent; // Count of movable entries USHORT ne_align; // Segment alignment shift count USHORT ne_cres; // Count of resource segments UCHAR ne_exetyp; // Target Operating system UCHAR ne_flagsothers; // Other .EXE flags USHORT ne_pretthunks; // offset to return thunks USHORT ne_psegrefbytes; // offset to segment ref. bytes USHORT ne_swaparea; // Minimum code swap area size USHORT ne_expver; // Expected Windows version number } NEMODULE; typedef NEMODULE UNALIGNED *PNEMODULE; #pragma pack() #ifdef FE_IME VOID WN32WINNLSSImeNotifyTaskExit(); // wnman.c #endif // FE_IME // // Performs Module cleanup (win31:tmdstroy.c\ModuleUnload()) // void ModuleUnload( HAND16 hModule16, BOOL fTaskExit ) { PNEMODULE pNeModule = SEGPTR(hModule16, 0); PTD ptd = CURRENTPTD(); if (pNeModule->ne_usage == 1 || fTaskExit) { W32UnhookHooks(hModule16,FALSE); } if (fTaskExit) { ptd->dwFlags |= TDF_TASKCLEANUPDONE; (pfnOut.pfnWOWCleanup)(HINSTRES32(ptd->hInst16), (DWORD) ptd->htask16); } if (pNeModule->ne_usage > 1) { return; } #ifdef FE_IME /* * We need to notify IMM that this WOW task is quiting before * calling WowCleanup or IME windows can not receive WM_DESTROY * and will fail to clean up their 32bit resource. */ if ( fTaskExit ) { WN32WINNLSSImeNotifyTaskExit(); } #endif // FE_IME /* WowCleanup, UserSrv private api * It cleans up any USER objects created by this hModule, most notably * classes, and subclassed windows. */ (pfnOut.pfnWOWModuleUnload)((HANDLE)hModule16); RemoveHmodFromCache(hModule16); } WORD FASTCALL WOWGetProcModule16( DWORD vpfn ) { WOW32ASSERTMSG(gpfn16GetProcModule, "WOWGetProcModule16 called before gpfn16GetProcModule initialized.\n"); return (WORD) WOWCallback16( gpfn16GetProcModule, vpfn ); } /*++ BOOL SignalProc(, , , ) HWND ; LPSTR ; WORD ; DWORD ; This function provides the communication link between KERNEL and USER. --*/ #define SG_EXIT 0x0020 #define SG_LOAD_DLL 0x0040 #define SG_EXIT_DLL 0x0080 #define SG_GP_FAULT 0x0666 ULONG FASTCALL WU32SignalProc(PVDMFRAME pFrame) { WORD message; LONG lparam; register PSIGNALPROC16 parg16; HAND16 hModule16; PTD ptd; GETARGPTR(pFrame, sizeof(SIGNALPROC16), parg16); message = FETCHWORD(parg16->f2); switch( message ) { case SG_EXIT: case SG_GP_FAULT: lparam = FETCHDWORD(parg16->f4); ptd = CURRENTPTD(); ptd->dwFlags |= TDF_IGNOREINPUT; ptd->cStackAlloc16 = 0; ModuleUnload(GetExePtr16((HAND16)HIWORD(lparam)), TRUE); FreeCursorIconAlias(ptd->htask16, CIALIAS_HTASK); break; case SG_LOAD_DLL: break; case SG_EXIT_DLL: hModule16 = FETCHWORD(parg16->f1); ModuleUnload(hModule16, FALSE); FreeCursorIconAlias(hModule16, CIALIAS_HMOD); break; } FREEARGPTR(parg16); RETURN(0); } // This routine checks the RECT structure (in PAINTSTRUCT) on BeginPaint // call and updates its fields for maximum positive and minimum negative // numbers for 16 bit apps to be compatible with win 3.1. // void W32FixPaintRect (VPVOID vpPaint, LPPAINTSTRUCT ps) { SHORT i; PPAINTSTRUCT16 pps16; GETVDMPTR(vpPaint, sizeof(PAINTSTRUCT16), pps16); if (i = ConvertInt16 (ps->rcPaint.left)) { STORESHORT(pps16->rcPaint.left, i); } if (i = ConvertInt16 (ps->rcPaint.top)) { STORESHORT(pps16->rcPaint.top, i); } if (i = ConvertInt16 (ps->rcPaint.right)) { STORESHORT(pps16->rcPaint.right, i); } if (i = ConvertInt16 (ps->rcPaint.bottom)) { STORESHORT(pps16->rcPaint.bottom, i); } FLUSHVDMPTR(vpPaint, sizeof(PAINTSTRUCT16), pps16); FREEVDMPTR(pps16); } SHORT ConvertInt16 (LONG x) { if (x > (LONG)0x7fff) return((SHORT)0x7fff); if (x < (LONG)0xffff8000) return((SHORT)0x8000); return ((SHORT)0); }