Index: windows/clipboard.c
===================================================================
RCS file: /home/wine/wine/windows/clipboard.c,v
retrieving revision 1.18
diff -u -u -r1.18 clipboard.c
--- windows/clipboard.c	1999/10/24 20:22:24	1.18
+++ windows/clipboard.c	1999/11/01 18:08:56
@@ -24,6 +24,7 @@
 #include <unistd.h>
 #include <string.h>
 #include "winuser.h"
+#include "winproc.h"
 #include "wine/winuser16.h"
 #include "wine/winbase16.h"
 #include "heap.h"
@@ -54,6 +55,8 @@
 
 static WORD LastRegFormat = CF_REGFORMATBASE;
 
+static TIMERPROC globalFreeProc = 0;  /* Really a pointer to a WINDOWPROC */
+    
 /* Clipboard cache initial data.
  * WARNING: This data ordering is dependendent on the WINE_CLIPFORMAT structure
  * declared in clipboard.h
@@ -171,15 +174,39 @@
  */
 VOID CALLBACK CLIPBOARD_GlobalFreeProc( HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime )
 {
-    /* idEvent is the HGLOBAL to be deleted */
-    GlobalFree( (HGLOBAL)idEvent );
+    HANDLE16 hGlobal16 = (HGLOBAL16)idEvent;
+    HANDLE * pGlobalData = (HANDLE *)GlobalLock16( hGlobal16 );
+    int nElements = GlobalSize16(hGlobal16) / sizeof(HANDLE);
+    int i;
+
+    /* Free the list of HGLOBAL's */
+    for (i = 0; i < nElements; i++)
+    {
+        if (pGlobalData[i])
+            GlobalFree( pGlobalData[i] );
+    }
+    
+    GlobalUnlock16( hGlobal16 );
+    GlobalFree16( hGlobal16 );
 }
 
 /**************************************************************************
  *			CLIPBOARD_DeleteRecord
  */
+
 void CLIPBOARD_DeleteRecord(LPWINE_CLIPFORMAT lpFormat, BOOL bChange)
 {
+    HANDLE16 hGlobal16 = 0;
+    HANDLE * pGlobalData = 0;
+
+    /* We must allocate a WINDOWPROC handle to allow DispatchMessage to correctly
+     * call our globalFreeProc as a 32 bit WndProc, while running either in a 16
+     * or 32 bit context.
+     */
+    if ( !globalFreeProc )
+        globalFreeProc = (TIMERPROC)WINPROC_AllocWinProc( (WNDPROC16)CLIPBOARD_GlobalFreeProc,
+                                                          WIN_PROC_32A, WIN_PROC_TIMER );
+    
     if( (lpFormat->wFormatID >= CF_GDIOBJFIRST &&
 	 lpFormat->wFormatID <= CF_GDIOBJLAST) || lpFormat->wFormatID == CF_BITMAP 
 	    || lpFormat->wFormatID == CF_PALETTE)
@@ -194,17 +221,22 @@
       if (lpFormat->hData32)
       {
         DeleteMetaFile( ((METAFILEPICT *)GlobalLock( lpFormat->hData32 ))->hMF );
+        GlobalUnlock(lpFormat->hData32);
+
+        /* Release lpFormat->hData32 in the context of the process which created it.
+         * See CLIPBOARD_GlobalFreeProc for more details about this technique.
+         * GlobalFree(lpFormat->hDataSrc32);
+         */
+
+        /* hGlobal16 contains an array of HGLOBAL's to be free'd */
+        hGlobal16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(HANDLE) * 2);
+        pGlobalData = (HANDLE *)GlobalLock16(hGlobal16);
+        pGlobalData[0] = lpFormat->hData32;
+        pGlobalData[1] = lpFormat->hDataSrc32;
+        GlobalUnlock16(hGlobal16);
+        
         PostMessageA(hWndClipOwner, WM_TIMER,
-                     (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
-        if (lpFormat->hDataSrc32)
-        {
-          /* Release lpFormat->hData32 in the context of the process which created it.
-           * See CLIPBOARD_GlobalFreeProc for more details about this technique.
-           * GlobalFree(lpFormat->hDataSrc32);
-           */
-          PostMessageA(hWndClipOwner, WM_TIMER,
-                       (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
-        }
+                     (WPARAM)hGlobal16, (LPARAM)globalFreeProc);
           
 	if (lpFormat->hData16)
 	  /* HMETAFILE16 and HMETAFILE32 are apparently the same thing, 
@@ -223,22 +255,20 @@
     {
       if (lpFormat->hData32)
       {
+        /* hGlobal16 contains an array of HGLOBAL's to be free'd */
+        hGlobal16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(HANDLE) * 2);
+        pGlobalData = (HANDLE *)GlobalLock16(hGlobal16);
+        pGlobalData[0] = lpFormat->hData32;
+        pGlobalData[1] = lpFormat->hDataSrc32;
+        GlobalUnlock16(hGlobal16);
+        
         /* Release lpFormat->hData32 in the context of the process which created it.
          * See CLIPBOARD_GlobalFreeProc for more details about this technique.
          * GlobalFree( lpFormat->hData32 );
          */
         PostMessageA(hWndClipOwner, WM_TIMER,
-                     (WPARAM)lpFormat->hData32, (LPARAM)CLIPBOARD_GlobalFreeProc);
+                     (WPARAM)hGlobal16, (LPARAM)globalFreeProc);
       }
-      if (lpFormat->hDataSrc32)
-      {
-        /* Release lpFormat->hData32 in the context of the process which created it.
-         * See CLIPBOARD_GlobalFreeProc for more details about this technique.
-         * GlobalFree(lpFormat->hDataSrc32);
-         */
-        PostMessageA(hWndClipOwner, WM_TIMER,
-                     (WPARAM)lpFormat->hDataSrc32, (LPARAM)CLIPBOARD_GlobalFreeProc);
-      }
       if (lpFormat->hData16)
 	GlobalFree16(lpFormat->hData16);
     }
