Alexandre Julliard : user32: Pack the CREATESTRUCTW structure in messages to allow crossing 32/ 64 boundaries.

Alexandre Julliard julliard at winehq.org
Wed Mar 31 10:04:48 CDT 2010


Module: wine
Branch: master
Commit: fcf8a819047e4ac2bbc02554e94bb233a4607d9e
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=fcf8a819047e4ac2bbc02554e94bb233a4607d9e

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Mar 30 20:26:10 2010 +0200

user32: Pack the CREATESTRUCTW structure in messages to allow crossing 32/64 boundaries.

---

 dlls/user32/message.c |  139 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 116 insertions(+), 23 deletions(-)

diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index f8e4a43..cab4113 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -56,12 +56,41 @@ WINE_DECLARE_DEBUG_CHANNEL(key);
 
 #define SYS_TIMER_RATE  55   /* min. timer rate in ms (actually 54.925)*/
 
+/* the various structures that can be sent in messages, in platform-independent layout */
+struct packed_CREATESTRUCTW
+{
+    ULONGLONG     lpCreateParams;
+    ULONGLONG     hInstance;
+    user_handle_t hMenu;
+    DWORD         __pad1;
+    user_handle_t hwndParent;
+    DWORD         __pad2;
+    INT           cy;
+    INT           cx;
+    INT           y;
+    INT           x;
+    LONG          style;
+    ULONGLONG     lpszName;
+    ULONGLONG     lpszClass;
+    DWORD         dwExStyle;
+    DWORD         __pad3;
+};
+
+/* the structures are unpacked on top of the packed ones, so make sure they fit */
+C_ASSERT( sizeof(struct packed_CREATESTRUCTW) >= sizeof(CREATESTRUCTW) );
+
+union packed_structs
+{
+    struct packed_CREATESTRUCTW cs;
+};
+
 /* description of the data fields that need to be packed along with a sent message */
 struct packed_message
 {
-    int         count;
-    const void *data[MAX_PACK_COUNT];
-    size_t      size[MAX_PACK_COUNT];
+    union packed_structs ps;
+    int                  count;
+    const void          *data[MAX_PACK_COUNT];
+    size_t               size[MAX_PACK_COUNT];
 };
 
 /* info about the message currently being received by the current thread */
@@ -267,6 +296,19 @@ static inline BOOL check_string( LPCWSTR str, size_t size )
     return FALSE;
 }
 
