Index: trunk/src/kernel32/wprocess.cpp
===================================================================
--- trunk/src/kernel32/wprocess.cpp	(revision 10010)
+++ trunk/src/kernel32/wprocess.cpp	(revision 10012)
@@ -1,3 +1,3 @@
-/* $Id: wprocess.cpp,v 1.186 2003-04-02 11:03:33 sandervl Exp $ */
+/* $Id: wprocess.cpp,v 1.187 2003-04-11 14:21:53 sandervl Exp $ */
 
 /*
@@ -373,4 +373,11 @@
     if(winteb->o.odin.hPostMsgEvent) {
         CloseHandle(winteb->o.odin.hPostMsgEvent);
+    }
+
+    // free shared memory for WM_COPYDATA
+    if (winteb->o.odin.pWM_COPYDATA)
+    {
+        dprintf(("DestroyTEB: freeing WM_COPYDATA: %#p", winteb->o.odin.pWM_COPYDATA));
+        _sfree(winteb->o.odin.pWM_COPYDATA);
     }
 
@@ -2005,5 +2012,5 @@
 
     //Only use WGSS to launch the app if it's not PE or PE & win32k loaded
-    if(!fPEExe || (fPEExe && fWin32k)) 
+    if(!fPEExe || (fPEExe && fWin32k))
     {
       if(O32_CreateProcess(szAppName, lpCommandLine, lpProcessAttributes,
@@ -2031,10 +2038,10 @@
             lpProcessInfo->dwThreadId = MAKE_THREADID(lpProcessInfo->dwProcessId, lpProcessInfo->dwThreadId);
         }
-  
+
         if(cmdline)
             free(cmdline);
         return(TRUE);
       }
-  
+
       // verify why O32_CreateProcess actually failed.
       // If GetLastError() == 191 (ERROR_INVALID_EXE_SIGNATURE)
Index: trunk/src/user32/oslibmsg.cpp
===================================================================
--- trunk/src/user32/oslibmsg.cpp	(revision 10010)
+++ trunk/src/user32/oslibmsg.cpp	(revision 10012)
@@ -1,3 +1,3 @@
-/* $Id: oslibmsg.cpp,v 1.67 2003-03-28 11:49:01 sandervl Exp $ */
+/* $Id: oslibmsg.cpp,v 1.68 2003-04-11 14:22:05 sandervl Exp $ */
 /*
  * Window message translation functions for OS/2
@@ -53,5 +53,5 @@
 #include "user32api.h"
 
-#define DBG_LOCALLOG	DBG_oslibmsg
+#define DBG_LOCALLOG    DBG_oslibmsg
 #include "dbglocal.h"
 
@@ -210,12 +210,12 @@
         teb->o.odin.winmsg.time = -1;
         if(msg->hwnd) {
-            	teb->o.odin.nrOfMsgs = 1;
-            	teb->o.odin.msgstate++; //odd -> next call to our PM window handler should dispatch the translated msg
-            	memcpy(&teb->o.odin.msg, msg, sizeof(MSG));
+                teb->o.odin.nrOfMsgs = 1;
+                teb->o.odin.msgstate++; //odd -> next call to our PM window handler should dispatch the translated msg
+                memcpy(&teb->o.odin.msg, msg, sizeof(MSG));
         }
         if(os2msg.hwnd || os2msg.msg == WM_QUIT) {
-		memset(&teb->o.odin.os2msg, 0, sizeof(teb->o.odin.os2msg));
-		memset(&teb->o.odin.winmsg, 0, sizeof(teb->o.odin.winmsg));
-            	return (LONG)WinDispatchMsg(teb->o.odin.hab, &os2msg);
+                memset(&teb->o.odin.os2msg, 0, sizeof(teb->o.odin.os2msg));
+                memset(&teb->o.odin.winmsg, 0, sizeof(teb->o.odin.winmsg));
+                return (LONG)WinDispatchMsg(teb->o.odin.hab, &os2msg);
         }
         //SvL: Don't dispatch messages sent by PostThreadMessage (correct??)
@@ -241,11 +241,11 @@
 
     if(hwnd) {
-      	hwndOS2 = Win32ToOS2Handle(hwnd);
-    	if(hwndOS2 == NULL) {
-		    memset(pMsg, 0, sizeof(MSG));
-		    dprintf(("GetMsg: window %x NOT FOUND!", hwnd));
-		    SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
-		    return TRUE;
-	    }
+        hwndOS2 = Win32ToOS2Handle(hwnd);
+        if(hwndOS2 == NULL) {
+                    memset(pMsg, 0, sizeof(MSG));
+                    dprintf(("GetMsg: window %x NOT FOUND!", hwnd));
+                    SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
+                    return TRUE;
+            }
     }
 
@@ -253,8 +253,8 @@
     if(teb == NULL) {
         DebugInt3();
-    	return TRUE;
-    }
-    
-    if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd)) 
+        return TRUE;
+    }
+
+    if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd))
     {
         dprintf(("Return queued WM_CHAR message hwnd=%x msg=%d wParam=%x lParam=%x", teb->o.odin.msgWCHAR.hwnd, teb->o.odin.msgWCHAR.message, teb->o.odin.msgWCHAR.wParam, teb->o.odin.msgWCHAR.lParam));
@@ -277,5 +277,5 @@
         teb->o.odin.os2msg.msg  = 0;
         teb->o.odin.os2msg.hwnd = 0;
-    
+
         if(!IsWindow(pMsg->hwnd)) {
             //could be a queued char message for a window that was just destroyed
@@ -306,14 +306,14 @@
 continuegetmsg:
     if(hwnd) {
-    	filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
-	    filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
-	    if(filtermin > filtermax) {
-    		ULONG tmp = filtermin;
-		    filtermin = filtermax;
-		    filtermax = filtermin;
-	    }
+        filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
+            filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
+            if(filtermin > filtermax) {
+                ULONG tmp = filtermin;
+                    filtermin = filtermax;
+                    filtermax = filtermin;
+            }
         do {
-            	WinWaitMsg(teb->o.odin.hab, filtermin, filtermax);
-            	rc = OSLibWinPeekMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, PM_REMOVE_W, isUnicode);
+                WinWaitMsg(teb->o.odin.hab, filtermin, filtermax);
+                rc = OSLibWinPeekMsg(pMsg, hwnd, uMsgFilterMin, uMsgFilterMax, PM_REMOVE_W, isUnicode);
         }
         while(rc == FALSE);
@@ -323,16 +323,16 @@
     else
     {
-    	filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
-	    filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
-	    if(filtermin > filtermax) {
-    		ULONG tmp = filtermin;
-		    filtermin = filtermax;
-		    filtermax = filtermin;
-	    }
-    	do {
-        	eaten = FALSE;
-	        rc = WinGetMsg(teb->o.odin.hab, &os2msg, 0, filtermin, filtermax);
-	        if (os2msg.msg == WM_TIMER)
-	            eaten = TIMER_HandleTimer(&os2msg);
+        filtermin = TranslateWinMsg(uMsgFilterMin, TRUE);
+            filtermax = TranslateWinMsg(uMsgFilterMax, FALSE);
+            if(filtermin > filtermax) {
+                ULONG tmp = filtermin;
+                    filtermin = filtermax;
+                    filtermax = filtermin;
+            }
+        do {
+                eaten = FALSE;
+                rc = WinGetMsg(teb->o.odin.hab, &os2msg, 0, filtermin, filtermax);
+                if (os2msg.msg == WM_TIMER)
+                    eaten = TIMER_HandleTimer(&os2msg);
                 if (os2msg.msg == WM_QUIT && ((ULONG)os2msg.mp2 != 0) ) {
                     // Don't return FALSE when the window list sends us
@@ -342,7 +342,7 @@
                     // in this case. When the app calls PostQuitMessage (mp2 == 0),
                     // then we handle it the normal way
-                    rc = 1; 
+                    rc = 1;
                 }
-	    } 
+            }
         while (eaten);
     }
@@ -356,5 +356,5 @@
     memcpy(&teb->o.odin.os2msg, &os2msg, sizeof(QMSG));
     memcpy(&teb->o.odin.winmsg, pMsg, sizeof(MSG));
-  
+
     // send keyboard messages to the registered hooks
     switch (pMsg->message)
@@ -375,13 +375,13 @@
 
 //******************************************************************************
-//PeekMessage retrieves only messages associated with the window identified by the 
-//hwnd parameter or any of its children as specified by the IsChild function, and within 
-//the range of message values given by the uMsgFilterMin and uMsgFilterMax 
-//parameters. If hwnd is NULL, PeekMessage retrieves messages for any window that 
-//belongs to the current thread making the call. (PeekMessage does not retrieve 
-//messages for windows that belong to other threads.) If hwnd is -1, PeekMessage only 
-//returns messages with a hwnd value of NULL, as posted by the PostAppMessage 
-//function. If uMsgFilterMin and uMsgFilterMax are both zero, PeekMessage returns all 
-//available messages (no range filtering is performed). 
+//PeekMessage retrieves only messages associated with the window identified by the
+//hwnd parameter or any of its children as specified by the IsChild function, and within
+//the range of message values given by the uMsgFilterMin and uMsgFilterMax
+//parameters. If hwnd is NULL, PeekMessage retrieves messages for any window that
+//belongs to the current thread making the call. (PeekMessage does not retrieve
+//messages for windows that belong to other threads.) If hwnd is -1, PeekMessage only
+//returns messages with a hwnd value of NULL, as posted by the PostAppMessage
+//function. If uMsgFilterMin and uMsgFilterMax are both zero, PeekMessage returns all
+//available messages (no range filtering is performed).
 //TODO: Not working as specified right now!
 //******************************************************************************
@@ -401,10 +401,10 @@
     }
     if(hwnd && hwnd != -1) {
-  	    hwndOS2 = Win32ToOS2Handle(hwnd);
-	    if(hwndOS2 == NULL) {
-    		dprintf(("PeekMsg: window %x NOT FOUND!", hwnd));
-		    SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
-		    return FALSE;
-	    }
+            hwndOS2 = Win32ToOS2Handle(hwnd);
+            if(hwndOS2 == NULL) {
+                dprintf(("PeekMsg: window %x NOT FOUND!", hwnd));
+                    SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
+                    return FALSE;
+            }
     }
 
@@ -415,5 +415,5 @@
     }
 
-    if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd)) 
+    if(teb->o.odin.fTranslated && (!hwnd || hwnd == teb->o.odin.msgWCHAR.hwnd))
     {
         dprintf(("Return queued WM_CHAR message hwnd=%x msg=%d wParam=%x lParam=%x", teb->o.odin.msgWCHAR.hwnd, teb->o.odin.msgWCHAR.message, teb->o.odin.msgWCHAR.wParam, teb->o.odin.msgWCHAR.lParam));
@@ -447,5 +447,5 @@
             goto continuepeekmsg;
         }
-    
+
         // @@@PH verify this
         // if this is a keyup or keydown message, we've got to
@@ -466,10 +466,10 @@
             }
         }
-    
+
         return TRUE;
     }
 
 continuepeekmsg:
-    if(uMsgFilterMin && uMsgFilterMax) 
+    if(uMsgFilterMin && uMsgFilterMax)
     {   //we can't use the PM message filter (since the message nrs aren't similar), so we must
         //filter each message seperately
@@ -485,10 +485,10 @@
                     eaten = FALSE;
 
-                    rc = WinPeekMsg(teb->o.odin.hab, &os2msg, hwndOS2, ulPMFilter, ulPMFilter, 
+                    rc = WinPeekMsg(teb->o.odin.hab, &os2msg, hwndOS2, ulPMFilter, ulPMFilter,
                                     (fRemove & PM_REMOVE_W) ? PM_REMOVE : PM_NOREMOVE);
                     //Sadly indeed WinPeekMsg sometimes does not filter well!
                     if (rc && (os2msg.msg != ulPMFilter)) {// drop this message
                        dprintf(("WARNING: WinPeekMsg returns %x even though we filter for %x", os2msg.msg, ulPMFilter));
-                       rc = 0;   
+                       rc = 0;
                     }
                     if (rc && (fRemove & PM_REMOVE_W) && os2msg.msg == WM_TIMER) {
@@ -518,9 +518,9 @@
         return FALSE;
     }
-  
+
     // @@@PH
     // warning - OS2ToWinMsgTranslate might insert additional messages
     // into the queue
-    if(OS2ToWinMsgTranslate((PVOID)teb, &os2msg, pMsg, isUnicode, (fRemove & PM_REMOVE_W) ? MSG_REMOVE : MSG_NOREMOVE) == FALSE) 
+    if(OS2ToWinMsgTranslate((PVOID)teb, &os2msg, pMsg, isUnicode, (fRemove & PM_REMOVE_W) ? MSG_REMOVE : MSG_NOREMOVE) == FALSE)
     {
          //unused PM message; dispatch immediately and grab next one
@@ -535,6 +535,6 @@
     //TODO: This is not safe! There's no guarantee this message will be dispatched and it might overwrite a previous message
     if(fRemove & PM_REMOVE_W) {
-      	memcpy(&teb->o.odin.os2msg, &os2msg, sizeof(QMSG));
-      	memcpy(&teb->o.odin.winmsg, pMsg, sizeof(MSG));
+        memcpy(&teb->o.odin.os2msg, &os2msg, sizeof(QMSG));
+        memcpy(&teb->o.odin.winmsg, pMsg, sizeof(MSG));
     }
 
@@ -627,53 +627,200 @@
     return (BOOL)WinReplyMsg( NULLHANDLE, NULLHANDLE, HMQ_CURRENT, (MRESULT)result);
 }
-//******************************************************************************
-//******************************************************************************
+
+//******************************************************************************
+
+/**
+ * Send and Post message helper for packing down interprocess and interthread messages.
+ *
+ * @returns Pointer to packet on success. (shared memory)
+ * @returns NULL on failure with SendMessage return code suggestion in *pRc if pRc is set.
+ * @param   hwndOdin    Odin window handle. (NULL allowed)
+ * @param   hwndOS2     OS/2 window handle.
+ * @param   msg         Message id.
+ * @param   wParam      Message param.
+ * @param   lParam      Message param.
+ * @param   fUnicode    Unicode or ansi indicator.
+ * @param   pRc         Where to store SendMessage return code. Optional.
+ * @author  knut st. osmundsen<bird@anduin.net>
+ */
+void * OSLibPackMessage(HWND hwndOdin, HWND hwndOS2, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode, PULONG pRc)
+{
+    POSTMSG_PACKET  * pMsgPacket;
+
+    /*
+     * Pack message by id.
+     */
+    switch (msg)
+    {
+        /*
+         * lParam = PCOPYDATASTRUCT.
+         *      Must move this to shared memory together with any
+         *      data it's pointing at.
+         *
+         *      We put everything into the package that might ease cleanup...
+         *      WARNING! Currently there are cleanup hacks which works with acrobat.
+         */
+        case WINWM_COPYDATA:
+        {
+            PCOPYDATASTRUCT_W pOrg = (PCOPYDATASTRUCT_W)lParam;
+            dprintf(("user32::oslibmsg::OSLibPackMessage - WM_COPYDATA: lParam=%#x  dwData=%#x cbData=%d lpData=%#x",
+                     pOrg, pOrg ? pOrg->dwData : -1, pOrg ? pOrg->cbData : -1, pOrg ? pOrg->lpData : (LPVOID)-1));
+
+            /*
+             * Calc packet size.
+             */
+            unsigned cb = sizeof(POSTMSG_PACKET);
+            if (pOrg)
+            {
+                cb += sizeof(COPYDATASTRUCT_W);
+                if (pOrg->lpData && pOrg->cbData)
+                    cb += 16 + pOrg->cbData; //add 16 Bytes for safty and alignment.
+            }
+
+            /*
+             * Allocate packet.
+             */
+            pMsgPacket = (POSTMSG_PACKET *)_smalloc(cb);
+            if (!pMsgPacket)
+            {
+                dprintf(("user32::oslibmsg::OSLibPackMessage - WM_COPYDATA: failed to allocate %d shared bytes for packing", cb));
+                DebugInt3();
+                if (pRc)
+                    *pRc = FALSE;
+                //@todo figure out which error to set. This is plain guesswork!
+                SetLastError(ERROR_NOT_ENOUGH_MEMORY_W);
+                break;
+            }
+
+            /*
+             * Initialize packet.
+             */
+            PCOPYDATASTRUCT_W pNew = (PCOPYDATASTRUCT_W)(pMsgPacket + 1);
+            pMsgPacket->wParam = wParam;
+            pMsgPacket->lParam = (LPARAM)pNew;
+            *pNew = *pOrg;
+            if (pNew->cbData && pNew->lpData)
+            {
+                pNew->lpData = (LPVOID)(((unsigned)(pNew + 1) + 15) & ~15); //16byte align for safty.
+                //@todo what about a safe_memcpy?
+                memcpy(pNew->lpData, pOrg->lpData, pNew->cbData);
+            }
+
+            /* done! */
+            dprintf(("user32::oslibmsg::OSLibPackMessage - WM_COPYDATA: Packed down %d bytes at %#x (pMsgPacket)",
+                     cb, pMsgPacket));
+            break;
+        }
+
+
+        /*
+         * Default packing
+         */
+        default:
+        {
+            pMsgPacket = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
+            if (!pMsgPacket)
+            {
+                dprintf(("user32::oslibmsg::OSLibPackMessage - allocated packet structure is NULL"));
+                if (pRc)
+                {   // Can't find any better return code than 0 :/
+                    *pRc = 0;
+                }
+                DebugInt3();
+                break;
+            }
+            pMsgPacket->wParam = wParam;
+            pMsgPacket->lParam = lParam;
+        }
+
+    }
+
+    return pMsgPacket;
+}
+
+
+/**
+ * Send an inter thread/proces message.
+ *
+ * @returns
+ * @param   hwnd        OS/2 hwnd.
+ * @param   msg         Odin message id.
+ * @param   wParam      Message param.
+ * @param   lParam      Message param.
+ * @param   fUnicode    Unicode indicator.
+ */
 ULONG OSLibSendMessage(HWND hwnd, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
 {
-    POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
-  
-    if(NULL == packet)
-    {
-        dprintf(("user32::oslibmsg::OSLibSendMessage - allocated packet structure is NULL"));
-    
-        // PH: we cannot provide a correct returncode :(
-        DebugInt3();    
-        return 0;
-    }
-  
-    packet->wParam   = wParam;
-    packet->lParam   = lParam;
-
-    return (ULONG)WinSendMsg(hwnd, WIN32APP_POSTMSG+msg, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
-}
+    ULONG           rc;                 /* return code on packing failure */
+    void *          pvMsgPacket;        /* packed message (shared memory) */
+
+    /*
+     * Call message packer.
+     */
+    pvMsgPacket = OSLibPackMessage(NULLHANDLE, hwnd, msg, wParam, lParam, fUnicode, &rc);
+    if (!pvMsgPacket)
+    {
+        dprintf(("user32::oslibmsg::OSLibSendMessage - Failed to pack message !!"));
+        DebugInt3();
+        return rc;
+    }
+
+    return (ULONG)WinSendMsg(hwnd, WIN32APP_POSTMSG+msg, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), pvMsgPacket);
+}
+
 //******************************************************************************
 //******************************************************************************
 ULONG OSLibWinBroadcastMsg(ULONG msg, ULONG wParam, ULONG lParam, BOOL fSend)
 {
+    #ifdef DEBUG
+    if (msg == WINWM_COPYDATA)
+    {
+        dprintf(("user32::oslibmsg::OSLibWinBroadcastMsg - WM_COPYDATA will not work outside this process !!!"));
+        DebugInt3();
+    }
+    #endif
     return WinBroadcastMsg(HWND_DESKTOP, WIN32APP_POSTMSG+msg, (MPARAM)wParam, (MPARAM)lParam,
                            (fSend) ? BMSG_SEND : BMSG_POST);
 }