@@ -432,7 +462,7 @@
  * FIXME: Should be a pair of driver functions that convert between OEM text and Windows.
  *
  */
-static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat )
+static LPWINE_CLIPFORMAT CLIPBOARD_RenderText( UINT wFormat, BOOL b16Bit )
 {
     LPWINE_CLIPFORMAT lpSource = ClipFormats; 
     LPWINE_CLIPFORMAT lpTarget;
@@ -487,10 +517,18 @@
         if( !lpstrS ) return NULL;
         TRACE("\tconverting from '%s' to '%s', %i chars\n",
                                           lpSource->Name, lpTarget->Name, size);
-    
-        lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
-        lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
-    
+
+        if (b16Bit)
+        {
+            lpTarget->hData16 = GlobalAlloc16(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
+            lpstrT = (LPSTR)GlobalLock16(lpTarget->hData16);
+        }
+        else
+        {
+            lpTarget->hData32 = GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, size);
+            lpstrT = (LPSTR)GlobalLock(lpTarget->hData32);
+        }
+        
         if( lpstrT )
         {
             if( lpSource->wFormatID == CF_TEXT )
@@ -498,10 +536,15 @@
             else
                 OemToCharBuffA(lpstrS, lpstrT, size);
             TRACE("\tgot %s\n", lpstrT);
-            GlobalUnlock(lpTarget->hData32);
+
+            /* Unlock target */
+            if (b16Bit)
+                GlobalUnlock16(lpTarget->hData16);
+            else
+                GlobalUnlock(lpTarget->hData32);
         }
         else
-            lpTarget->hData32 = 0;
+            lpTarget->hData16 = lpTarget->hData32 = 0;
 
         /* Unlock source */
         if (lpSource->hData32)
@@ -781,7 +824,7 @@
 
     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
     {
-	lpRender = CLIPBOARD_RenderText(wFormat);
+	lpRender = CLIPBOARD_RenderText(wFormat, TRUE);
         if ( !lpRender ) return 0;
     }
     else
@@ -848,7 +891,7 @@
 
     if( wFormat == CF_TEXT || wFormat == CF_OEMTEXT )
     {
-	lpRender = CLIPBOARD_RenderText(wFormat);
+	lpRender = CLIPBOARD_RenderText(wFormat, FALSE);
         if ( !lpRender ) return 0;
     }
     else
