Packing in mmsystem16 and supporting broken GetWindowLong use cases

Jukka Heinonen jhei at iki.fi
Wed Nov 21 06:13:33 CST 2001


The following two patches are required to make Civilization 2 work.
The first patch is needed because Civilization 2 calls GetWindowLong16
with an illegal offset value and really expects to get the last long
value instead of an error (thanks to Ove Kaaven for hinting that this
might be the case).

The second patch is because Wine mmsystem16 header does not use
correct packing which results into 48 byte structure taking
52 bytes and overwriting a pointer. This makes Civilization 2
quite unhappy. Took almost a day to debug the game and 
find out that the bugger who messes the pointer is really 
waveOutGetDevCaps16...


Changelog:
  Added support for broken 16 bit applications that want to call
  GetWindowLong16 with an illegal offset value and expect to get
  not an error but the last long value.

Index: wine/windows/win.c
===================================================================
RCS file: /home/wine/wine/windows/win.c,v
retrieving revision 1.169
diff -u -r1.169 win.c
--- wine/windows/win.c  2001/11/14 21:28:37     1.169
+++ wine/windows/win.c  2001/11/21 10:13:11
@@ -1846,6 +1846,24 @@
     {
         if (offset > wndPtr->cbWndExtra - sizeof(LONG))
         {
+           /*
+            * Some programs try to access last element from 16 bit
+            * code using illegal offset value. Hopefully this is
+            * what those programs really expect.
+            */
+           if (type == WIN_PROC_16 && 
+               offset == wndPtr->cbWndExtra - sizeof(WORD))
+           {
+             INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
+
+             TRACE( "- replaced invalid offset %d with %d\n",
+                    offset, offset2 );
+
+             retvalue = *(LONG *)(((char *)wndPtr->wExtra) + offset2);
+             WIN_ReleasePtr( wndPtr );
+             return retvalue;
+           }
+
             WARN("Invalid offset %d\n", offset );
             WIN_ReleasePtr( wndPtr );
             SetLastError( ERROR_INVALID_INDEX );


Changelog:
  Added instructions to pack structures correctly.
  Added missing C++ wrapper.

Index: wine/include/wine/mmsystem16.h
===================================================================
RCS file: /home/wine/wine/include/wine/mmsystem16.h,v
retrieving revision 1.3
diff -u -r1.3 mmsystem16.h
--- wine/include/wine/mmsystem16.h      2000/12/13 20:20:16     1.3
+++ wine/include/wine/mmsystem16.h      2001/11/21 10:22:49
@@ -12,6 +12,8 @@
 #include "windef.h"
 #include "wine/windef16.h"
 
+#include "pshpack1.h"
+
 typedef UINT16 MMVERSION16;
 typedef UINT16 MCIDEVICEID16;
 typedef        UINT16  MMRESULT16;
@@ -565,5 +567,11 @@
     LPCSTR     lpfilename;
     RECT16     rc;
 } MCI_OVLY_LOAD_PARMS16, *LPMCI_OVLY_LOAD_PARMS16;
+
+#include "poppack.h"
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif  /* __WINE_WINE_MMSYSTEM16_H */


-- 
Jukka Heinonen <http://www.iki.fi/jhei/>




More information about the wine-patches mailing list