-//******************************************************************************
-//******************************************************************************
+
+
+/**
+ * Post a message.
+ *
+ * @returns Success indicator.
+ *
+ * @param   hwndWin32   Odin window handle.
+ * @param   hwndOS2     OS/2 window handle
+ * @param   msg         Odin message id.
+ * @param   wParam      Message param.
+ * @param   lParam      Message param.
+ * @param   fUnicode    Unicode indicator.
+ */
 BOOL OSLibPostMessage(HWND hwndWin32, HWND hwndOS2, ULONG msg, ULONG wParam, ULONG lParam, BOOL fUnicode)
 {
-    POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
-    BOOL ret;
-
-    if (NULL == packet)
-    {
-        dprintf(("user32::oslibmsg::OSLibPostMessage - allocated packet structure is NULL"));
-    
-        // PH: we can provide a correct returncode
-        DebugInt3();    
+    void *          pvMsgPacket;        /* packed message (shared memory) */
+
+    /*
+     * Call message packer.
+     */
+    pvMsgPacket = OSLibPackMessage(hwndWin32, hwndOS2, msg, wParam, lParam, fUnicode, NULL);
+    if (!pvMsgPacket)
+    {
+        dprintf(("user32::oslibmsg::OSLibPostMessage - Failed to pack message !!"));
+        DebugInt3();
         return FALSE;
     }
+
+    /*
+     * Post the message.
+     * Signal the receiver for if it's doing MsgWaitForMultipleObjects() at the time.
+     */
     TEB *teb = GetTEBFromThreadId(GetWindowThreadProcessId(hwndWin32, NULL));
-
-    packet->wParam   = wParam;
-    packet->lParam   = lParam;
-    ret = WinPostMsg(hwndOS2, WIN32APP_POSTMSG+msg, (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), (MPARAM)packet);
-
-    if(teb && (teb->o.odin.dwWakeMask & QS_POSTMESSAGE_W)) {
+    BOOL ret = WinPostMsg(hwndOS2,
+                          WIN32APP_POSTMSG+msg,
+                          (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA),
+                          pvMsgPacket);
+    if (teb && (teb->o.odin.dwWakeMask & QS_POSTMESSAGE_W))
+    {
         //thread is blocked in MsgWaitForMultipleObjects waiting for
         //posted messages
@@ -697,14 +844,14 @@
     POSTMSG_PACKET *packet = (POSTMSG_PACKET *)_smalloc(sizeof(POSTMSG_PACKET));
     BOOL ret;
-  
-    if(NULL == packet)
+
+    if (NULL == packet)
     {
         dprintf(("user32::oslibmsg::OSLibPostMessage - allocated packet structure is NULL"));
 
-        DebugInt3();    
+        DebugInt3();
         // PH: we can provide a correct returncode
         return FALSE;
     }
-    
+
     if(teb == NULL) {
         dprintf(("OSLibPostThreadMessage: thread %x not found!", threadid));
@@ -715,6 +862,6 @@
     packet->lParam   = lParam;
 
-    ret = WinPostQueueMsg((HMQ)teb->o.odin.hmq, WIN32APP_POSTMSG+msg, 
-                          (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA), 
+    ret = WinPostQueueMsg((HMQ)teb->o.odin.hmq, WIN32APP_POSTMSG+msg,
+                          (MPARAM)((fUnicode) ? WIN32MSG_MAGICW : WIN32MSG_MAGICA),
                           (MPARAM)packet);
 
Index: trunk/src/user32/oslibmsg.h
===================================================================
--- trunk/src/user32/oslibmsg.h	(revision 10010)
+++ trunk/src/user32/oslibmsg.h	(revision 10012)
@@ -1,3 +1,3 @@
-/* $Id: oslibmsg.h,v 1.19 2003-01-03 16:35:54 sandervl Exp $ */
+/* $Id: oslibmsg.h,v 1.20 2003-04-11 14:22:05 sandervl Exp $ */
 /*
  * Window message translation functions for OS/2
@@ -14,10 +14,18 @@
 
 
+typedef struct tagCOPYDATASTRUCT_W
+{
+    DWORD   dwData;
+    DWORD   cbData;
+    LPVOID  lpData;
+} COPYDATASTRUCT_W, *PCOPYDATASTRUCT_W, *LPCOPYDATASTRUCT_W;
+
+
 #ifdef __cplusplus
 
 ULONG TranslateWinMsg(ULONG msg);
 
-#define MSG_NOREMOVE	0
-#define MSG_REMOVE	1
+#define MSG_NOREMOVE    0
+#define MSG_REMOVE      1
 
 #ifdef OS2DEF_INCLUDED
@@ -27,7 +35,7 @@
 #endif
 
-BOOL  OSLibWinGetMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, 
+BOOL  OSLibWinGetMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin,
                      UINT uMsgFilterMax, BOOL isUnicode = FALSE);
-BOOL  OSLibWinPeekMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin, 
+BOOL  OSLibWinPeekMsg(LPMSG pMsg, HWND hwnd, UINT uMsgFilterMin,
                       UINT uMsgFilterMax, DWORD fRemove, BOOL isUnicode = FALSE);
 void  OSLibWinPostQuitMessage(ULONG nExitCode);
Index: trunk/src/user32/oslibmsgtranslate.cpp
===================================================================
--- trunk/src/user32/oslibmsgtranslate.cpp	(revision 10010)
+++ trunk/src/user32/oslibmsgtranslate.cpp	(revision 10012)
@@ -1,3 +1,3 @@
-/* $Id: oslibmsgtranslate.cpp,v 1.107 2003-03-28 11:49:01 sandervl Exp $ */
+/* $Id: oslibmsgtranslate.cpp,v 1.108 2003-04-11 14:22:06 sandervl Exp $ */
 /*
  * Window message translation functions for OS/2
@@ -52,7 +52,7 @@
 //PF Correction is different for different mouse drivers. For now no correction
 //is ok because lots of Odin controls rely on minimum delta. However in future
-//we will possibly detect mouse driver and use correction if speed will be 
+//we will possibly detect mouse driver and use correction if speed will be
 //too high or too low.
- 
+
 //******************************************************************************
 //******************************************************************************
@@ -90,5 +90,5 @@
            ret = pmScan;
   }
- 
+
   KeyTranslatePMScanToWinVKey(ret, FALSE, (PBYTE)&winKey, NULL, NULL);
   return winKey;
@@ -127,4 +127,40 @@
 }
 //******************************************************************************
+
+
+/**
+ * Inter process/thread packet cleanup.
+ * See OSLibPackMessage() for details on the packing.
+ *
+ * @param   pTeb        Pointer to the thread environment block for the current thread.
+ * @param   pPacket     Pointer to the packet in question.
+ * @param   pWinMsg     Pointer to the window message corresponding to the packet.
+ */
+inline void OSLibCleanupPacket(TEB *pTeb, POSTMSG_PACKET *pPacket, MSG *pWinMsg)
+{
+    switch (pWinMsg->message)
+    {
+        /*
+         * Place this in the TEB freeing any previous WM_COPYDATA packet.
+         * Note! Nested WM_COPYDATA isn't working.
+         */
+        case WINWM_COPYDATA:
+        {
+            dprintf(("OSLibCleanupPacket: WM_COPYDATA: old %#p  new %#p", pTeb->o.odin.pWM_COPYDATA, pPacket));
+            if (pTeb->o.odin.pWM_COPYDATA)
+                _sfree(pTeb->o.odin.pWM_COPYDATA);
+            pTeb->o.odin.pWM_COPYDATA = pPacket;
+            break;
+        }
+
+        /*
+         * Default packing - free the shared memory here.
+         */
+        default:
+            _sfree(pPacket);
+            break;
+    }
+}
+
 //******************************************************************************
 BOOL OS2ToWinMsgTranslate(void *pTeb, QMSG *os2Msg, MSG *winMsg, BOOL isUnicode, BOOL fMsgRemoved)
@@ -167,5 +203,6 @@
             winMsg->wParam  = packet->wParam;
             winMsg->lParam  = packet->lParam;
-            if(fMsgRemoved == MSG_REMOVE) free(packet); //free the shared memory here
+            if (fMsgRemoved == MSG_REMOVE)
+                OSLibCleanupPacket(teb, packet, winMsg);
             if(win32wnd) RELEASE_WNDOBJ(win32wnd);
             return TRUE;
@@ -407,8 +444,8 @@
             (winMsg->message == WINWM_NCMBUTTONDOWN))
         {
-            if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message && 
+            if(fGenerateDoubleClick && doubleClickMsg.message == winMsg->message &&
                winMsg->time - doubleClickMsg.time < GetDoubleClickTime() &&
                (abs(winMsg->pt.x - doubleClickMsg.pt.x) < GetSystemMetrics(SM_CXDOUBLECLK_W)/2) &&
-               (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2)) 
+               (abs(winMsg->pt.y - doubleClickMsg.pt.y) < GetSystemMetrics(SM_CYDOUBLECLK_W)/2))
             {
                  dprintf(("single -> double click"));
@@ -440,5 +477,5 @@
             }
             else msg = winMsg->message;
-            
+
             if(msg == WINWM_LBUTTONDBLCLK) {
                 msg = WINWM_LBUTTONDOWN;
@@ -589,5 +626,5 @@
             //FALSE -> keyboard operation = user pressed Alt-F4 -> close app
             //TRUE  -> user clicked on close button -> close window
-            if(SHORT2FROMMP(os2Msg->mp2) == FALSE) 
+            if(SHORT2FROMMP(os2Msg->mp2) == FALSE)
             {
                 HWND hwnd = win32wnd->GetTopParent();
@@ -655,5 +692,5 @@
       // NO BREAK! FALLTHRU CASE!
     }
-      
+
     case WM_CHAR_SPECIAL:
     {
@@ -665,5 +702,5 @@
       // NO BREAK! FALLTHRU CASE!
     }
-      
+
     case WM_CHAR:
     {
@@ -674,5 +711,5 @@
       ULONG  flags = SHORT1FROMMP(os2Msg->mp1);
       BOOL   keyWasPressed;
-      BOOL   numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);       
+      BOOL   numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
       char   c;
       USHORT usPMScanCode = CHAR4FROMMP(os2Msg->mp1);
@@ -693,5 +730,5 @@
 
         KeyTranslatePMScanToWinVKey(usPMScanCode,
-                                    FALSE, 
+                                    FALSE,
                                     &bWinVKey,
                                     &wWinScan,
@@ -700,10 +737,10 @@
         winMsg->lParam  = repeatCount & 0x0FFFF;                 // bit 0-15, repeatcount
         winMsg->lParam |= (wWinScan & 0x1FF) << 16;  // bit 16-23, scancode + bit 15 extended
-      
+
         // Set the extended bit when appropriate
         if (fWinExtended)
             winMsg->lParam = winMsg->lParam | WIN_KEY_EXTENDED;
 
-	//PF When we press shift we enable non-numeric functions of Numpad
+        //PF When we press shift we enable non-numeric functions of Numpad
         if ((!numPressed || (flags & KC_SHIFT)) && (scanCode >= PMSCAN_PAD7) && (scanCode <= PMSCAN_PADPERIOD))
              winMsg->wParam = ConvertNumPadKey(scanCode);
@@ -728,5 +765,5 @@
             winMsg->lParam = 0x01460001;
         }
-      
+
         if (!(flags & KC_ALT))
         {
@@ -745,5 +782,5 @@
               // held ALT-key when current key is released
               // generates additional flag 0x2000000
-              // Note: PM seems to do this differently, 
+              // Note: PM seems to do this differently,
               // KC_ALT is already reset
             }
@@ -756,5 +793,5 @@
             winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP
           }
-          else 
+          else
           { // send WM_KEYDOWN message
             winMsg->message = WINWM_KEYDOWN;
@@ -762,10 +799,10 @@
             if (keyWasPressed)
               winMsg->lParam |= WIN_KEY_PREVSTATE;                  // bit 30, previous state, 1 means key was pressed
-             
+
             //Shift-Enter and possibly others need to have special handling
             if (flags & KC_SHIFT)
             {
                 if(fMsgRemoved && !(teb->o.odin.fTranslated))
-                {                    
+                {
                   dprintf(("PM: KC_SHIFT: %x",winMsg->wParam));
                   if (winMsg->wParam == VK_RETURN_W)
@@ -773,5 +810,5 @@
                     MSG extramsg;
                     memcpy(&extramsg, winMsg, sizeof(MSG));
-    
+
                     //After SetFocus(0), all keystrokes are converted in WM_SYS*
                     extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
@@ -791,5 +828,5 @@
                     MSG extramsg;
                     memcpy(&extramsg, winMsg, sizeof(MSG));
-    
+
                     //After SetFocus(0), all keystrokes are converted in WM_SYS*
                     extramsg.message = (fIgnoreKeystrokes) ? WINWM_SYSCHAR : WINWM_CHAR;
@@ -802,11 +839,11 @@
           // if right alt is down, then we need to set the alt down bit too
           // except for the fake Ctrl WM_CHAR sent for AltGr emulation
-          if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL && 
-              (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000)) 
+          if (os2Msg->msg != WM_CHAR_SPECIAL_ALTGRCONTROL &&
+              (WinGetKeyState(HWND_DESKTOP, VK_ALTGRAF) & 0x8000))
           {
-              winMsg->lParam |= WIN_KEY_ALTHELD;            
+              winMsg->lParam |= WIN_KEY_ALTHELD;
           }
         }
-        else 
+        else
         {
           //
@@ -817,10 +854,10 @@
              //@@PF Note that without pmkbdhook there will not be correct message for Alt-Enter
               winMsg->message = WINWM_SYSKEYUP;
-              winMsg->lParam |= WIN_KEY_PREVSTATE;            
+              winMsg->lParam |= WIN_KEY_PREVSTATE;
               // No ALTHELD for Alt itself ;)
-              winMsg->lParam |= WIN_KEY_ALTHELD;            
-	      winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP 
+              winMsg->lParam |= WIN_KEY_ALTHELD;
+              winMsg->lParam |= 1 << 31;                              // bit 31, transition state, always 1 for WM_KEYUP
           }
-          else 
+          else
           {
             // send WM_SYSKEYDOWN message
@@ -838,17 +875,17 @@
         // AltGr needs special handling
         //
-        // AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU) 
+        // AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
         //          WM_SYSKEYUP (VK_CONTROL)
         //          WM_KEYUP (VK_MENU)
         //
-        // Ctrl+AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYUP (VK_CONTROL) 
-        //               WM_KEYDOWN (VK_MENU) 
+        // Ctrl+AltGr -> WM_KEYDOWN (VK_CONTROL), WM_KEYUP (VK_CONTROL)
+        //               WM_KEYDOWN (VK_MENU)
         //               WM_KEYUP (VK_MENU)
-        //               WM_KEYUP (VK_CONTROL) 
+        //               WM_KEYUP (VK_CONTROL)
         //
-        // AltGr+Ctrl -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU) 
-        //               WM_KEYDOWN (VK_CONTROL) 
-        //               WM_SYSKEYUP (VK_CONTROL) 
-        //               WM_SYSKEYUP (VK_CONTROL) 
+        // AltGr+Ctrl -> WM_KEYDOWN (VK_CONTROL), WM_KEYDOWN (VK_MENU)
+        //               WM_KEYDOWN (VK_CONTROL)
+        //               WM_SYSKEYUP (VK_CONTROL)
+        //               WM_SYSKEYUP (VK_CONTROL)
         //               WM_KEYUP (VK_MENU)
         //
@@ -861,10 +898,10 @@
         //               endif
         //               Send WM_KEYDOWN (VK_MENU)
-        // 
-        if(winMsg->wParam == VK_MENU_W && (winMsg->lParam & WIN_KEY_EXTENDED)) 
+        //
+        if(winMsg->wParam == VK_MENU_W && (winMsg->lParam & WIN_KEY_EXTENDED))
         {//AltGr
-            if(GetKeyState(VK_CONTROL_W) & 0x8000) 
+            if(GetKeyState(VK_CONTROL_W) & 0x8000)
             {//Ctrl key pressed, send WM_KEYUP
-            
+
             }
         }
@@ -876,5 +913,5 @@
                 winMsg->message = WINWM_SYSKEYDOWN;
             }
-            else 
+            else
             if(winMsg->message == WINWM_KEYUP) {
                 winMsg->message = WINWM_SYSKEYUP;
@@ -971,41 +1008,41 @@
         if (os2Msg->msg == WM_VSCROLL)
         {
-	    POINT CursorPoint;
+            POINT CursorPoint;
             winMsg->message = WINWM_MOUSEWHEEL;
             if (OSLibWinQueryPointerPos(&CursorPoint))
                mapScreenPoint((OSLIBPOINT*)&CursorPoint);
- 
+
             if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
-                winMsg->wParam  = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);  
+                winMsg->wParam  = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
             else
             if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
-                winMsg->wParam  = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);  
+                winMsg->wParam  = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
             else
-                winMsg->wParam  = MAKELONG(GetMouseKeyState(), 0);  
-
-            winMsg->lParam  = MAKELONG(CursorPoint.x, CursorPoint.y); 
-
-            dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));  
+                winMsg->wParam  = MAKELONG(GetMouseKeyState(), 0);
+
+            winMsg->lParam  = MAKELONG(CursorPoint.x, CursorPoint.y);
+
+            dprintf(("WM_MOUSEWHEEL message delta %d at (%d,%d)",HIWORD(winMsg->wParam),CursorPoint.x, CursorPoint.y));
             if (fMsgRemoved == MSG_REMOVE)
             {
-	            MSLLHOOKSTRUCT hook;
-
-	            hook.pt.x       = os2Msg->ptl.x & 0xFFFF;
-	            hook.pt.y       = mapScreenY(os2Msg->ptl.y);
-	            if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
-	                hook.mouseData   = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);  
-	            else
-	            if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
-	                hook.mouseData   = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);  
-	            else goto dummymessage; // IBM driver produces other messages as well sometimes
-
-	            hook.flags       = LLMHF_INJECTED;
-	            hook.time        = winMsg->time;
-	            hook.dwExtraInfo = 0;
-	            if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
-	                goto dummymessage; //hook swallowed message
-	   }
+                    MSLLHOOKSTRUCT hook;
+
+                    hook.pt.x       = os2Msg->ptl.x & 0xFFFF;
+                    hook.pt.y       = mapScreenY(os2Msg->ptl.y);
+                    if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEDOWN)
+                        hook.mouseData   = MAKELONG(GetMouseKeyState(), -WHEEL_DELTA/OS2_WHEEL_CORRECTION);
+                    else
+                    if (SHORT2FROMMP(os2Msg->mp2) == SB_LINEUP)
+                        hook.mouseData   = MAKELONG(GetMouseKeyState(), WHEEL_DELTA/OS2_WHEEL_CORRECTION);
+                    else goto dummymessage; // IBM driver produces other messages as well sometimes
+
+                    hook.flags       = LLMHF_INJECTED;
+                    hook.time        = winMsg->time;
+                    hook.dwExtraInfo = 0;
+                    if(HOOK_CallHooksW( WH_MOUSE_LL, HC_ACTION, WINWM_MOUSEWHEEL, (LPARAM)&hook))
+                        goto dummymessage; //hook swallowed message
+           }
            break;
-        } 
+        }
         goto dummymessage; //eat this message
         break;