+/* pack a pointer into a 32/64 portable format */
+static inline ULONGLONG pack_ptr( const void *ptr )
+{
+    return (ULONG_PTR)ptr;
+}
+
+/* unpack a potentially 64-bit pointer, returning 0 when truncated */
+static inline void *unpack_ptr( ULONGLONG ptr64 )
+{
+    if ((ULONG_PTR)ptr64 != ptr64) return 0;
+    return (void *)(ULONG_PTR)ptr64;
+}
+
 /* make sure that there is space for 'size' bytes in buffer, growing it if needed */
 static inline void *get_buffer_space( void **buffer, size_t size )
 {
@@ -544,10 +586,22 @@ static size_t pack_message( HWND hwnd, UINT message, WPARAM wparam, LPARAM lpara
     case WM_CREATE:
     {
         CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
-        push_data( data, cs, sizeof(*cs) );
+        data->ps.cs.lpCreateParams = pack_ptr( cs->lpCreateParams );
+        data->ps.cs.hInstance      = pack_ptr( cs->hInstance );
+        data->ps.cs.hMenu          = wine_server_user_handle( cs->hMenu );
+        data->ps.cs.hwndParent     = wine_server_user_handle( cs->hwndParent );
+        data->ps.cs.cy             = cs->cy;
+        data->ps.cs.cx             = cs->cx;
+        data->ps.cs.y              = cs->y;
+        data->ps.cs.x              = cs->x;
+        data->ps.cs.style          = cs->style;
+        data->ps.cs.dwExStyle      = cs->dwExStyle;
+        data->ps.cs.lpszName       = pack_ptr( cs->lpszName );
+        data->ps.cs.lpszClass      = pack_ptr( cs->lpszClass );
+        push_data( data, &data->ps.cs, sizeof(data->ps.cs) );
         if (!IS_INTRESOURCE(cs->lpszName)) push_string( data, cs->lpszName );
         if (!IS_INTRESOURCE(cs->lpszClass)) push_string( data, cs->lpszClass );
-        return sizeof(*cs);
+        return sizeof(data->ps.cs);
     }
     case WM_GETTEXT:
     case WM_ASKCBFORMATNAME:
@@ -774,28 +828,42 @@ static BOOL unpack_message( HWND hwnd, UINT message, WPARAM *wparam, LPARAM *lpa
                             void **buffer, size_t size )
 {
     size_t minsize = 0;
+    union packed_structs *ps = *buffer;
 
     switch(message)
     {
     case WM_NCCREATE:
     case WM_CREATE:
     {
-        CREATESTRUCTW *cs = *buffer;
-        WCHAR *str = (WCHAR *)(cs + 1);
-        if (size < sizeof(*cs)) return FALSE;
-        size -= sizeof(*cs);
-        if (!IS_INTRESOURCE(cs->lpszName))
+        CREATESTRUCTW cs;
+        WCHAR *str = (WCHAR *)(&ps->cs + 1);
+        if (size < sizeof(ps->cs)) return FALSE;
+        size -= sizeof(ps->cs);
+        cs.lpCreateParams = unpack_ptr( ps->cs.lpCreateParams );
+        cs.hInstance      = unpack_ptr( ps->cs.hInstance );
+        cs.hMenu          = wine_server_ptr_handle( ps->cs.hMenu );
+        cs.hwndParent     = wine_server_ptr_handle( ps->cs.hwndParent );
+        cs.cy             = ps->cs.cy;
+        cs.cx             = ps->cs.cx;
+        cs.y              = ps->cs.y;
+        cs.x              = ps->cs.x;
+        cs.style          = ps->cs.style;
+        cs.dwExStyle      = ps->cs.dwExStyle;
+        cs.lpszName       = unpack_ptr( ps->cs.lpszName );
+        cs.lpszClass      = unpack_ptr( ps->cs.lpszClass );
+        if (ps->cs.lpszName >> 16)
         {
             if (!check_string( str, size )) return FALSE;
-            cs->lpszName = str;
+            cs.lpszName = str;
             size -= (strlenW(str) + 1) * sizeof(WCHAR);
             str += strlenW(str) + 1;
         }
-        if (!IS_INTRESOURCE(cs->lpszClass))
+        if (ps->cs.lpszClass >> 16)
         {
             if (!check_string( str, size )) return FALSE;
-            cs->lpszClass = str;
+            cs.lpszClass = str;
         }
+        memcpy( &ps->cs, &cs, sizeof(cs) );
         break;
     }
     case WM_GETTEXT:
@@ -1053,8 +1121,23 @@ static void pack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
     {
     case WM_NCCREATE:
     case WM_CREATE:
-        push_data( data, (CREATESTRUCTW *)lparam, sizeof(CREATESTRUCTW) );
+    {
+        CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
+        data->ps.cs.lpCreateParams = (ULONG_PTR)cs->lpCreateParams;
+        data->ps.cs.hInstance      = (ULONG_PTR)cs->hInstance;
+        data->ps.cs.hMenu          = wine_server_user_handle( cs->hMenu );
+        data->ps.cs.hwndParent     = wine_server_user_handle( cs->hwndParent );
+        data->ps.cs.cy             = cs->cy;
+        data->ps.cs.cx             = cs->cx;
+        data->ps.cs.y              = cs->y;
+        data->ps.cs.x              = cs->x;
+        data->ps.cs.style          = cs->style;
+        data->ps.cs.dwExStyle      = cs->dwExStyle;
+        data->ps.cs.lpszName       = (ULONG_PTR)cs->lpszName;
+        data->ps.cs.lpszClass      = (ULONG_PTR)cs->lpszClass;
+        push_data( data, &data->ps.cs, sizeof(data->ps.cs) );
         break;
+    }
     case WM_GETTEXT:
     case CB_GETLBTEXT:
     case LB_GETTEXT:
@@ -1132,18 +1215,28 @@ static void pack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
 static void unpack_reply( HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam,
                           void *buffer, size_t size )
 {
+    union packed_structs *ps = buffer;
+
     switch(message)
     {
     case WM_NCCREATE:
     case WM_CREATE:
-    {
-        CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
-        LPCWSTR name = cs->lpszName, class = cs->lpszClass;
-        memcpy( cs, buffer, min( sizeof(*cs), size ));
-        cs->lpszName = name;  /* restore the original pointers */
-        cs->lpszClass = class;
+        if (size >= sizeof(ps->cs))
+        {
+            CREATESTRUCTW *cs = (CREATESTRUCTW *)lparam;
+            cs->lpCreateParams = unpack_ptr( ps->cs.lpCreateParams );
+            cs->hInstance      = unpack_ptr( ps->cs.hInstance );
+            cs->hMenu          = wine_server_ptr_handle( ps->cs.hMenu );
+            cs->hwndParent     = wine_server_ptr_handle( ps->cs.hwndParent );
+            cs->cy             = ps->cs.cy;
+            cs->cx             = ps->cs.cx;
+            cs->y              = ps->cs.y;
+            cs->x              = ps->cs.x;
+            cs->style          = ps->cs.style;
+            cs->dwExStyle      = ps->cs.dwExStyle;
+            /* don't allow changing name and class pointers */
+        }
         break;
-    }
     case WM_GETTEXT:
     case WM_ASKCBFORMATNAME:
         memcpy( (WCHAR *)lparam, buffer, min( wparam*sizeof(WCHAR), size ));
@@ -1248,7 +1341,7 @@ static void reply_message( struct received_message_info *info, LRESULT result, B
     if (info->flags & ISMEX_NOTIFY) return;  /* notify messages don't get replies */
     if (!remove && replied) return;  /* replied already */
 
-    data.count = 0;
+    memset( &data, 0, sizeof(data) );
     info->flags |= ISMEX_REPLIED;
 
     if (info->type == MSG_OTHER_PROCESS && !replied)
@@ -2315,7 +2408,7 @@ static BOOL put_message_in_queue( const struct send_message_info *info, size_t *
         timeout = (timeout_t)max( 0, (int)info->timeout ) * -10000;
     }
 
-    data.count = 0;
+    memset( &data, 0, sizeof(data) );
     if (info->type == MSG_OTHER_PROCESS)
     {
         *reply_size = pack_message( info->hwnd, info->msg, info->wparam, info->lparam, &data );




More information about the wine-cvs mailing list