INF: Win32s 1.1 Limitations
PSS ID Number: Q114340
Article last modified on 07-08-1994

1.10

WINDOWS


----------------------------------------------------------------------
The information in this article applies to:

 - Microsoft Win32s, version 1.1
----------------------------------------------------------------------

SUMMARY
=======

The following is a list of limitations of Win32s, not including the
complete list of unsupported Win32 APIs.

MORE INFORMATION
================

 - Thread creation is not supported.

 - Win32s uses the Windows 3.1 nonpreemptive scheduling mechanism.

 - Win32s has a shared address space, so instance data for dynamic link
   libraries (DLLs) is not supported.

 - Win32 processes should be started from a Win16 application through
   WinExec() or Int 21 4B. LoadModule() does not start a Win32 process.

 - Win32 applications cannot use the EM_SETHANDLE or EM_GETHANDLE messages
   to access the text in a multiline edit control. These messages allow the
   sharing of local memory handles between an application and USER.EXE. In
   Win32s, an application's local heap is 32-bit, so USER.EXE cannot
   interpret the local handle. To read and write multiline edit control
   text, an application should use WM_GETTEXT and WM_SETTEXT.

   Text for multiline edit controls is stored in the 16-bit local heap in
   DGROUP, which is allocated by Windows 3.1 for the WIN32S.EXE stub that
   is loaded before each Win32 application is loaded. This means that the
   size of edit control text is limited to somewhat less than 64K.

 - The CBT hook thunks do not copy back the contents of structures, so any
   changes will be lost.

 - Win32 applications should not call through return from SetWindowsHook().
   SetWindowsHook() returns a pointer to the next hook in the chain. To
   call this function, the application is supposed to call DefHookProc()
   and pass a pointer to a variable where this address is stored. Because
   Win32s simulates the old hook API in terms of the new, SetWindowsHook()
   actually passes back a hook handle, not a function pointer.

 - Win32s requires all modules to be linked with 4K alignment. Temporarily,
   the loader supports 64K as well.

 - Integer ID must be a 16-bit value.

 - PostMessage() and PeekMessage() do not thunk structures. These functions
   do not allocate space for repacking structures, because there is no way
   to know when to free up the space.

 - Private application messages should not use high word of wParam. Win32s
   uses Windows 3.1 to deliver window messages. For unknown messages,
   wParam is truncated to make it fit into 16 bits. Therefore, Win32
   applications should not put 32-bit quantities into the wParam of
   privately defined messages, which are unknown to the thunk layer.

 - Win32s allows a Win32 application to allocate memory at a specific
   address; however, because of the shared address space on Windows 3.1,
   this is more likely to fail under Win32s.

 - DDE messages are always posted, not sent, except for two:
   WM_DDE_INITIATE and WM_DDE_ACK, responding to the former. The sent form
   of WM_DDE_ACK is different from the posted form. When sent, no thunking
   of lParam is necessary when going between 16- and 32-bit format.
   However, when posting, the lParam parameter is repacked as two DWORDs
   into private memory, allocated by COMBO.DLL (or by USER.DLL in Windows
   NT). The thunk layer makes this distinction through the InSendMessage()
   function. Therefore, a Win32 application should not do anything in the
   processing of a WM_DDE_INITIATE message that would cause the return code
   from InSendMessage() to be FALSE.

 - The following DDE messages are handled differently by different
   applications under Windows and Win32:

      WM_DDE_ACK
      WM_DDE_ADVISE
      WM_DDE_DATA
      WM_DDE_EXECUTE
      WM_DDE_POKE

   Because of widening of handles, there is not enough space in the Win32
   message parameters for all the Windows 3.1 data. Win32 applications are
   required to call helper functions that package the data into memory
   (DDEPACK structure) referenced by a special handle. Win32s implements
   the helper functions, and allocates the DDEPACK structure on behalf of
   16-bit code when necessary.

   As with other memory handles shared through DDE, there are rules
   concerning who frees the memory allocated by these helper routines:

      lParam = PackDDElParam(...)
      if( PostMessage(...,lParam) )
         receiving window has obligation of freeing memory
         lParam now invalid for this process
      else
         FreeDDElParam(...,lParam)

   A Win32s hook procedure that has called CallNextHookProc() should not
   use the lParam handle if the latter's return code indicates that the
   message has been processed. The hooks that could possibly process a DDE
   message are:

      WH_DEBUG
      WH_HARDWARE
      WH_KEYBOARD
      WH_MOUSE
      WH_MSGFILTER
      WH_SYSMSGFILTER

   In each case, if the hook proc (and therefore CallNextHookEx()) returns
   a non-zero value, the message was either discarded or processed.
   WndProcs should not use the lParam of a DDE message after handing it off
   to any other message API, because they cannot know if the message has
   been processed and therefore must assume that it has been.

 - WDEB386 does not support FreeSegment() for 32-bit segments. Win32s
   Kernel Debugger support depends on it.

 - Resource table size for PE is limited to 32K (not including the resource
   data).

 - SetClipbrdData() must be used only with global handle. Otherwise the
   data can not be accessed by other applications.

 - Win32s supports printing exactly as Windows 3.1 does. Win32s does not
   add beziers, paths, or transforms to GDI; to let applications use these
   features on PostScript printers, you must call the Escape() function
   with the appropriate escape codes.

   Applications link to Windows 3.1 printer drivers through the
   LoadLibrary() and GetProcAddress() APIs, which have special support for
   this purpose. There is no mechanism allowing a Win32 application to link
   to a 16-bit DLL.

 - Win32s does not support the following GDI escape codes:

      BANDINFO                 ;24
      GETSETPAPERBINS          ;29
      ENUMPAPERMETRICS         ;34
      EXTTEXTOUT               ;512
      SETALLJUSTVALUES         ;771

 - Integer atoms must be in the range 0 0x3FFF. This restriction is
   necessary for the current implementation of the window properties API
   thunks: SetProp(), GetProp(), RemoveProp(), EnumProps(), and
   EnumPropsEx(). Integer atoms above 0x4000 are rejected by the thunk
   layer.

 - Arrays must fit in 64K after converting to 16-bit format. An array
   passed to a function such as SetCharABCWidths() or Polyline() must fit
   within 64K after its elements have been converted to their 16-bit form.
   Its 32-bit form may be bigger than 64K.

 - Temporarily, all Windows 3.1 APIs that return void return 1 to the Win32
   application.

 - Win32 child window ID's must be sign-extended 16-bit values. This
   excludes the use of 32-bit pointer values as child ID's.

 - When calling PeekMessage(), a Win32 application should not filter any
   messages for Windows 3.1 internal window classes (button, edit,
   scrollbar, and so forth). The messages for these controls are mapped to
   different values in Win32, and checking for the necessity of mapping is
   time-consuming.

 - The dwThreadId parameter in SetWindowsHookEx() is ignored. The
   dwThreadId is translated to hTask in Windows 3.1. There's a bug in
   Windows 3.1 where if hTask!=NULL, the call may fail. This needs further
   investigation.

 - Floating point (FP) emulation by exception cannot be performed in 16-bit
   applications. When tasks are switched between applications, the CR0-EM
   bit state is not preserved, in order to support 32-bit application FP
   emulation by exception without breaking the existing 16-bit applications
   that use FP instructions. The CR0-EM bit is assumed to be cleared during
   execution of 16-bit-application FP instructions. Upon executing a 16-bit
   application FP instruction, the bit is cleared and reset when switching
   back to a 32-bit application. The CR0-EM bit management is done in the
   Win32s VxD, thus disabling the possibility of getting an int 7 exception
   just by setting the CR0-EM bit in a 16-bit application.

 - EndDialog() nResult parameter is sign-extended. Applications specify the
   return value for the DialogBox() function by way of the nResult
   parameter to the EndDialog() function. This parameter is of type "int",
   which is 32-bit in Win32s. However, this value is thunked through to the
   Windows 3.1 EndDialog() function, which truncates it to a 16-bit value.
   Win32s sign-extends the return code from DialogBox().

 - GetClipBox() returns SIMPLEREGION(2) and COMPLEXREGION(3). Because
   Windows NT is a preemptive multitasking system, GetClipBox() on Windows
   NT never returns SIMPLEREGION(2); the reason for this is that between
   the time the API was called and the time the application gets the
   result, the region may change. Win32s can return both SIMPLEREGION(2)
   and COMPLEXREGION(3).

 - PeekMessage() filtering for posted messages (hWnd==-1) is not supported.
   The hWnd is replaced with NULL.

 - Message queue length is limited to Windows default: 8 (or whatever the
   length) was set by DefaultQueueSize=n in WIN.INI. This limit may be
   increased in the future to a larger size, but there will always be a
   limit.

 - GetFileTime() and SetFileTime() process only the lpLastWriteTime
   parameter and return an error if this parameter is not supplied.

 - The precision of the time of a file is 2 seconds (DOS limitation).

 - CommDlg does not support private dialog templates. The dialog templates
   need to be converted back and forth between 16- and 32-bit formats.
   Until Win32s 1.15, private dialog templates are not supported.

 - GetPrivateProfileString() returns an error when the lpszSection
   parameter is NULL instead of giving all the section names in the
   inifile, as it does under Windows NT.

 - TLS locations are the same in all processes for a specific DLL. This is
   because Win32s does not support instance data for DLLs. The TLS
   locations are unique per DLL. Each DLL should call TlsAlloc() only once
   per index if it is running under Win32s. The index returned is then
   valid for all Win32 processes. The DLL can maintain several indices.

 - GlobalCompact() is thunked through to the Windows 3.1 GlobalCompact().
   This API has no effect on memory allocated through VirtualAlloc(), which
   does not come from the Win3.1 global heap.

 - GetVolumeInformation() does not support the Volume ID.

 - GetFileInformationByHandle() and the CRT fstat() that uses it are not
   supported. Both are supported in Win32s, version 1.15. The
   dwFileAttribute of GetFileInformationByHandle() is always zero. This
   also causes fstat() to return an st_mode of read/write regardless the
   actual attribute.

 - CreatePolyPolygonRgn() requires a closed polygon, as it does under
   Windows 3.1. If the polygons are not closed, the Windows NT call closes
   the polygons for you. In Windows 3.1/Win32s, if the polygons are not
   closed, the call does not create the region correctly or returns an
   error for an invalid parameter.

 - Win32s does not support DIB_PAL_INDICES option for SetDIBits(). It will
   be supported in future release. DIB_PAL_PHYSINDICES and
   DIB_PAL_LOGINDICES are not supported either.

 - The WH_FOREGROUNDIDLE hook type is not supported. Windows 3.1 does not
   provide the necessary support.

 - The brush styles BS_DIBPATTERNPT and BS_PATTERN8X8 are not supported and
   cause an error to be returned.

 - The hFile in DLL and PROCESS events is not supported under Win32s
   because there is no support for duplicating file handles between
   processes (basically an MS-DOS limitation).

   There are two ways to access the image bytes: ReadProcessMemory() or
   open the file in compatibility mode (the name is provided in
   lplpImageName).

 - Under Windows NT, NetBIOS keeps a different name table for each process.

   On Win32s, there is only one NetBIOS name table for the system. Each
   name (group or unique) added by a process is kept in a doubly linked
   list. Through NCBRESET or by destroying the process, we delete all the
   names that were added by the process. Win32s does not implement the full
   NetBIOS 3.0 specification, which has a separate name table per process.

 - When calling 32-bit code from 16-bit code with UT (for example, from
   interrupt routine) the stack must be at least 10K. The interrupt routine
   must ensure that the stack will be big enough.

 - Get/SetThreadContext() can be called only from within an exception. At
   all other times, this function returns FALSE and the error code is set
   to ERROR_CAN_NOT_COMPLETE.

 - CreateProcess() PROCESS_INFORMATION is not supported for 16-bit
   applications. A valid structure must be passed to CreateProcess(), but
   the function fills all the fields with NULLs and zeroes.

 - CreateProcess() does not support handle inheritance.

 - CreateFile() FILE_FLAG_NO_BUFFERING and FILE_FLAG_WRITE_THROUGH are not
   supported.

 - Win32s does not support NT event mechanism; therefore, the ncb_event
   field in NCB structure is not supported.

 - CreateFileMapping() does not support SEC_NOCACHE nor SEC_NOCOMMIT. The
   call fails with ERROR_INVALID_PARAMETER.

 - When EM_GETFIRSTVISIBLELINE is sent to a single-line edit control, the
   return is always 0. This is the underlying Windows 3.1 behavior. New
   behavior was added under Windows NT. The return is the same for a multi-
   line edit control under Win32s and Windows NT.

 - Always use device-independent bitmaps for color bitmaps. Win32s supports
   the four Win32 "device-dependent" bitmap APIs. These are device-
   dependent in the sense that the bitmap bits are supplied without a color
   table to explain their meaning.

      CreateBitmap
      CreateBitmapIndirect
      GetBitmapBits
      SetBitmapBits

   These are well-defined and fully supported for monochrome bitmaps. For
   color bitmaps, these APIs are not well defined and Win32s relies on
   Windows 3.1 for their support. This means that an application cannot
   know the format of the bits returned by GetBitmapBits() and should not
   attempt to directly manipulate them. The values returned by
   GetDeviceCaps() for PLANES and BITSPIXEL, and the values returned by
   GetObject() for a bitmap, do not necessarily indicate the format of the
   bits returned by GetBitmapBits().It is possible for the GDI DIB APIs to
   be unsupported on some displays. However, it is now rare for display
   drivers to not support DIBs. The one case where it is not uncommon to
   encounter a lack of DIB support is with printer drivers, which may not
   support the GetDIBits() API, though most do support the SetDIBits() API.

   Win32s does not transform the bits in any way when passing them on to a
   Windows 3.1 API. When running an application that creates a device-
   dependent bitmap through CreateBitmap() or CreateBitmapIndirect(), be
   aware that the bits it is passing in may not be in the right format for
   the device. Windows NT takes care of this by treating the bits as a DIB
   whose format is consistent with the PLANES and BITSPIXEL values; but
   Win32s simply passes them through.

 - After calling FindText(), an application cannot directly access the
   FINDREPLACE structure. When an application calls the common dialog box
   function FindText(), it passes a FINDREPLACE structure. The FindText()
   dialog box communicates with the owner window through a registered
   message, in which the lParam points to the structure. The thunks repack
   this structure in place, so that unless the application is processing
   the registered message, it should not access the structure.

 - Subclassing a window that owns a FindText() common dialog does not work.
   The FindText() thunk repacks the FINDREPLACE structure in place. This
   means that 32-bit WndProcs cannot subclass 16-bit owners of FindText()
   dialog boxes without likely trashing four bytes beyond the end of the
   structure, because the 32-bit FINDREPLACE is four bytes bigger than the
   16-bit version.

   For 32-bit owners of the dialog box, there are also problems. Whenever
   the structure might be referenced by 16-bit code, it needs to be in the
   16-bit format. However, when the FindText() dialog box terminates, the
   structure needs to be in 32-bit format so that the application can read
   the final values. The dialog box indicates to its owner that it is about
   to be destroyed by sending the commdlg_FindReplace message with the
   FR_DIALOGTERM bit set in the Flags field of the FINDREPLACE structure.
   After sending this message, the FindText() dialog does not reference the
   structure anymore, so that the commdlg_FindReplace thunk leaves it in
   32-bit format.

   The problem occurs when the owner has been subclassed. Once the message
   has moved to the 32-bit side, the structure is not reconverted to 16-
   bit. Suppose the dialog box owner was subclassed by a 16-bit WndProc,
   which was in turn subclassed by a 32-bit WndProc. When a message is sent
   to the owner, it will first go to 32-bit, then to 16-bit, then back to
   32-bit to the original WndProc:

   1. 16->32 message sent to 32-bit subclasser (repacked to 32-bit)

   2. 32->16 message sent to 16-bit subclasser (not repacked)

   3. 16->32 message sent to 32-bit original WndProc (not repacked)

   The 16-bit subclasser cannot interpret the message parameters because
   they are in 32-bit format. Between steps 2 and 3, the structure is not
   repacked because it's already in 32-bit format.

   When a Win32 application calls FindText(), allocate the following:

   1. A structure that contains the htask of WIN32S.EXE

   2. The original 32-bit FINDREPLACE pointer

   3. A count of the number of times the structure has been thunked without
      returning

   4. A 16-bit format copy of FINDREPLACE

   The structure is repacked into the 16-bit version and this copy is
   passed to Windows. The count is initially zero. When the
   commdlg_FindReplace message is sent in either direction (16->32 or
   32->16), repack the structure on the stack. If it was originally 32-bit,
   increment the count. When returning, unpack the structure and, if
   originally 32-bit, decrement the count. If the Flags field of the
   structure has the FR_DIALOGTERM bit set, the structure is originally 32-
   bit, and the count goes to 0 on a return, then repack the structure back
   to the original 32-bit space.

Additional reference words: 1.10
KBCategory: Prg
KBSubcategory: W32s

=============================================================================

Copyright Microsoft Corporation 1994.