@@ -1054,5 +1091,5 @@
   TEB *teb;
   MSG extramsg;
-  BOOL   numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);       
+  BOOL   numPressed = (BOOL)(WinGetKeyState(HWND_DESKTOP,VK_NUMLOCK) & 1);
   teb = GetThreadTEB();
   if(!teb)
@@ -1061,10 +1098,10 @@
   UCHAR ucPMScanCode = CHAR4FROMMP(teb->o.odin.os2msg.mp1);
   ULONG fl = SHORT1FROMMP(teb->o.odin.os2msg.mp1);
-    
-  
+
+
     //NOTE: These actually need to be posted so that the next message retrieved by GetMessage contains
     //      the newly generated WM_CHAR message.
     if(!teb->o.odin.fTranslated &&
-       teb->o.odin.os2msg.msg == WM_CHAR && 
+       teb->o.odin.os2msg.msg == WM_CHAR &&
        !((SHORT1FROMMP(teb->o.odin.os2msg.mp1) & KC_KEYUP) == KC_KEYUP))
     {
@@ -1083,5 +1120,5 @@
         break;
       }
-      
+
       // PF With NumLock off do not generate any WM_CHAR messages at all
       // PADMINUS,PADPLUS fall in range of PAD7..PADPERIOD but they should generate WM_CHAR
@@ -1089,7 +1126,7 @@
       if (!numPressed && (ucPMScanCode != PMSCAN_PADMINUS) && (ucPMScanCode != PMSCAN_PADPLUS) &&
          (ucPMScanCode >= PMSCAN_PAD7) && (ucPMScanCode <= PMSCAN_PADPERIOD))
-        return FALSE; 
-
-      if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN) 
+        return FALSE;
+
+      if(!(fl & KC_CHAR) && msg->message < WINWM_SYSKEYDOWN)
       {
         return FALSE;
@@ -1103,5 +1140,5 @@
         if(msg->wParam)
         {
-          if ((msg->wParam >= VK_NUMPAD0_W) && 
+          if ((msg->wParam >= VK_NUMPAD0_W) &&
               (msg->wParam <= VK_NUMPAD9_W))
             extramsg.wParam = msg->wParam - 0x30;
@@ -1114,5 +1151,5 @@
                 extramsg.wParam = msg->wParam;
         }
-        else    
+        else
           extramsg.wParam = SHORT2FROMMP(teb->o.odin.os2msg.mp2);
       }
@@ -1120,7 +1157,7 @@
 
       //After SetFocus(0), all keystrokes are converted in WM_SYS*
-      if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes) 
+      if(msg->message >= WINWM_SYSKEYDOWN || fIgnoreKeystrokes)
         extramsg.message = WINWM_SYSCHAR;
-      else    
+      else
         extramsg.message = WINWM_CHAR;
 
