Index: trunk/src/comdlg32/initcomdlg32.cpp
===================================================================
--- trunk/src/comdlg32/initcomdlg32.cpp	(revision 21307)
+++ trunk/src/comdlg32/initcomdlg32.cpp	(revision 21308)
@@ -54,120 +54,6 @@
    switch (fdwReason)
    {
-    case DLL_PROCESS_ATTACH:
-    {
-        /*
-         * Find default printer and write name to win.ini
-         * Format: queuename,driver,portname
-         */
-        char szWinDefPrn[256];
-        szWinDefPrn[0] = '\0';
-
-        /*
-         * OS/2 stores the default printer as a combination of printerdevice and queue.
-         *
-         *   Printer Device is related to one port. It may have multiple printer
-         *       drivers because the port may serve multiple queues with different drivers.
-         *   The Ports are related to multiple queues.
-         *
-         * So we take the default default printer+queue combination and finds the
-         */
-        char szDefPrnDev[20];
-        char szDefPrnQue[20];
-        if (PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "PRINTER", "",
-                                  szDefPrnDev, sizeof(szDefPrnDev)) > 1
-            &&  PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "QUEUE", "",
-                                      szDefPrnQue, sizeof(szDefPrnQue)) > 1
-            &&  szDefPrnDev[0]
-            &&  szDefPrnQue[0]
-           )
-        {
-            char *psz;
-            /* remove everything beyond the first ';' */
-            if ((psz = strchr(szDefPrnDev, ';')) != NULL)
-                *psz = '\0';
-            if ((psz = strchr(szDefPrnQue, ';')) != NULL)
-                *psz = '\0';
-
-            /*
-             * Now we must lookup the port name from the device settings.
-             *  This is a string of this form:
-             *      <port>;<driver1>[,<driver2>;<queue1>[,<queue2>];?;?;
-             */
-            ULONG   cb = 0;
-            if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev, &cb)
-                &&  cb > 0)
-            {
-                char *pszBufD = (char*)malloc(cb + 1);
-                if (pszBufD
-                    &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev,
-                                              NULL, pszBufD, cb + 1)
-                    > 1
-                   )
-                {
-                    /*
-                     * Now get the Default printer driver for the queue.
-                     *  This is stored as a ';' separated list of drivers, the first one is the default.
-                     */
-                    if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue, &cb)
-                        &&  cb > 0)
-                    {
-                        char *pszBufQ = (char*)malloc(cb + 1);
-                        if (pszBufQ
-                            &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue,
-                                                      NULL, pszBufQ, cb + 1)
-                            > 1
-                           )
-                        {
-                            /*
-                             * We got everything now. just find the parts we need.
-                             *  First printer driver from QUEUE_DD
-                             *  Port name of the device.
-                             */
-                            if ((psz = strchr(pszBufQ, ';')) != NULL)
-                                *psz = '\0';
-                            if ((psz = strchr(pszBufQ, ',')) != NULL) //paranoia! in case comman separated list of some kind.
-                                *psz = '\0';
-                            if ((psz = strchr(pszBufD, ';')) != NULL)
-                                *psz = '\0';
-                            if ((psz = strchr(pszBufD, ',')) != NULL) //paranoia in case comman separated list of some kind.
-                                *psz = '\0';
-
-                            /*
-                             * Now make default printer string for the win.ini.
-                             */
-                            strcpy(szWinDefPrn, szDefPrnQue);
-                            strcat(strcat(szWinDefPrn, ","), pszBufQ);
-                            strcat(strcat(szWinDefPrn, ","), pszBufD);
-                            dprintf(("LibMainComdlg32: Successfully found default printer.'%s'", szWinDefPrn));
-                            free(pszBufQ);
-                        }
-                    }
-                    else
-                    {
-                        /* OS/2 the device may exist though the default queue is destroyed.
-                         * it may still exist even if there are no queues on the system at all!
-                         */
-                        dprintf(("LibMainComdlg32: no queue driver entry for '%s'.", szDefPrnQue));
-                    }
-
-                    free(pszBufD);
-                }
-            }
-            else
-            {
-                /* OS/2 doesn't remove the default settings if the default queue/printer is deleted. */
-                dprintf(("LibMainComdlg32: can't find device settings for '%s'.", szDefPrnDev));
-            }
-        }
-        else
-        {
-            dprintf(("LibMainComdlg32: no default printer? szDefPrnDev='%s' szDefPrnQue='%s'.", szDefPrnDev, szDefPrnQue));
-        }
-
-        //Now get real printer name the one that will be used in DC calls
-        WriteProfileStringA("windows", "device", szWinDefPrn);
-
-        return COMDLG32_DllEntryPoint(hinstDLL, fdwReason, fImpLoad);
-    }
+   case DLL_PROCESS_ATTACH:
+       return COMDLG32_DllEntryPoint(hinstDLL, fdwReason, fImpLoad);
 
    case DLL_THREAD_ATTACH:
Index: trunk/src/kernel32/initkernel32.cpp
===================================================================
--- trunk/src/kernel32/initkernel32.cpp	(revision 21307)
+++ trunk/src/kernel32/initkernel32.cpp	(revision 21308)
@@ -60,4 +60,5 @@
 #include <stats.h>
 #include <heapshared.h>
+#include <heapstring.h>
 #include <_ras.h>
 
@@ -71,4 +72,6 @@
  extern DWORD kernel32_PEResTab;
 }
+
+extern PFN pfnImSetMsgQueueProperty;
 
        ULONG   flAllocMem = 0;    /* flag to optimize DosAllocMem to use all the memory on SMP machines */
@@ -79,4 +82,6 @@
        BOOL    fInit     = FALSE;
        BOOL    fWin32k   = FALSE;
+       HMODULE imHandle = 0;
+       char    szModName[ 256 ] = "";
 
 /****************************************************************************/
@@ -224,4 +229,7 @@
             CODEPAGE_Init();
 
+            if( IsDBCSEnv() && DosLoadModule( szModName, sizeof( szModName ), "OS2IM.DLL", &imHandle ) == 0 )
+                DosQueryProcAddr( imHandle, 140, NULL, &pfnImSetMsgQueueProperty );
+
             InitSystemInfo(ulSysinfo);
             //Set up environment as found in NT
@@ -272,4 +280,7 @@
     dprintf(("kernel32 exit %d\n", ulReason));
 
+    if( IsDBCSEnv() && imHandle )
+        DosFreeModule( imHandle );
+
     //Flush and delete all open memory mapped files
     Win32MemMap::deleteAll();
Index: trunk/src/kernel32/oslibmisc.cpp
===================================================================
--- trunk/src/kernel32/oslibmisc.cpp	(revision 21307)
+++ trunk/src/kernel32/oslibmisc.cpp	(revision 21308)
@@ -28,4 +28,8 @@
 #include "dbglocal.h"
 
+typedef APIRET ( APIENTRY *PFN_IMSETMSGQUEUEPROPERTY )( HMQ, ULONG );
+
+PFN_IMSETMSGQUEUEPROPERTY pfnImSetMsgQueueProperty = NULL;
+
 //******************************************************************************
 //TODO: not reentrant!
@@ -351,3 +355,19 @@
 //******************************************************************************
 //******************************************************************************
-
+ULONG OSLibImSetMsgQueueProperty( ULONG hmq, ULONG ulFlag )
+{
+    USHORT sel;
+    APIRET rc;
+
+    if( !pfnImSetMsgQueueProperty )
+        return 1;
+
+    sel = RestoreOS2FS();
+    rc = pfnImSetMsgQueueProperty( hmq, ulFlag );
+    SetFS( sel );
+
+    return rc;
+}
+//******************************************************************************
+//******************************************************************************
+
Index: trunk/src/kernel32/oslibmisc.h
===================================================================
--- trunk/src/kernel32/oslibmisc.h	(revision 21307)
+++ trunk/src/kernel32/oslibmisc.h	(revision 21308)
@@ -103,4 +103,6 @@
 void OSLibQueryBeginLibpath(char *lpszBeginlibpath, int size);
 
+ULONG OSLibImSetMsgQueueProperty( ULONG hmq, ULONG ulFlag );
+
 #ifdef __cplusplus
 }
Index: trunk/src/kernel32/thread.cpp
===================================================================
--- trunk/src/kernel32/thread.cpp	(revision 21307)
+++ trunk/src/kernel32/thread.cpp	(revision 21308)
@@ -34,4 +34,5 @@
 #include <handlemanager.h>
 #include <codepage.h>
+#include <heapstring.h>
 
 #include "hmhandle.h"
@@ -48,4 +49,6 @@
 
 static ULONG priorityclass = NORMAL_PRIORITY_CLASS;
+
+#define MQP_INSTANCE_PERMQ              0x00000001 // from os2im.h
 
 //******************************************************************************
@@ -689,4 +692,8 @@
     dprintf(("Win32ThreadProc: hab %x hmq %x", winteb->o.odin.hab, winteb->o.odin.hmq));
     dprintf(("Stack top 0x%x, stack end 0x%x", winteb->stack_top, winteb->stack_low));
+
+    if( IsDBCSEnv())
+        /* IM instace is created per message queue, that is, thread */
+        OSLibImSetMsgQueueProperty( winteb->o.odin.hmq, MQP_INSTANCE_PERMQ );
 
     //Note: The Win32 exception structure referenced by FS:[0] is the same
Index: trunk/src/kernel32/windllbase.cpp
===================================================================
--- trunk/src/kernel32/windllbase.cpp	(revision 21307)
+++ trunk/src/kernel32/windllbase.cpp	(revision 21308)
@@ -708,4 +708,10 @@
         PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "CRTDLL32", "CRTDLL");
     }
+    if(PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "IMM32", "", renameddll,
+                                sizeof(renameddll)-1) <= 1)
+    {
+        PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "IMM32", "IMM32OS2");
+        PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "IMM32OS2", "IMM32");
+    }
 }
 //******************************************************************************
Index: trunk/src/oleaut32/stubs.cpp
===================================================================
--- trunk/src/oleaut32/stubs.cpp	(revision 21307)
+++ trunk/src/oleaut32/stubs.cpp	(revision 21308)
@@ -173,4 +173,12 @@
 //*****************************************************************************
 //*****************************************************************************
+HRESULT WIN32API VarDecFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, DECIMAL *pdecOut)
+{
+    dprintf(("OLEAUT32: VarDecFromStr - stub"));
+    return S_OK;
+}
+
+//*****************************************************************************
+//*****************************************************************************
 HRESULT WIN32API VarDecFromDisp(IDispatch *pdispIn, LCID lcid, DECIMAL *pdecOut)
 {
@@ -256,4 +264,12 @@
 {
     dprintf(("OLEAUT32: VarCyFromDec - stub"));
+    return S_OK;
+}
+
+//*****************************************************************************
+//*****************************************************************************
+HRESULT WIN32API VarBstrFromDec(DECIMAL *pdecIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
+{
+    dprintf(("OLEAUT32: VarBstrFromDec - stub"));
     return S_OK;
 }
Index: trunk/src/oleaut32/variant.c
===================================================================
--- trunk/src/oleaut32/variant.c	(revision 21307)
+++ trunk/src/oleaut32/variant.c	(revision 21308)
@@ -201,211 +201,4 @@
     {0x00    ,   0,  0          , VT_NULL}
 };
-
-
-/************** Form wine: oleaut32/variant.h **************/
-
-/* Value of sign for a positive decimal number */
-#define DECIMAL_POS 0
-
-/* Native headers don't change the union ordering for DECIMAL sign/scale (duh).
- * This means that the signscale member is only useful for setting both members to 0.
- * SIGNSCALE creates endian-correct values so that we can properly set both at once
- * to values other than 0.
- */
-#ifdef WORDS_BIGENDIAN
-#define SIGNSCALE(sign,scale) (((scale) << 8) | sign)
-#else
-#define SIGNSCALE(sign,scale) (((sign) << 8) | scale)
-#endif
-/* Macros for getting at a DECIMAL's parts */
-#define DEC_SIGN(d)      ((d)->u.s.sign)
-#define DEC_SCALE(d)     ((d)->u.s.scale)
-#define DEC_SIGNSCALE(d) ((d)->u.signscale)
-#define DEC_HI32(d)      ((d)->Hi32)
-#define DEC_MID32(d)     ((d)->u1.s1.Mid32)
-#define DEC_LO32(d)      ((d)->u1.s1.Lo32)
-#define DEC_LO64(d)      ((d)->u1.Lo64)
-
-/* DECIMAL */
-#define _VarDecFromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_DECIMAL)
-/* R8 (double) */
-#define _VarR8FromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_R8)
-
-/* Internal flags for low level conversion functions */
-#define  VAR_BOOLONOFF 0x0400 /* Convert bool to "On"/"Off" */
-#define  VAR_BOOLYESNO 0x0800 /* Convert bool to "Yes"/"No" */
-#define  VAR_NEGATIVE  0x1000 /* Number is negative */
-
-/* The localised characters that make up a valid number */
-typedef struct tagVARIANT_NUMBER_CHARS
-{
-  WCHAR cNegativeSymbol;
-  WCHAR cPositiveSymbol;
-  WCHAR cDecimalPoint;
-  WCHAR cDigitSeperator;
-  WCHAR cCurrencyLocal;
-  WCHAR cCurrencyLocal2;
-  WCHAR cCurrencyDecimalPoint;
-  WCHAR cCurrencyDigitSeperator;
-} VARIANT_NUMBER_CHARS;
-
-void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS*,LCID,DWORD);
-/********** End of Form wine: oleaut32/variant.h ************/
-
-/* Write a number from a UI8 and sign */
-#ifdef __WIN32OS2__
-static WCHAR *VARIANT_WriteNumber(ULONG ulVal, WCHAR* szOut)
-{
-  //FIXME("%s: Hack! No real ULONG64 support here, using ULONG instead. ulVal=%x!!\n", __FUNCTION__, ulVal);
-#else 
-static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
-  {
-#endif
-
-  do
-  {
-    WCHAR ulNextDigit = ulVal % 10;
-
-    *szOut-- = '0' + ulNextDigit;
-    ulVal = (ulVal - ulNextDigit) / 10;
-  } while (ulVal);
-
-  szOut++;
-  return szOut;
-}
-
-/* Create a (possibly localised) BSTR from a UI8 and sign */
-static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
-{
-  WCHAR szConverted[256];
-
-  if (dwFlags & VAR_NEGATIVE)
-    *--szOut = '-';
-
-  if (dwFlags & LOCALE_USE_NLS)
-  {
-    /* Format the number for the locale */
-    szConverted[0] = '\0';
-    GetNumberFormatW(lcid,
-                     dwFlags & LOCALE_NOUSEROVERRIDE,
-                     szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
-    szOut = szConverted;
-  }
-  return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
-}
-
-
-/******************************************************************************
- * VarBstrFromDec (OLEAUT32.232)
- *
- * Convert a VT_DECIMAL to a VT_BSTR.
- *
- * PARAMS
- *  pDecIn   [I] Source
- *  lcid     [I] LCID for the conversion
- *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
- *  pbstrOut [O] Destination
- *
- * RETURNS
- *  Success: S_OK.
- *  Failure: E_INVALIDARG, if pbstrOut is invalid.
- *           E_OUTOFMEMORY, if memory allocation fails.
- */
-HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
-{
-  TRACE("%s: entering function. pDecIn->lo32: %x, pDecIn->Mid32: %x, pDecIn->Hi32: %x, sign: %x, dwFlags: %x\n",
-        __FUNCTION__, DEC_LO32(pDecIn), DEC_MID32(pDecIn), DEC_HI32(pDecIn), DEC_SIGN(pDecIn), dwFlags);
-  if (!pbstrOut)
-    return E_INVALIDARG;
-
-  if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
-  {
-    WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
-
-    /* Create the basic number string */
-    *szOut-- = '\0';
-
-
-#ifdef __WIN32OS2__
-    szOut = VARIANT_WriteNumber(DEC_LO32(pDecIn), szOut);
-#else
-    szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
-#endif
-    if (DEC_SIGN(pDecIn))
-      dwFlags |= VAR_NEGATIVE;
-
-    *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
-    TRACE("%s: returning %s\n", __FUNCTION__, debugstr_w(*pbstrOut));
-    return *pbstrOut ? S_OK : E_OUTOFMEMORY;
-  }
-  FIXME("semi-stub\n");
-  return E_INVALIDARG;
-}
-
-
-/* Copy data from one variant to another. */
-static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
-{
-  //  TRACE("%s: entering function.\n", __FUNCTION__);
-  switch (vt)
-  {
-  case VT_I1:
-  case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
-  case VT_BOOL:
-  case VT_I2:
-  case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
-  case VT_R4:
-  case VT_INT:
-  case VT_I4:
-  case VT_UINT:
-  case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
-  case VT_R8:
-  case VT_DATE:
-  case VT_CY:
-  case VT_I8:
-#ifdef __WIN32OS2__
-    /*  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break; */
-    /*  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break; */
-  case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
-#else
-  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break;
-  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
-  case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
-#endif
-  default:
-    FIXME("%s: VT_ type %d unhandled, please report!\n", __FUNCTION__,  vt);
-  }
-}
-
-/* Form wine: oleaut32/vartype.c */
-/* Coerce VT_BSTR to a numeric type */
-HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
-                               void* pOut, VARTYPE vt)
-{
-  VARIANTARG dstVar;
-  HRESULT hRet;
-  NUMPARSE np;
-  BYTE rgb[1024];
-
-  TRACE("%s: (StrIn: %s, LCID: 0x%08lx, ulFlags: 0x%08lx )\n", __FUNCTION__, pStrIn, lcid, ulFlags );
-
-  /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
-  np.cDig = sizeof(rgb) / sizeof(BYTE);
-  np.dwInFlags = NUMPRS_STD;
-
-  hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
-
-  if (SUCCEEDED(hRet))
-  {
-    /* 1 << vt gives us the VTBIT constant for the destination number type */
-    hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
-    if (SUCCEEDED(hRet)) {
-      VARIANT_CopyData(&dstVar, vt, pOut);
-      TRACE("%s: Returning dstVar-> type : %x", __FUNCTION__, V_VT(&dstVar));
-    }
-  }
-  return hRet;
-}
-
 
 /******************************************************************************
@@ -2039,5 +1832,5 @@
 void WINAPI VariantInit(VARIANTARG* pvarg)
 {
-  TRACE("%s: (%p)\n", __FUNCTION__, pvarg);
+  TRACE("(%p)\n",pvarg);
 
   memset(pvarg, 0, sizeof (VARIANTARG));
@@ -2058,5 +1851,5 @@
 {
   HRESULT res = S_OK;
-  TRACE("%s: (%p)\n",__FUNCTION__, pvarg);
+  TRACE("(%p)\n",pvarg);
 
   res = ValidateVariantType( V_VT(pvarg) );
@@ -2118,5 +1911,5 @@
   HRESULT res = S_OK;
 
-  TRACE("%s: (Dest: %p, Src: %p), vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, V_VT(pvargSrc));
+  TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
 
   res = ValidateVariantType( V_VT(pvargSrc) );
@@ -2339,5 +2132,6 @@
 	VARIANTARG varg;
 	VariantInit( &varg );
-	TRACE("%s: (Dest: %p, source: %p, LCID: %ld, wFlags: %u, VARTYPE: %u) vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
+
+	TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
     TRACE("Src Var:\n");
     dump_Variant(pvargSrc);
@@ -2376,5 +2170,4 @@
 			 */
 			VARIANTARG Variant;
-
 			VariantInit( &Variant );
 			res = VariantCopyInd( &Variant, pvargSrc );
@@ -2386,4 +2179,5 @@
 				VariantClear( &Variant );
 			}
+
 		}
 		else
@@ -2403,5 +2197,5 @@
 		V_VT(pvargDest) = vt;
 
-    TRACE("Dest Var (re: %x)\n", res);
+    TRACE("Dest Var:\n");
     dump_Variant(pvargDest);
 
@@ -2981,5 +2775,5 @@
 	LPSTR pNewString = NULL;
 
-	TRACE("%s: ( strIn: %p -> %s, lcid: 0x%08lx, dwFlags: 0x%08lx, plOut: %p ), stub\n", __FUNCTION__, strIn, debugstr_w(strIn), lcid, dwFlags, plOut );
+	TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
 
 	/* Check if we have a valid argument
@@ -3305,5 +3099,4 @@
 }
 
-#if 0
 /******************************************************************************
  *		VarR8FromStr		[OLEAUT32.84]
@@ -3336,26 +3129,4 @@
 
 	return S_OK;
-}
-#endif
-
-/************************************************************************
- * VarR8FromStr (OLEAUT32.84)
- *
- * Convert a VT_BSTR to a VT_R8.
- *
- * PARAMS
- *  strIn   [I] Source
- *  lcid    [I] LCID for the conversion
- *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
- *  pDblOut [O] Destination
- *
- * RETURNS
- *  Success: S_OK.
- *  Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
- *           DISP_E_TYPEMISMATCH, if the type cannot be converted
- */
-HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
-{
-  return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
 }
 
@@ -3562,6 +3333,4 @@
    return S_OK;
 }
-
-
 
 /******************************************************************************
@@ -4716,453 +4485,4 @@
 
 
-#define GET_NUMBER_TEXT(fld,name) \
-  buff[0] = 0; \
-  if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
-    WARN("%s: buffer too small for " #fld "\n", __FUNCTION__); \
-  else \
-    if (buff[0]) lpChars->name = buff[0]; /* \
-  TRACE("lcid 0x%lx, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)*/
-
-/* Get the valid number characters for an lcid */
-void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
-{
-  static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
-  LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
-  WCHAR buff[4];
-
-  memcpy(lpChars, &defaultChars, sizeof(defaultChars));
-  GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
-  GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
-  GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
-  GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeperator);
-  GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
-  GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeperator);
-
-  /* Local currency symbols are often 2 characters */
-  lpChars->cCurrencyLocal2 = '\0';
-  switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
-  {
-    case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
-    case 2: lpChars->cCurrencyLocal  = buff[0];
-            break;
-    default: WARN("buffer too small for LOCALE_SCURRENCY\n");
-  }
-  TRACE("lcid 0x%lx, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
-        lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
-}
-
-/* Number Parsing States */
-#define B_PROCESSING_EXPONENT 0x1
-#define B_NEGATIVE_EXPONENT   0x2
-#define B_EXPONENT_START      0x4
-#define B_INEXACT_ZEROS       0x8
-#define B_LEADING_ZERO        0x10
-#define B_PROCESSING_HEX      0x20
-#define B_PROCESSING_OCT      0x40
-/**********************************************************************
- *              VarParseNumFromStr [OLEAUT32.46]
- *
- * Parse a string containing a number into a NUMPARSE structure.
- *
- * PARAMS
- *  lpszStr [I]   String to parse number from
- *  lcid    [I]   Locale Id for the conversion
- *  dwFlags [I]   0, or LOCALE_NOUSEROVERRIDE to use system default number chars
- *  pNumprs [I/O] Destination for parsed number
- *  rgbDig  [O]   Destination for digits read in
- *
- * RETURNS
- *  Success: S_OK. pNumprs and rgbDig contain the parsed representation of
- *           the number.
- *  Failure: E_INVALIDARG, if any parameter is invalid.
- *           DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
- *           incorrectly.
- *           DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
- *
- * NOTES
- *  pNumprs must have the following fields set:
- *   cDig: Set to the size of rgbDig.
- *   dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
- *            from "oleauto.h".
- *
- * FIXME
- *  - I am unsure if this function should parse non-arabic (e.g. Thai)
- *   numerals, so this has not been implemented.
- */
-HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
-                                  NUMPARSE *pNumprs, BYTE *rgbDig)
-{
-  VARIANT_NUMBER_CHARS chars;
-  BYTE rgbTmp[1024];
-  DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
-  int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
-  int cchUsed = 0;
-
-  TRACE("%s: (%s, %ld, dwFlags: 0x%08lx,%p,%p, NUMPARSE->dwInFlags: %x)\n", __FUNCTION__, debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig, pNumprs->dwInFlags);
-
-  if (!pNumprs || !rgbDig)
-    return E_INVALIDARG;
-
-  if (pNumprs->cDig < iMaxDigits)
-    iMaxDigits = pNumprs->cDig;
-
-  pNumprs->cDig = 0;
-  pNumprs->dwOutFlags = 0;
-  pNumprs->cchUsed = 0;
-  pNumprs->nBaseShift = 0;
-  pNumprs->nPwr10 = 0;
-
-  if (!lpszStr)
-    return DISP_E_TYPEMISMATCH;
-
-  VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
-
-  /* First consume all the leading symbols and space from the string */
-  while (1)
-  {
-    if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
-      do
-      {
-        cchUsed++;
-        lpszStr++;
-      } while (isspaceW(*lpszStr));
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
-             *lpszStr == chars.cPositiveSymbol &&
-             !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
-      cchUsed++;
-      lpszStr++;
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
-             *lpszStr == chars.cNegativeSymbol &&
-             !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
-    {
-      pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
-      cchUsed++;
-      lpszStr++;
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
-             !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
-             *lpszStr == chars.cCurrencyLocal &&
-             (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
-      cchUsed++;
-      lpszStr++;
-      /* Only accept currency characters */
-      chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
-      chars.cDigitSeperator = chars.cCurrencyDigitSeperator;
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
-             !(pNumprs->dwOutFlags & NUMPRS_PARENS))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_PARENS;
-      cchUsed++;
-      lpszStr++;
-    }
-    else
-      break;
-  } /* End of while */
-
-  if(pNumprs->dwOutFlags & (1<<VT_LPWSTR))
-    {
- TRACE("  I'm here");     
-    }
-  if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
-  {
-    /* Only accept non-currency characters */
-    chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
-    chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
-  }
-
-  if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
-    pNumprs->dwInFlags & NUMPRS_HEX_OCT)
-  {
-      dwState |= B_PROCESSING_HEX;
-      pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
-      cchUsed=cchUsed+2;
-      lpszStr=lpszStr+2;
-  }
-  else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
-    pNumprs->dwInFlags & NUMPRS_HEX_OCT)
-  {
-      dwState |= B_PROCESSING_OCT;
-      pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
-      cchUsed=cchUsed+2;
-      lpszStr=lpszStr+2;
-  }
-
-  /* Strip Leading zeros */
-  while (*lpszStr == '0')
-  {
-    dwState |= B_LEADING_ZERO;
-    cchUsed++;
-    lpszStr++;
-  }
-
-  while (*lpszStr)
-  {
-    if (isdigitW(*lpszStr))
-    {
-      if (dwState & B_PROCESSING_EXPONENT)
-      {
-        int exponentSize = 0;
-        if (dwState & B_EXPONENT_START)
-        {
-          while (*lpszStr == '0')
-          {
-            /* Skip leading zero's in the exponent */
-            cchUsed++;
-            lpszStr++;
-          }
-          if (!isdigitW(*lpszStr))
-            break; /* No exponent digits - invalid */
-        }
-
-        while (isdigitW(*lpszStr))
-        {
-          exponentSize *= 10;
-          exponentSize += *lpszStr - '0';
-          cchUsed++;
-          lpszStr++;
-        }
-        if (dwState & B_NEGATIVE_EXPONENT)
-          exponentSize = -exponentSize;
-        /* Add the exponent into the powers of 10 */
-        pNumprs->nPwr10 += exponentSize;
-        dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
-        lpszStr--; /* back up to allow processing of next char */
-      }
-      else
-      {
-        if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
-          && !(dwState & B_PROCESSING_OCT))
-        {
-          pNumprs->dwOutFlags |= NUMPRS_INEXACT;
-
-          if (*lpszStr != '0')
-            dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
-
-          /* This digit can't be represented, but count it in nPwr10 */
-          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
-            pNumprs->nPwr10--;
-          else
-            pNumprs->nPwr10++;
-        }
-        else
-        {
-          if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
-            return DISP_E_TYPEMISMATCH;
-          }
-
-          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
-            pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
-
-          rgbTmp[pNumprs->cDig] = *lpszStr - '0';
-        }
-        pNumprs->cDig++;
-        cchUsed++;
-      }
-    }
-    else if (*lpszStr == chars.cDigitSeperator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
-    {
-      pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
-      cchUsed++;
-    }
-    else if (*lpszStr == chars.cDecimalPoint &&
-             pNumprs->dwInFlags & NUMPRS_DECIMAL &&
-             !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
-      cchUsed++;
-
-      /* Remove trailing zeros from the whole number part */
-      while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
-      {
-        pNumprs->nPwr10++;
-        pNumprs->cDig--;
-      }
-
-      /* If we have no digits so far, skip leading zeros */
-      if (!pNumprs->cDig)
-      {
-        while (lpszStr[1] == '0')
-        {
-          dwState |= B_LEADING_ZERO;
-          cchUsed++;
-          lpszStr++;
-        }
-      }
-    }
-    else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
-             pNumprs->dwInFlags & NUMPRS_EXPONENT &&
-             !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
-    {
-      dwState |= B_PROCESSING_EXPONENT;
-      pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
-      cchUsed++;
-    }
-    else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
-    {
-      cchUsed++; /* Ignore positive exponent */
-    }
-    else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
-    {
-      dwState |= B_NEGATIVE_EXPONENT;
-      cchUsed++;
-    }
-    else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
-             (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
-             dwState & B_PROCESSING_HEX)
-    {
-      if (pNumprs->cDig >= iMaxDigits)
-      {
-        return DISP_E_OVERFLOW;
-      }
-      else
-      {
-        if (*lpszStr >= 'a')
-          rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
-        else
-          rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
-      }
-      pNumprs->cDig++;
-      cchUsed++;
-    }
-    else
-      break; /* Stop at an unrecognised character */
-
-    lpszStr++;
-  }
-
-  if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
-  {
-    /* Ensure a 0 on its own gets stored */
-    pNumprs->cDig = 1;
-    rgbTmp[0] = 0;
-  }
-
-  if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
-  {
-    pNumprs->cchUsed = cchUsed;
-    return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
-  }
-
-  if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
-  {
-    if (dwState & B_INEXACT_ZEROS)
-      pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
-  } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
-  {
-    /* copy all of the digits into the output digit buffer */
-    /* this is exactly what windows does although it also returns */
-    /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
-    memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
-
-    if (dwState & B_PROCESSING_HEX) {
-      /* hex numbers have always the same format */
-      pNumprs->nPwr10=0;
-      pNumprs->nBaseShift=4;
-    } else {
-      if (dwState & B_PROCESSING_OCT) {
-        /* oct numbers have always the same format */
-        pNumprs->nPwr10=0;
-        pNumprs->nBaseShift=3;
-      } else {
-        while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
-        {
-          if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
-            pNumprs->nPwr10--;
-          else
-            pNumprs->nPwr10++;
-
-          pNumprs->cDig--;
-        }
-      }
-    }
-  } else
-  {
-    /* Remove trailing zeros from the last (whole number or decimal) part */
-    while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
-    {
-      if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
-        pNumprs->nPwr10--;
-      else
-        pNumprs->nPwr10++;
-
-      pNumprs->cDig--;
-    }
-  }
-
-  if (pNumprs->cDig <= iMaxDigits)
-    pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
-  else
-    pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
-
-  /* Copy the digits we processed into rgbDig */
-  memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
-
-  /* Consume any trailing symbols and space */
-  while (1)
-  {
-    if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
-    {
-      pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
-      do
-      {
-        cchUsed++;
-        lpszStr++;
-      } while (isspaceW(*lpszStr));
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
-             !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
-             *lpszStr == chars.cPositiveSymbol)
-    {
-      pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
-      cchUsed++;
-      lpszStr++;
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
-             !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
-             *lpszStr == chars.cNegativeSymbol)
-    {
-      pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
-      cchUsed++;
-      lpszStr++;
-    }
-    else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
-             pNumprs->dwOutFlags & NUMPRS_PARENS)
-    {
-      cchUsed++;
-      lpszStr++;
-      pNumprs->dwOutFlags |= NUMPRS_NEG;
-    }
-    else
-      break;
-  }
-
-  if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
-  {
-    pNumprs->cchUsed = cchUsed;
-    return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
-  }
-
-  if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
-    return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
-
-  if (!pNumprs->cDig)
-    return DISP_E_TYPEMISMATCH; /* No Number found */
-
-  pNumprs->cchUsed = cchUsed;
-  TRACE("%s: Returning, NUMPARS->cchUsed: %x, NUMPARS->cDig: %x, pNumprs->dwOutFlags: %x, NUMPARS->nBaseShift: %x,, NUMPARS->nPwr10: %x\n",
-        __FUNCTION__, cchUsed, pNumprs->cDig, pNumprs->dwOutFlags, pNumprs->nBaseShift, pNumprs->nPwr10);
-  return S_OK;
-}
-
-#if 0
 /**********************************************************************
  *              VarParseNumFromStr [OLEAUT32.46]
@@ -5204,50 +4524,23 @@
     return S_OK;
 }
-#endif
 
 
 /**********************************************************************
  *              VarNumFromParseNum [OLEAUT32.47]
- *
- * Convert a NUMPARSE structure into a numeric Variant type.
- *
- * PARAMS
- *  pNumprs  [I] Source for parsed number. cDig must be set to the size of rgbDig
- *  rgbDig   [I] Source for the numbers digits
- *  dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
- *  pVarDst  [O] Destination for the converted Variant value.
- *
- * RETURNS
- *  Success: S_OK. pVarDst contains the converted value.
- *  Failure: E_INVALIDARG, if any parameter is invalid.
- *           DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
- *
- * NOTES
- *  - The smallest favoured type present in dwVtBits that can represent the
- *    number in pNumprs without losing precision is used.
- *  - Signed types are preferrred over unsigned types of the same size.
- *  - Preferred types in order are: integer, float, double, currency then decimal.
- *  - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
- *    for details of the rounding method.
- *  - pVarDst is not cleared before the result is stored in it.
  */
 HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
                                   ULONG dwVtBits, VARIANT * pvar)
 {
-#ifdef __WIN32OS2__
     DWORD xint;
     int i;
-
-    TRACE("%s: NUMPARSE->cDig: %x, NUMPARSE->nBaseShift: %x, NUMPARSE->dwOutFlags: %x dwVtBits=%lx. rgbDig: \n",
-          __FUNCTION__, pnumprs->cDig, pnumprs->nBaseShift, pnumprs->dwOutFlags, dwVtBits);
+    FIXME("(..,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
 
     xint = 0;
     for (i=0;i<pnumprs->cDig;i++)
-      xint = xint*10 + rgbDig[i];
+	xint = xint*10 + rgbDig[i];
 
     if (pnumprs->dwOutFlags & NUMPRS_NEG) {
         xint = xint * -1;
     }
-    TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint);
 
     VariantInit(pvar);
@@ -5281,580 +4574,8 @@
     }
 
-    if (dwVtBits & VTBIT_DECIMAL)
-      {
-        int i;
-        ULONG carry;
-        /*    ULONG64 tmp; */
-        ULONG tmp;
-        DECIMAL* pDec = &V_DECIMAL(pvar);
-        
-        V_VT(pvar) = VT_DECIMAL;
-        
-        DECIMAL_SETZERO(pDec);
-        DEC_LO32(pDec) = 0;
-        
-        if (pnumprs->dwOutFlags & NUMPRS_NEG)
-          DEC_SIGN(pDec) = DECIMAL_NEG;
-        else
-          DEC_SIGN(pDec) = DECIMAL_POS;
-
-        /* Factor the significant digits */
-        for (i = 0; i < pnumprs->cDig; i++)
-          {
-            if(0xffffffff /10 - 9 < DEC_LO32(pDec) ) {
-              /* Overflow expected. This code only support 32Bit numbers for now */
-              FIXME("%s: Converted number will be  > 32bit! Only partial implementation. Returning DISP_E_OVERFLOW.", __FUNCTION__);
-              DEC_LO32(pDec) =  UI4_MAX;
-              return DISP_E_OVERFLOW;
-            }
-
-            tmp = DEC_LO32(pDec) * 10 + rgbDig[i];
-
-            /* No support for numbers > 32 bit for now. */           
-            DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
-            DEC_MID32(pDec) = (ULONG)0;
-            DEC_HI32(pDec) = (ULONG)0;
-
-            /* The following is not working because of missing ULONG64 !! */
-#if 0
-            carry = (ULONG)(tmp >> 32);
-            DEC_LO64(pDec)=tmp;
-            DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
-            tmp = (ULONG)DEC_MID32(pDec) * 10 + carry;
-            carry = (ULONG)(tmp >> 32);
-            DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
-            tmp = (ULONG)DEC_HI32(pDec) * 10 + carry;
-            DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
-#endif
-
-            if (tmp >> 32 & UI4_MAX)
-              {
-              VarNumFromParseNum_DecOverflow:
-                TRACE("Overflow\n");
-                DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
-                return DISP_E_OVERFLOW;
-              }
-          }
-        
-        TRACE("Done... LO32: %x, MID32: %x, HI32: %x, DEC_LO64: %x, SignScale: %x, sign: %x\n",
-              DEC_LO32(pDec), DEC_MID32(pDec), DEC_HI32(pDec), DEC_LO64(pDec), DEC_SIGNSCALE(pDec), DEC_SIGN(pDec) );
-        
-        return S_OK;
-      }
-    
-    FIXME("%s: (..,dwVtBits=%lx,....), partial stub!\n", __FUNCTION__, dwVtBits);
 	FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint);
 	return E_FAIL;
-} /* End of __WIN32OS2__ */
-
-#else
-
-  /* Scale factors and limits for double arithmetic */
-  static const double dblMultipliers[11] = {
-    1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
-    1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
-  };
-  static const double dblMinimums[11] = {
-    R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
-    R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
-    R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
-  };
-  static const double dblMaximums[11] = {
-    R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
-    R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
-    R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
-  };
-
-  int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
-
-  TRACE("(%p,%p,0x%lx,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
-
-  if (pNumprs->nBaseShift)
-  {
-    /* nBaseShift indicates a hex or octal number */
-    ULONG64 ul64 = 0;
-    LONG64 l64;
-    int i;
-
-    /* Convert the hex or octal number string into a UI64 */
-    for (i = 0; i < pNumprs->cDig; i++)
-    {
-      if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
-      {
-        TRACE("Overflow multiplying digits\n");
-        return DISP_E_OVERFLOW;
-      }
-      ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
-    }
-
-    /* also make a negative representation */
-    l64=-ul64;
-
-    /* Try signed and unsigned types in size order */
-    if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
-    {
-      V_VT(pVarDst) = VT_I1;
-      if (ul64 <= I1_MAX)
-          V_I1(pVarDst) = ul64;
-      else
-          V_I1(pVarDst) = l64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
-    {
-      V_VT(pVarDst) = VT_UI1;
-      V_UI1(pVarDst) = ul64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
-    {
-      V_VT(pVarDst) = VT_I2;
-      if (ul64 <= I2_MAX)
-          V_I2(pVarDst) = ul64;
-      else
-          V_I2(pVarDst) = l64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
-    {
-      V_VT(pVarDst) = VT_UI2;
-      V_UI2(pVarDst) = ul64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
-    {
-      V_VT(pVarDst) = VT_I4;
-      if (ul64 <= I4_MAX)
-          V_I4(pVarDst) = ul64;
-      else
-          V_I4(pVarDst) = l64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
-    {
-      V_VT(pVarDst) = VT_UI4;
-      V_UI4(pVarDst) = ul64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
-    {
-      V_VT(pVarDst) = VT_I8;
-      V_I8(pVarDst) = ul64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_UI8)
-    {
-      V_VT(pVarDst) = VT_UI8;
-      V_UI8(pVarDst) = ul64;
-      return S_OK;
-    }
-    else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
-    {
-      V_VT(pVarDst) = VT_DECIMAL;
-      DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
-      DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
-      DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
-    {
-      V_VT(pVarDst) = VT_R4;
-      if (ul64 <= I4_MAX)
-          V_R4(pVarDst) = ul64;
-      else
-          V_R4(pVarDst) = l64;
-      return S_OK;
-    }
-    else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
-    {
-      V_VT(pVarDst) = VT_R8;
-      if (ul64 <= I4_MAX)
-          V_R8(pVarDst) = ul64;
-      else
-          V_R8(pVarDst) = l64;
-      return S_OK;
-    }
-    TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
-    return DISP_E_OVERFLOW;
-  }
-
-  /* Count the number of relevant fractional and whole digits stored,
-   * And compute the divisor/multiplier to scale the number by.
-   */
-  if (pNumprs->nPwr10 < 0)
-  {
-    if (-pNumprs->nPwr10 >= pNumprs->cDig)
-    {
-      /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
-      wholeNumberDigits = 0;
-      fractionalDigits = pNumprs->cDig;
-      divisor10 = -pNumprs->nPwr10;
-    }
-    else
-    {
-      /* An exactly represented real number e.g. 1.024 */
-      wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
-      fractionalDigits = pNumprs->cDig - wholeNumberDigits;
-      divisor10 = pNumprs->cDig - wholeNumberDigits;
-    }
-  }
-  else if (pNumprs->nPwr10 == 0)
-  {
-    /* An exactly represented whole number e.g. 1024 */
-    wholeNumberDigits = pNumprs->cDig;
-    fractionalDigits = 0;
-  }
-  else /* pNumprs->nPwr10 > 0 */
-  {
-    /* A whole number followed by nPwr10 0's e.g. 102400 */
-    wholeNumberDigits = pNumprs->cDig;
-    fractionalDigits = 0;
-    multiplier10 = pNumprs->nPwr10;
-  }
-
-  TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", pNumprs->cDig,
-        pNumprs->nPwr10, wholeNumberDigits, fractionalDigits);
-  TRACE("mult %d; div %d\n", multiplier10, divisor10);
-
-  if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
-      (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
-  {
-    /* We have one or more integer output choices, and either:
-     *  1) An integer input value, or
-     *  2) A real number input value but no floating output choices.
-     * Alternately, we have a DECIMAL output available and an integer input.
-     *
-     * So, place the integer value into pVarDst, using the smallest type
-     * possible and preferring signed over unsigned types.
-     */
-    BOOL bOverflow = FALSE, bNegative;
-    ULONG64 ul64 = 0;
-    int i;
-
-    /* Convert the integer part of the number into a UI8 */
-    for (i = 0; i < wholeNumberDigits; i++)
-    {
-      if (ul64 > (UI8_MAX / 10 - rgbDig[i]))
-      {
-        TRACE("Overflow multiplying digits\n");
-        bOverflow = TRUE;
-        break;
-      }
-      ul64 = ul64 * 10 + rgbDig[i];
-    }
-
-    /* Account for the scale of the number */
-    if (!bOverflow && multiplier10)
-    {
-      for (i = 0; i < multiplier10; i++)
-      {
-        if (ul64 > (UI8_MAX / 10))
-        {
-          TRACE("Overflow scaling number\n");
-          bOverflow = TRUE;
-          break;
-        }
-        ul64 = ul64 * 10;
-      }
-    }
-
-    /* If we have any fractional digits, round the value.
-     * Note we don't have to do this if divisor10 is < 1,
-     * because this means the fractional part must be < 0.5
-     */
-    if (!bOverflow && fractionalDigits && divisor10 > 0)
-    {
-      const BYTE* fracDig = rgbDig + wholeNumberDigits;
-      BOOL bAdjust = FALSE;
-
-      TRACE("first decimal value is %d\n", *fracDig);
-
-      if (*fracDig > 5)
-        bAdjust = TRUE; /* > 0.5 */
-      else if (*fracDig == 5)
-      {
-        for (i = 1; i < fractionalDigits; i++)
-        {
-          if (fracDig[i])
-          {
-            bAdjust = TRUE; /* > 0.5 */
-            break;
-          }
-        }
-        /* If exactly 0.5, round only odd values */
-        if (i == fractionalDigits && (ul64 & 1))
-          bAdjust = TRUE;
-      }
-
-      if (bAdjust)
-      {
-        if (ul64 == UI8_MAX)
-        {
-          TRACE("Overflow after rounding\n");
-          bOverflow = TRUE;
-        }
-        ul64++;
-      }
-    }
-
-    /* Zero is not a negative number */
-    bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE;
-
-    TRACE("Integer value is %lld, bNeg %d\n", ul64, bNegative);
-
-    /* For negative integers, try the signed types in size order */
-    if (!bOverflow && bNegative)
-    {
-      if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
-      {
-        if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
-        {
-          V_VT(pVarDst) = VT_I1;
-          V_I1(pVarDst) = -ul64;
-          return S_OK;
-        }
-        else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
-        {
-          V_VT(pVarDst) = VT_I2;
-          V_I2(pVarDst) = -ul64;
-          return S_OK;
-        }
-        else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
-        {
-          V_VT(pVarDst) = VT_I4;
-          V_I4(pVarDst) = -ul64;
-          return S_OK;
-        }
-        else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
-        {
-          V_VT(pVarDst) = VT_I8;
-          V_I8(pVarDst) = -ul64;
-          return S_OK;
-        }
-        else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
-        {
-          /* Decimal is only output choice left - fast path */
-          V_VT(pVarDst) = VT_DECIMAL;
-          DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
-          DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
-          DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
-          return S_OK;
-        }
-      }
-    }
-    else if (!bOverflow)
-    {
-      /* For positive integers, try signed then unsigned types in size order */
-      if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
-      {
-        V_VT(pVarDst) = VT_I1;
-        V_I1(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
-      {
-        V_VT(pVarDst) = VT_UI1;
-        V_UI1(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
-      {
-        V_VT(pVarDst) = VT_I2;
-        V_I2(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
-      {
-        V_VT(pVarDst) = VT_UI2;
-        V_UI2(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
-      {
-        V_VT(pVarDst) = VT_I4;
-        V_I4(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
-      {
-        V_VT(pVarDst) = VT_UI4;
-        V_UI4(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
-      {
-        V_VT(pVarDst) = VT_I8;
-        V_I8(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if (dwVtBits & VTBIT_UI8)
-      {
-        V_VT(pVarDst) = VT_UI8;
-        V_UI8(pVarDst) = ul64;
-        return S_OK;
-      }
-      else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
-      {
-        /* Decimal is only output choice left - fast path */
-        V_VT(pVarDst) = VT_DECIMAL;
-        DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
-        DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
-        DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
-        return S_OK;
-      }
-    }
-  }
-
-  if (dwVtBits & REAL_VTBITS)
-  {
-    /* Try to put the number into a float or real */
-    BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
-    double whole = 0.0;
-    int i;
-
-    /* Convert the number into a double */
-    for (i = 0; i < pNumprs->cDig; i++)
-      whole = whole * 10.0 + rgbDig[i];
-
-    TRACE("Whole double value is %16.16g\n", whole);
-
-    /* Account for the scale */
-    while (multiplier10 > 10)
-    {
-      if (whole > dblMaximums[10])
-      {
-        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
-        bOverflow = TRUE;
-        break;
-      }
-      whole = whole * dblMultipliers[10];
-      multiplier10 -= 10;
-    }
-    if (multiplier10)
-    {
-      if (whole > dblMaximums[multiplier10])
-      {
-        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
-        bOverflow = TRUE;
-      }
-      else
-        whole = whole * dblMultipliers[multiplier10];
-    }
-
-    TRACE("Scaled double value is %16.16g\n", whole);
-
-    while (divisor10 > 10)
-    {
-      if (whole < dblMinimums[10])
-      {
-        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
-        bOverflow = TRUE;
-        break;
-      }
-      whole = whole / dblMultipliers[10];
-      divisor10 -= 10;
-    }
-    if (divisor10)
-    {
-      if (whole < dblMinimums[divisor10])
-      {
-        dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
-        bOverflow = TRUE;
-      }
-      else
-        whole = whole / dblMultipliers[divisor10];
-    }
-    if (!bOverflow)
-      TRACE("Final double value is %16.16g\n", whole);
-
-    if (dwVtBits & VTBIT_R4 &&
-        ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
-    {
-      TRACE("Set R4 to final value\n");
-      V_VT(pVarDst) = VT_R4; /* Fits into a float */
-      V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
-      return S_OK;
-    }
-
-    if (dwVtBits & VTBIT_R8)
-    {
-      TRACE("Set R8 to final value\n");
-      V_VT(pVarDst) = VT_R8; /* Fits into a double */
-      V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
-      return S_OK;
-    }
-
-    if (dwVtBits & VTBIT_CY)
-    {
-      if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
-      {
-        V_VT(pVarDst) = VT_CY; /* Fits into a currency */
-        TRACE("Set CY to final value\n");
-        return S_OK;
-      }
-      TRACE("Value Overflows CY\n");
-    }
-  }
-
-  if (dwVtBits & VTBIT_DECIMAL)
-  {
-    int i;
-    ULONG carry;
-    ULONG64 tmp;
-    DECIMAL* pDec = &V_DECIMAL(pVarDst);
-
-    DECIMAL_SETZERO(pDec);
-    DEC_LO32(pDec) = 0;
-
-    if (pNumprs->dwOutFlags & NUMPRS_NEG)
-      DEC_SIGN(pDec) = DECIMAL_NEG;
-    else
-      DEC_SIGN(pDec) = DECIMAL_POS;
-
-    /* Factor the significant digits */
-    for (i = 0; i < pNumprs->cDig; i++)
-    {
-      tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
-      carry = (ULONG)(tmp >> 32);
-      DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
-      tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
-      carry = (ULONG)(tmp >> 32);
-      DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
-      tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
-      DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
-
-      if (tmp >> 32 & UI4_MAX)
-      {
-VarNumFromParseNum_DecOverflow:
-        TRACE("Overflow\n");
-        DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
-        return DISP_E_OVERFLOW;
-      }
-    }
-
-    /* Account for the scale of the number */
-    while (multiplier10 > 0)
-    {
-      tmp = (ULONG64)DEC_LO32(pDec) * 10;
-      carry = (ULONG)(tmp >> 32);
-      DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
-      tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
-      carry = (ULONG)(tmp >> 32);
-      DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
-      tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
-      DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
-
-      if (tmp >> 32 & UI4_MAX)
-        goto VarNumFromParseNum_DecOverflow;
-      multiplier10--;
-    }
-    DEC_SCALE(pDec) = divisor10;
-
-    V_VT(pVarDst) = VT_DECIMAL;
-    return S_OK;
-  }
-  return DISP_E_OVERFLOW; /* No more output choices */
-}
-#endif
+}
+
 
 /**********************************************************************
@@ -5875,44 +4596,4 @@
     return E_NOTIMPL;
 }
-
-/**********************************************************************
- *              VarFormatNumber [OLEAUT32.107]
- */
-HRESULT WINAPI VarFormatNumber(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-
-/**********************************************************************
- *              VarFormatPercent [OLEAUT32.117]
- */
-HRESULT WINAPI VarFormatPercent(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-
-/**********************************************************************
- *              VarWeekdayName [OLEAUT32.128]
- */
-HRESULT WINAPI VarWeekdayName(int iWeekday, int fAbbrey, int iFirstDay, ULONG dwFlags, BSTR* pbstrOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-
-/**********************************************************************
- *              VarMonthName [OLEAUT32.129]
- */
-HRESULT WINAPI VarMonthName(int iMonth, int fAbbrey, ULONG dwFlags, BSTR* pbstrOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
 
 /**********************************************************************
@@ -6339,7 +5020,4 @@
     case VT_UI4  : rVal = V_UNION(right,ulVal); break;
     case VT_UINT : rVal = V_UNION(right,ulVal); break;
-#ifdef __WIN32OS2__
-    case VT_R8   : rVal = V_UNION(right,dblVal); break;
-#endif
     default: rOk = FALSE;
     }
@@ -6429,281 +5107,4 @@
 
 /**********************************************************************
- *              VarOr [OLEAUT32.157]
- *
- * Perform a logical or (OR) operation on two variants.
- *
- * PARAMS
- *  pVarLeft  [I] First variant
- *  pVarRight [I] Variant to OR with pVarLeft
- *  pVarOut   [O] Destination for OR result
- *
- * RETURNS
- *  Success: S_OK. pVarOut contains the result of the operation with its type
- *           taken from the table listed under VarXor().
- *  Failure: An HRESULT error code indicating the error.
- *
- * NOTES
- *  See the Notes section of VarXor() for further information.
- */
-HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-
-
-#if 0
-    VARTYPE vt = VT_I4;
-    VARIANT varLeft, varRight, varStr;
-    HRESULT hRet;
-
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
-          debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
-          debugstr_VF(pVarRight), pVarOut);
-#endif
-    if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
-        V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
-        V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
-        V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
-        return DISP_E_BADVARTYPE;
-
-    V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY;
-
-    if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
-    {
-        /* NULL OR Zero is NULL, NULL OR value is value */
-        if (V_VT(pVarLeft) == VT_NULL)
-            pVarLeft = pVarRight; /* point to the non-NULL var */
-
-        V_VT(pVarOut) = VT_NULL;
-        V_I4(pVarOut) = 0;
-
-        switch (V_VT(pVarLeft))
-        {
-        case VT_DATE: case VT_R8:
-            if (V_R8(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_BOOL:
-            if (V_BOOL(pVarLeft))
-                *pVarOut = *pVarLeft;
-            return S_OK;
-         case VT_I2: case VT_UI2:
-            if (V_I2(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_I1:
-            if (V_I1(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_UI1:
-            if (V_UI1(pVarLeft))
-                *pVarOut = *pVarLeft;
-            return S_OK;
-        case VT_R4:
-            if (V_R4(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_I4: case VT_UI4: case VT_INT: case VT_UINT:
-            if (V_I4(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_CY:
-            if (V_CY(pVarLeft).int64)
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_I8: case VT_UI8:
-            if (V_I8(pVarLeft))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_DECIMAL:
-            if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
-                goto VarOr_AsEmpty;
-            return S_OK;
-        case VT_BSTR:
-        {
-            VARIANT_BOOL b;
-
-            if (!V_BSTR(pVarLeft))
-                return DISP_E_BADVARTYPE;
-
-            hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
-            if (SUCCEEDED(hRet) && b)
-            {
-                V_VT(pVarOut) = VT_BOOL;
-                V_BOOL(pVarOut) = b;
-            }
-            return hRet;
-        }
-        case VT_NULL: case VT_EMPTY:
-            V_VT(pVarOut) = VT_NULL;
-            return S_OK;
-        default:
-            return DISP_E_BADVARTYPE;
-        }
-    }
-
-    if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
-    {
-        if (V_VT(pVarLeft) == VT_EMPTY)
-            pVarLeft = pVarRight; /* point to the non-EMPTY var */
-
-VarOr_AsEmpty:
-        /* Since one argument is empty (0), OR'ing it with the other simply
-         * gives the others value (as 0|x => x). So just convert the other
-         * argument to the required result type.
-         */
-        switch (V_VT(pVarLeft))
-        {
-        case VT_BSTR:
-            if (!V_BSTR(pVarLeft))
-                return DISP_E_BADVARTYPE;
-
-            hRet = VariantCopy(&varStr, pVarLeft);
-            if (FAILED(hRet))
-                goto VarOr_Exit;
-            pVarLeft = &varStr;
-            hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
-            if (FAILED(hRet))
-                goto VarOr_Exit;
-            /* Fall Through ... */
-        case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
-            V_VT(pVarOut) = VT_I2;
-            break;
-        case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
-        case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
-        case VT_INT: case VT_UINT: case VT_UI8:
-            V_VT(pVarOut) = VT_I4;
-            break;
-        case VT_I8:
-            V_VT(pVarOut) = VT_I8;
-            break;
-        default:
-            return DISP_E_BADVARTYPE;
-        }
-        hRet = VariantCopy(&varLeft, pVarLeft);
-        if (FAILED(hRet))
-            goto VarOr_Exit;
-        pVarLeft = &varLeft;
-        hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut));
-        goto VarOr_Exit;
-    }
-
-    if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
-    {
-        V_VT(pVarOut) = VT_BOOL;
-        V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight);
-        return S_OK;
-    }
-
-    if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
-    {
-        V_VT(pVarOut) = VT_UI1;
-        V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight);
-        return S_OK;
-    }
-
-    if (V_VT(pVarLeft) == VT_BSTR)
-    {
-        hRet = VariantCopy(&varStr, pVarLeft);
-        if (FAILED(hRet))
-            goto VarOr_Exit;
-        pVarLeft = &varStr;
-        hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
-        if (FAILED(hRet))
-            goto VarOr_Exit;
-    }
-
-    if (V_VT(pVarLeft) == VT_BOOL &&
-        (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR))
-    {
-        vt = VT_BOOL;
-    }
-    else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
-        V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) &&
-        (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
-        V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR))
-    {
-        vt = VT_I2;
-    }
-    else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
-    {
-        if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
-            return DISP_E_TYPEMISMATCH;
-        vt = VT_I8;
-    }
-
-    hRet = VariantCopy(&varLeft, pVarLeft);
-    if (FAILED(hRet))
-        goto VarOr_Exit;
-
-    hRet = VariantCopy(&varRight, pVarRight);
-    if (FAILED(hRet))
-        goto VarOr_Exit;
-
-    if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4)
-        V_VT(&varLeft) = VT_I4; /* Don't overflow */
-    else
-    {
-        double d;
-
-        if (V_VT(&varLeft) == VT_BSTR &&
-            FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d)))
-            hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL);
-        if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt)
-            hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
-        if (FAILED(hRet))
-            goto VarOr_Exit;
-    }
-
-    if (vt == VT_I4 && V_VT(&varRight) == VT_UI4)
-        V_VT(&varRight) = VT_I4; /* Don't overflow */
-    else
-    {
-        double d;
-
-        if (V_VT(&varRight) == VT_BSTR &&
-            FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d)))
-            hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL);
-        if (SUCCEEDED(hRet) && V_VT(&varRight) != vt)
-            hRet = VariantChangeType(&varRight, &varRight, 0, vt);
-        if (FAILED(hRet))
-            goto VarOr_Exit;
-    }
-
-    V_VT(pVarOut) = vt;
-    if (vt == VT_I8)
-    {
-        V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight);
-    }
-    else if (vt == VT_I4)
-    {
-        V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight);
-    }
-    else
-    {
-        V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight);
-    }
-
-VarOr_Exit:
-    VariantClear(&varStr);
-    VariantClear(&varLeft);
-    VariantClear(&varRight);
-    return hRet;
-#endif
-}
-
-
-/**********************************************************************
- *              VarXor [OLEAUT32.167]
- */
-HRESULT WINAPI VarXor(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
  *              VarNot [OLEAUT32.174]
  *
@@ -6732,568 +5133,4 @@
     TRACE("rc=%d, Result:\n", (int) rc);
     dump_Variant(result);
-    return rc;
-}
-
-/**********************************************************************
- *              VarNeg [OLEAUT32.173]
- *
- * Negate the value of a variant.
- *
- * PARAMS
- *  pVarIn  [I] Source variant
- *  pVarOut [O] Destination for converted value
- *
- * RETURNS
- *  Success: S_OK. pVarOut contains the converted value.
- *  Failure: An HRESULT error code indicating the error.
- *
- * NOTES
- *  - The type of the value stored in pVarOut depends on the type of pVarIn,
- *    according to the following table:
- *| Input Type       Output Type
- *| ----------       -----------
- *|  VT_EMPTY         VT_I2
- *|  VT_UI1           VT_I2
- *|  VT_BOOL          VT_I2
- *|  VT_BSTR          VT_R8
- *|  All Others       Unchanged (unless promoted)
- *  - Where the negated value of a variant does not fit in its base type, the type
- *    is promoted according to the following table:
- *| Input Type       Promoted To
- *| ----------       -----------
- *|   VT_I2            VT_I4
- *|   VT_I4            VT_R8
- *|   VT_I8            VT_R8
- *  - The native version of this function returns DISP_E_BADVARTYPE for valid
- *    variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
- *    for types which are not valid. Since this is in contravention of the
- *    meaning of those error codes and unlikely to be relied on by applications,
- *    this implementation returns errors consistent with the other high level
- *    variant math functions.
- */
-HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- * VarAbs [OLEAUT32.168]
- *
- * Convert a variant to its absolute value.
- *
- * PARAMS
- *  pVarIn  [I] Source variant
- *  pVarOut [O] Destination for converted value
- *
- * RETURNS
- *  Success: S_OK. pVarOut contains the absolute value of pVarIn.
- *  Failure: An HRESULT error code indicating the error.
- *
- * NOTES
- *  - This function does not process by-reference variants.
- *  - The type of the value stored in pVarOut depends on the type of pVarIn,
- *    according to the following table:
- *| Input Type       Output Type
- *| ----------       -----------
- *| VT_BOOL          VT_I2
- *| VT_BSTR          VT_R8
- *| (All others)     Unchanged
- */
-HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarFix [OLEAUT32.169]
- */
-HRESULT WINAPI VarFix(LPVARIANT pvarIn, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarInt [OLEAUT32.172]
- */
-HRESULT WINAPI VarInt(LPVARIANT pvarIn, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarImp [OLEAUT32.154]
- */
-HRESULT WINAPI VarImp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarMod [OLEAUT32.155]
- */
-HRESULT WINAPI VarMod(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarEqv [OLEAUT32.152]
- *
- * Determine if two variants contain the same value.
- *
- * PARAMS
- *  pVarLeft  [I] First variant to compare
- *  pVarRight [I] Variant to compare to pVarLeft
- *  pVarOut   [O] Destination for comparison result
- *
- * RETURNS
- *  Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
- *           if equivalent or non-zero otherwise.
- *  Failure: An HRESULT error code indicating the error.
- *
- * NOTES
- *  - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
- *    the result.
- */
-HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-
-/**********************************************************************
- *              VarIdiv [OLEAUT32.153]
- */
-HRESULT WINAPI VarIdiv(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarRound [OLEAUT32.175]
- */
-HRESULT VarRound(LPVARIANT  pvarIn, INT cDecimals, LPVARIANT  pvarResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarPow [OLEAUT32.158]
- *
- */
-HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
-{
-    HRESULT hr;
-    VARIANT dl,dr;
-
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
-          right, debugstr_VT(right), debugstr_VF(right), result);
-#endif
-
-    hr = VariantChangeType(&dl,left,0,VT_R8);
-    if (!SUCCEEDED(hr)) {
-        ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
-        return E_FAIL;
-    }
-    hr = VariantChangeType(&dr,right,0,VT_R8);
-    if (!SUCCEEDED(hr)) {
-        ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
-        return E_FAIL;
-    }
-    V_VT(result) = VT_R8;
-    V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
-    return S_OK;
-}
-
-/**********************************************************************
- *              VarAdd [OLEAUT32.141]
- * FIXME: From MSDN: If ... Then
- * Both expressions are of the string type Concatenated.
- * One expression is a string type and the other a character Addition.
- * One expression is numeric and the other is a string Addition.
- * Both expressions are numeric Addition.
- * Either expression is NULL NULL is returned.
- * Both expressions are empty  Integer subtype is returned.
- *
- */
-HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
-{
-    HRESULT rc = E_FAIL;
-
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
-#endif
-
-    if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
-    	return VariantCopy(result,right);
-
-    if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
-    	return VariantCopy(result,left);
-
-    /* check if we add doubles */
-    if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        double       lVal = -1;
-        double       rVal = -1;
-        double       res  = -1;
-
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_UNION(left,cVal);   break;
-        case VT_I2   : lVal = V_UNION(left,iVal);   break;
-        case VT_I4   : lVal = V_UNION(left,lVal);   break;
-        case VT_INT  : lVal = V_UNION(left,lVal);   break;
-        case VT_UI1  : lVal = V_UNION(left,bVal);   break;
-        case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
-        case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
-        case VT_UINT : lVal = V_UNION(left,ulVal);  break;
-        case VT_R4   : lVal = V_UNION(left,fltVal);  break;
-        case VT_R8   : lVal = V_UNION(left,dblVal);  break;
-	case VT_NULL : lVal = 0.0;  break;
-        default: lOk = FALSE;
-        }
-
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_UNION(right,cVal);  break;
-        case VT_I2   : rVal = V_UNION(right,iVal);  break;
-        case VT_I4   : rVal = V_UNION(right,lVal);  break;
-        case VT_INT  : rVal = V_UNION(right,lVal);  break;
-        case VT_UI1  : rVal = V_UNION(right,bVal);  break;
-        case VT_UI2  : rVal = V_UNION(right,uiVal); break;
-        case VT_UI4  : rVal = V_UNION(right,ulVal); break;
-        case VT_UINT : rVal = V_UNION(right,ulVal); break;
-        case VT_R4   : rVal = V_UNION(right,fltVal);break;
-        case VT_R8   : rVal = V_UNION(right,dblVal);break;
-	case VT_NULL : rVal = 0.0; break;
-        default: rOk = FALSE;
-        }
-
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = VT_R8;
-            V_UNION(result,dblVal)  = res;
-            rc = S_OK;
-        } else {
-	    FIXME("Unhandled type pair %d / %d in double addition.\n",
-        	(V_VT(left)&VT_TYPEMASK),
-        	(V_VT(right)&VT_TYPEMASK)
-	    );
-	}
-	return rc;
-    }
-
-    /* now check if we add floats. VT_R8 can no longer happen here! */
-    if (((V_VT(left)&VT_TYPEMASK) == VT_R4) || ((V_VT(right)&VT_TYPEMASK) == VT_R4)) {
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        float        lVal = -1;
-        float        rVal = -1;
-        float        res  = -1;
-
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_UNION(left,cVal);   break;
-        case VT_I2   : lVal = V_UNION(left,iVal);   break;
-        case VT_I4   : lVal = V_UNION(left,lVal);   break;
-        case VT_INT  : lVal = V_UNION(left,lVal);   break;
-        case VT_UI1  : lVal = V_UNION(left,bVal);   break;
-        case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
-        case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
-        case VT_UINT : lVal = V_UNION(left,ulVal);  break;
-        case VT_R4   : lVal = V_UNION(left,fltVal);  break;
-	case VT_NULL : lVal = 0.0;  break;
-        default: lOk = FALSE;
-        }
-
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_UNION(right,cVal);  break;
-        case VT_I2   : rVal = V_UNION(right,iVal);  break;
-        case VT_I4   : rVal = V_UNION(right,lVal);  break;
-        case VT_INT  : rVal = V_UNION(right,lVal);  break;
-        case VT_UI1  : rVal = V_UNION(right,bVal);  break;
-        case VT_UI2  : rVal = V_UNION(right,uiVal); break;
-        case VT_UI4  : rVal = V_UNION(right,ulVal); break;
-        case VT_UINT : rVal = V_UNION(right,ulVal); break;
-        case VT_R4   : rVal = V_UNION(right,fltVal);break;
-	case VT_NULL : rVal = 0.0; break;
-        default: rOk = FALSE;
-        }
-
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = VT_R4;
-            V_UNION(result,fltVal)  = res;
-            rc = S_OK;
-        } else {
-	    FIXME("Unhandled type pair %d / %d in float addition.\n",
-        	(V_VT(left)&VT_TYPEMASK),
-        	(V_VT(right)&VT_TYPEMASK)
-	    );
-	}
-	return rc;
-    }
-
-    /* Handle strings as concat */
-    if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
-        (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
-        V_VT(result) = VT_BSTR;
-        return VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
-    } else {
-
-        /* Integers */
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        LONGLONG     lVal = -1;
-        LONGLONG     rVal = -1;
-        LONGLONG     res  = -1;
-        int          resT = 0; /* Testing has shown I2 + I2 == I2, all else
-                                  becomes I4                                */
-
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
-        case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
-        case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
-        case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
-        case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
-        case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
-        case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
-        case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
-	case VT_NULL : lVal = 0; resT = VT_I4; break;
-        default: lOk = FALSE;
-        }
-
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
-        case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
-        case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
-        case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
-        case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
-        case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
-        case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
-        case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
-	case VT_NULL : rVal = 0; resT=VT_I4; break;
-        default: rOk = FALSE;
-        }
-
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = resT;
-            switch (resT) {
-            case VT_I2   : V_UNION(result,iVal)  = res; break;
-            case VT_I4   : V_UNION(result,lVal)  = res; break;
-            default:
-                FIXME("Unexpected result variant type %x\n", resT);
-                V_UNION(result,lVal)  = res;
-            }
-            rc = S_OK;
-
-        } else {
-            FIXME("unimplemented part (0x%x + 0x%x)\n",V_VT(left), V_VT(right));
-        }
-    }
-#if 0
-    TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
-#endif
-    return rc;
-}
-
-/**********************************************************************
- *              VarSub [OLEAUT32.159]
- *
- */
-HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
-{
-    HRESULT rc = E_FAIL;
-    VARTYPE lvt,rvt,resvt;
-    VARIANT lv,rv;
-    BOOL found;
-
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
-#endif
-
-    VariantInit(&lv);VariantInit(&rv);
-    lvt = V_VT(left)&VT_TYPEMASK;
-    rvt = V_VT(right)&VT_TYPEMASK;
-    found = FALSE;resvt = VT_VOID;
-    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_DATE)|(1<<VT_R4)|(1<<VT_R8))) {
-	found = TRUE;
-	resvt = VT_R8;
-    }
-    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
-	found = TRUE;
-	resvt = VT_I4;
-    }
-    if (!found) {
-	FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
-	return E_FAIL;
-    }
-    rc = VariantChangeType(&lv, left, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
-	return rc;
-    }
-    rc = VariantChangeType(&rv, right, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
-	return rc;
-    }
-    switch (resvt) {
-    case VT_R8:
-	V_VT(result) = resvt;
-	V_R8(result) = V_R8(&lv) - V_R8(&rv);
-	rc = S_OK;
-	break;
-    case VT_I4:
-	V_VT(result) = resvt;
-	V_I4(result) = V_I4(&lv) - V_I4(&rv);
-	rc = S_OK;
-	break;
-    }
-#if 0
-    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
-#endif
-    return rc;
-}
-
-
-/**********************************************************************
- *              VarDiv [OLEAUT32.143]
- *
- */
-HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
-{
-    HRESULT rc = E_FAIL;
-    VARTYPE lvt,rvt,resvt;
-    VARIANT lv,rv;
-    BOOL found;
-
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
-#endif
-
-    VariantInit(&lv);VariantInit(&rv);
-    lvt = V_VT(left)&VT_TYPEMASK;
-    rvt = V_VT(right)&VT_TYPEMASK;
-    found = FALSE;resvt = VT_VOID;
-    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
-	found = TRUE;
-	resvt = VT_R8;
-    }
-    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
-	found = TRUE;
-	resvt = VT_I4;
-    }
-    if (!found) {
-	FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
-	return E_FAIL;
-    }
-    rc = VariantChangeType(&lv, left, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
-	return rc;
-    }
-    rc = VariantChangeType(&rv, right, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
-	return rc;
-    }
-    switch (resvt) {
-    case VT_R8:
-	V_VT(result) = resvt;
-	V_R8(result) = V_R8(&lv) / V_R8(&rv);
-	rc = S_OK;
-	break;
-    case VT_I4:
-	V_VT(result) = resvt;
-	V_I4(result) = V_I4(&lv) / V_I4(&rv);
-	rc = S_OK;
-	break;
-    }
-#if 0
-    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
-#endif
-    return rc;
-}
-
-/**********************************************************************
- *              VarMul [OLEAUT32.156]
- *
- */
-HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
-{
-    HRESULT rc = E_FAIL;
-    VARTYPE lvt,rvt,resvt;
-    VARIANT lv,rv;
-    BOOL found;
-#if 0
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
-#endif
-    VariantInit(&lv);VariantInit(&rv);
-    lvt = V_VT(left)&VT_TYPEMASK;
-    rvt = V_VT(right)&VT_TYPEMASK;
-    found = FALSE;resvt=VT_VOID;
-    if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
-	found = TRUE;
-	resvt = VT_R8;
-    }
-    if (!found && (((1<<lvt) | (1<<rvt)) & ((1<<VT_I1)|(1<<VT_I2)|(1<<VT_UI1)|(1<<VT_UI2)|(1<<VT_I4)|(1<<VT_UI4)|(1<<VT_INT)|(1<<VT_UINT)))) {
-	found = TRUE;
-	resvt = VT_I4;
-    }
-    if (!found) {
-	FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
-	return E_FAIL;
-    }
-    rc = VariantChangeType(&lv, left, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
-	return rc;
-    }
-    rc = VariantChangeType(&rv, right, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
-	return rc;
-    }
-    switch (resvt) {
-    case VT_R8:
-	V_VT(result) = resvt;
-	V_R8(result) = V_R8(&lv) * V_R8(&rv);
-	rc = S_OK;
-	break;
-    case VT_I4:
-	V_VT(result) = resvt;
-	V_I4(result) = V_I4(&lv) * V_I4(&rv);
-	rc = S_OK;
-	break;
-    }
-#if 0
-    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
-#endif
     return rc;
 }
@@ -7737,125 +5574,2 @@
     return rc;
 }
-
-
-/**********************************************************************
- *              VarDecAdd [OLEAUT32.177]
- */
-HRESULT WINAPI VarDecAdd(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecSub [OLEAUT32.181]
- */
-HRESULT WINAPI VarDecSub(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecMul [OLEAUT32.179]
- */
-HRESULT WINAPI VarDecMul(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecRound [OLEAUT32.203]
- */
-HRESULT WINAPI VarDecRound(LPDECIMAL pdecIn, int iDecimals, LPDECIMAL  pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecDiv [OLEAUT32.178]
- */
-HRESULT WINAPI VarDecDiv(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecCmp [OLEAUT32.204]
- */
-HRESULT WINAPI VarDecCmp(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecAbs [OLEAUT32.182]
- */
-HRESULT WINAPI VarDecAbs(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecFix [OLEAUT32.187]
- */
-HRESULT WINAPI VarDecFix(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecInt [OLEAUT32.188]
- */
-HRESULT WINAPI VarDecInt(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-
-/**********************************************************************
- *              VarDecNeg [OLEAUT32.189]
- */
-HRESULT WINAPI VarDecNeg(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/**********************************************************************
- *              VarDecCmpR8 [OLEAUT32.298]
- */
-HRESULT WINAPI VarDecCmpR8(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
-{
-  FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
-  return E_NOTIMPL;
-}
-
-/************************************************************************
- * VarDecFromStr (OLEAUT32.197)
- *
- * Convert a VT_BSTR to a DECIMAL.
- *
- * PARAMS
- *  strIn   [I] Source
- *  lcid    [I] LCID for the conversion
- *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
- *  pDecOut [O] Destination
- *
- * RETURNS
- *  Success: S_OK.
- *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
- */
-HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
-{
-  TRACE("%s: now calling VARIANT_NumberFromBstr\n", __FUNCTION__);
-  return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
-}
-
Index: trunk/src/pmkbdhk/makefile
===================================================================
--- trunk/src/pmkbdhk/makefile	(revision 21307)
+++ trunk/src/pmkbdhk/makefile	(revision 21308)
@@ -7,4 +7,5 @@
 #
 
+NOPEHDR=1 
 
 #
Index: trunk/src/psapi/psapi.DEF
===================================================================
--- trunk/src/psapi/psapi.DEF	(revision 21307)
+++ trunk/src/psapi/psapi.DEF	(revision 21308)
@@ -10,5 +10,5 @@
     EmptyWorking		= _EmptyWorkingSet@4  			@1  
     EnumDeviceDrivers		= _EnumDeviceDrivers@12  		@2  
-    EnumProcessModules		= _EnumProcessModules@16  		@3  
+    EnumProcessModules		= _PSAPI_EnumProcessModules@16 		@3  
     EnumProcesses		= _EnumProcesses@12  			@4  
     GetDeviceDriverBaseNameA	= _GetDeviceDriverBaseNameA@12  	@5  
@@ -22,5 +22,5 @@
     GetModuleFileNameExA	= _GetModuleFileNameExA@16 		@13  
     GetModuleFileNameExW	= _GetModuleFileNameExW@16 		@14  
-    GetModuleInformation	= _GetModuleInformation@16  		@15
+    GetModuleInformation	= _PSAPI_GetModuleInformation@16	@15
     GetProcessMemoryInfo	= _GetProcessMemoryInfo@12		@16  
     GetWsChanges		= _GetWsChanges@12			@17  
Index: trunk/src/psapi/psapi.cpp
===================================================================
--- trunk/src/psapi/psapi.cpp	(revision 21307)
+++ trunk/src/psapi/psapi.cpp	(revision 21308)
@@ -56,4 +56,5 @@
 }
 
+#ifndef __WIN32OS2__
 /***********************************************************************
  *           EnumProcessModules (PSAPI.4)
@@ -70,4 +71,5 @@
   return TRUE;
 }
+#endif
 
 /***********************************************************************
@@ -191,4 +193,5 @@
 }
 
+#ifdef __WIN32OS2__
 /***********************************************************************
  *           GetModuleFileNameExA (PSAPI.13)
@@ -197,7 +200,17 @@
   HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
 {
-#ifdef DEBUG
-  dprintf(("PSAPI: GetModuleFileNameExA not implemented\n"));
-#endif
+   if(hProcess != GetCurrentProcess()) {
+       dprintf(("PSAPI: GetModuleFileNameExA not implemented for other processes (%x %x)\n", hProcess, hModule));
+       return 0;
+   }
+   return GetModuleFileNameA(hModule, lpFilename, nSize);
+}
+#else
+/***********************************************************************
+ *           GetModuleFileNameExA (PSAPI.13)
+ */
+DWORD WINAPI GetModuleFileNameExA(
+  HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
+{
   if(lpFilename&&nSize)
     lpFilename[0]='\0';
@@ -205,4 +218,5 @@
   return 0;
 }
+#endif
 
 /***********************************************************************
@@ -221,4 +235,5 @@
 }
 
+#ifndef __WIN32OS2__
 /***********************************************************************
  *           GetModuleInformation (PSAPI.15)
@@ -234,4 +249,5 @@
   return TRUE;
 }
+#endif
 
 /***********************************************************************
Index: trunk/src/riched32/charlist.c
===================================================================
--- trunk/src/riched32/charlist.c	(revision 21307)
+++ trunk/src/riched32/charlist.c	(revision 21308)
@@ -32,4 +32,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+
+#ifdef __WIN32OS2__ /* no useful trace in this file! */
+#define TRACE(a) do {} while (0)
+#endif
 
 extern HANDLE RICHED32_hHeap;
Index: trunk/src/riched32/reader.c
===================================================================
--- trunk/src/riched32/reader.c	(revision 21307)
+++ trunk/src/riched32/reader.c	(revision 21308)
@@ -80,4 +80,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+
+#ifdef __WIN32OS2__ /* no useful trace in this file! */
+#define TRACE(a) do {} while (0)
+#endif
 
 extern HANDLE RICHED32_hHeap;
Index: trunk/src/riched32/richedit.c
===================================================================
--- trunk/src/riched32/richedit.c	(revision 21307)
+++ trunk/src/riched32/richedit.c	(revision 21308)
@@ -43,4 +43,9 @@
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
 
+#ifdef __WIN32OS2__
+/** custom build hack. */
+BOOL (* WINAPI pfnCustomRichedHack_EM_STREAMIN)(HWND, LPSTR) = NULL;
+#endif
+
 HANDLE RICHED32_hHeap = (HANDLE)NULL;
 /* LPSTR  RICHED32_aSubclass = (LPSTR)NULL; */
@@ -198,4 +203,10 @@
 	    {
 	    	RTFToBuffer(rtfBuffer, rtfBufferSize);
+#ifdef __WIN32OS2__
+                /* This is a very very ugly hack to work around some major parsing errors. */
+                if (pfnCustomRichedHack_EM_STREAMIN)
+            	    pfnCustomRichedHack_EM_STREAMIN(hwnd, rtfBuffer);
+                else
+#endif
             	SetWindowTextA(hwnd,rtfBuffer);
 	    	HeapFree(RICHED32_hHeap, 0,rtfBuffer);
@@ -843,2 +854,16 @@
 	return ret;
 }
+
+
+#ifdef __WIN32OS2__
+/** Enables a callback replacement for the SetWindowTextA call finalizing
+ * the handling of an EM_STREAMIN message.
+ * @remark don't use this hack.
+ */
+BOOL WINAPI ODIN_RichedHack_EM_STREAMIN(BOOL (* WINAPI pfn)(HWND, LPSTR))
+{
+    pfnCustomRichedHack_EM_STREAMIN = pfn;
+    return TRUE;
+}
+#endif
+
Index: trunk/src/riched32/textwriter.c
===================================================================
--- trunk/src/riched32/textwriter.c	(revision 21307)
+++ trunk/src/riched32/textwriter.c	(revision 21308)
@@ -45,4 +45,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(richedit);
+
+#ifdef __WIN32OS2__ /* no useful trace in this file! */
+#define TRACE(a) do {} while (0)
+#endif
 
 static void	TextClass ();
Index: trunk/src/user32/Makefile
===================================================================
--- trunk/src/user32/Makefile	(revision 21307)
+++ trunk/src/user32/Makefile	(revision 21308)
@@ -130,4 +130,5 @@
 $(ODIN32_LIB)/libuls.lib \
 $(ODIN32_LIB)/$(ODINCRT).lib \
+$(ODIN32_LIB)/imm32os2.lib \
 OS2386.LIB \
 $(RTLLIB_O)
Index: trunk/src/user32/USER32.DEF
===================================================================
--- trunk/src/user32/USER32.DEF	(revision 21307)
+++ trunk/src/user32/USER32.DEF	(revision 21308)
@@ -750,2 +750,4 @@
     _clipboardPMToOdinFormat@4                                   @2043 NONAME
     _clipboardOdinToPMFormat@4                                   @2044 NONAME
+
+    _GetOS2Icon@4                                                @2045 NONAME
Index: trunk/src/user32/edit.c
===================================================================
--- trunk/src/user32/edit.c	(revision 21307)
+++ trunk/src/user32/edit.c	(revision 21308)
@@ -31,4 +31,5 @@
 #include "ctrlconf.h"
 #include <heapstring.h>
+#include <imm.h>
 #endif
 
@@ -128,4 +129,10 @@
     HLOCAL hloc32A;     /* alias for ANSI control receiving EM_GETHANDLE
                    or EM_SETHANDLE */
+#ifdef __WIN32OS2__
+    LPWSTR  compStr;
+    INT     compStrLen;
+    BOOL    moveCaret;
+    DWORD   sentenceMode;
+#endif
 } EDITSTATE;
 
@@ -1113,9 +1120,16 @@
             // always DBCS char
             CHAR charA[ 2 ];
-
+            INT  lenA = 1;
+
+            if( IsDBCSLeadByte(( CHAR )( wParam >> 8 )))
+            {
                 charA[ 0 ] = ( CHAR )( wParam >> 8 );
                 charA[ 1 ] = ( CHAR )wParam;
-
-            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, 2, ( LPWSTR )&charW, 1);
+                lenA = 2;
+            }
+            else
+                charA[ 0 ] = ( CHAR )wParam;
+
+            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, lenA, ( LPWSTR )&charW, 1);
         }
 
@@ -1123,4 +1137,271 @@
         break;
     }
+
+    case WM_IME_COMPOSITION:
+    {
+        HIMC    himc;
+        LONG    bufSize;
+        INT     i;
+        BOOL    passToDefWnd = FALSE;
+#ifdef DEBUG
+        LPSTR   strA;
+        INT     lenA;
+#endif
+
+        DPRINTF_EDIT_MSG32("WM_IME_COMPOSITION");
+
+        himc = ImmGetContext( hwnd );
+
+        if( es->sentenceMode )
+            passToDefWnd = TRUE;
+        else if( lParam & GCS_RESULTSTR )
+        {
+            LPWSTR  resultStr = NULL;
+            INT     resultStrLen = 0;
+
+            dprintf(("WM_IME_COMPOSITION : GCS_RESULTSTR"));
+
+            bufSize = ImmGetCompositionStringW( himc, GCS_RESULTSTR, NULL, 0 );
+            if( bufSize > 0 )
+            {
+                INT i;
+
+                resultStrLen = bufSize / sizeof( WCHAR );
+                resultStr = malloc( bufSize + sizeof( WCHAR ));
+                resultStr[ resultStrLen ] = 0;
+
+                ImmGetCompositionStringW( himc, GCS_RESULTSTR, resultStr, bufSize );
+
+#ifdef DEBUG
+                lenA = WideCharToMultiByte( CP_ACP, 0, resultStr, resultStrLen, 0, 0, 0, 0 );
+                strA = malloc( lenA + 1 );
+                WideCharToMultiByte( CP_ACP, 0, resultStr, resultStrLen, strA, lenA, 0, 0 );
+                strA[ lenA ] = 0;
+                dprintf(("Result String : '%s'", strA ));
+                free( strA );
+                dprintf(("Composition Len %d", es->compStrLen ));
+#endif
+                DestroyCaret();
+                if( es->compStrLen > 0 )
+                {
+                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
+                    for( i = 0; i < es->compStrLen; i++ )
+                        EDIT_MoveForward(hwnd, es, TRUE);
+                    EDIT_WM_Clear(hwnd, es);
+                }
+
+                EDIT_EM_ReplaceSel(hwnd, es, TRUE, resultStr, TRUE);
+
+                CreateCaret(hwnd, 0, 2, es->line_height);
+                EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
+                ShowCaret(hwnd);
+
+                free( resultStr );
+
+            }
+
+            if( es->compStr )
+                free( es->compStr );
+
+            es->compStr = NULL;
+            es->compStrLen = 0;
+        }
+        else if( lParam & GCS_COMPSTR )
+        {
+            INT prevLen = es->compStrLen;
+
+            dprintf(("WM_IME_COMPOSITION : GCS_COMPSTR"));
+
+            if( es->compStr )
+                free( es->compStr );
+
+            es->compStr = NULL;
+            es->compStrLen = 0;
+
+            bufSize = ImmGetCompositionStringW( himc, GCS_COMPSTR, NULL, 0 );
+            if( bufSize > 0 )
+            {
+                HDC     hdc;
+                SIZE    size;
+                BOOL    oldMoveCaret;
+
+                es->compStrLen = bufSize / sizeof( WCHAR );
+                es->compStr = malloc( bufSize + sizeof( WCHAR ));
+                es->compStr[ es->compStrLen ] = 0;
+
+                ImmGetCompositionStringW( himc, GCS_COMPSTR, es->compStr, bufSize );
+
+#ifdef DEBUG
+                lenA = WideCharToMultiByte( CP_ACP, 0, es->compStr, es->compStrLen, 0, 0, 0, 0 );
+                strA = malloc( lenA + 1 );
+                WideCharToMultiByte( CP_ACP, 0, es->compStr, es->compStrLen, strA, lenA, 0, 0  );
+                strA[ lenA ] = 0;
+                dprintf(("Composition String : '%s'", strA ));
+                free( strA );
+#endif
+                hdc = GetDC( hwnd );
+                GetTextExtentPoint32W( hdc, es->compStr, es->compStrLen, &size);
+                ReleaseDC( hwnd, hdc );
+
+                oldMoveCaret = es->moveCaret;
+
+                es->moveCaret = FALSE; // to prevent cursor from flashing too many
+
+                if( prevLen > 0 )
+                {
+                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
+                    for( i = 0; i < prevLen; i++ )
+                        EDIT_MoveForward(hwnd, es, TRUE);
+                    EDIT_WM_Clear(hwnd, es);
+                }
+
+                EDIT_EM_ReplaceSel(hwnd, es, TRUE, es->compStr, TRUE);
+
+                for( i = 0; i < es->compStrLen; i++ )
+                    EDIT_MoveBackward(hwnd, es, FALSE);
+
+                es->moveCaret = oldMoveCaret;
+
+                CreateCaret(hwnd, 0, size.cx, es->line_height);
+                EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
+                ShowCaret(hwnd);
+            }
+        }
+        else
+            passToDefWnd = TRUE;
+
+        ImmReleaseContext( hwnd, himc );
+
+        if( passToDefWnd )
+        {
+            if( unicode )
+                result = DefWindowProcW( hwnd, msg, wParam, lParam );
+            else
+                result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        }
+        break;
+    }
+
+    case WM_IME_COMPOSITIONFULL:
+        DPRINTF_EDIT_MSG32("WM_IME_COMPOSITIONFULL");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_CONTROL:
+        DPRINTF_EDIT_MSG32("WM_IME_CONTROL");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_ENDCOMPOSITION:
+        DPRINTF_EDIT_MSG32("WM_IME_ENDCOMPOSITION");
+
+        if( es->compStr )
+        {
+            INT i;
+
+            DestroyCaret();
+
+            EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
+            for( i = 0; i < es->compStrLen; i++ )
+                EDIT_MoveForward(hwnd, es, TRUE);
+            EDIT_WM_Clear(hwnd, es);
+
+            CreateCaret(hwnd, 0, 2, es->line_height);
+            EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
+            ShowCaret(hwnd);
+
+            free( es->compStr );
+        }
+
+        es->compStr = NULL;
+        es->compStrLen = 0;
+
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_NOTIFY:
+        DPRINTF_EDIT_MSG32("WM_IME_NOTIFY");
+
+        if( wParam == IMN_SETSENTENCEMODE )
+        {
+            HIMC  himc;
+            DWORD conversionMode;
+
+            himc = ImmGetContext( hwnd );
+
+            ImmGetConversionStatus( himc, &conversionMode, &es->sentenceMode );
+
+            ImmReleaseContext( hwnd, himc );
+        }
+
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_REQUEST:
+        DPRINTF_EDIT_MSG32("WM_IME_REQUEST");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_SELECT:
+        DPRINTF_EDIT_MSG32("WM_IME_SELECT");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_SETCONTEXT:
+        DPRINTF_EDIT_MSG32("WM_IME_SETCONTEXT");
+
+        dprintf(("ImmGetProperty %08lx", ImmGetProperty( 0, IGP_CONVERSION )));
+
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case WM_IME_STARTCOMPOSITION:
+        DPRINTF_EDIT_MSG32("WM_IME_STARTCOMPOSITION");
+
+        es->compStr = NULL;
+        es->compStrLen = 0;
+
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case EM_GETIMESTATUS:
+        DPRINTF_EDIT_MSG32("EM_GETIMESTATUS");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
+
+    case EM_SETIMESTATUS:
+        DPRINTF_EDIT_MSG32("EM_SETIMESTATUS");
+        if( unicode )
+            result = DefWindowProcW( hwnd, msg, wParam, lParam );
+        else
+            result = DefWindowProcA( hwnd, msg, wParam, lParam );
+        break;
 #endif
 
@@ -2440,5 +2721,39 @@
 {
     LRESULT res = EDIT_EM_PosFromChar(hwnd, es, pos, after_wrap);
+
+#ifdef __WIN32OS2__
+    if( es->moveCaret )
+    {
+        HIMC            himc;
+        CANDIDATEFORM   candForm;
+
+        himc = ImmGetContext( hwnd );
+
+#endif
+
     SetCaretPos(SLOWORD(res), SHIWORD(res));
+
+#ifdef __WIN32OS2__
+        if( es->sentenceMode )
+        {
+            COMPOSITIONFORM cf;
+
+            cf.dwStyle = CFS_POINT;
+            cf.ptCurrentPos.x = SLOWORD( res );
+            cf.ptCurrentPos.y = SHIWORD( res );
+
+            ImmSetCompositionWindow( himc, &cf );
+        }
+
+        candForm.dwIndex = 0;
+        candForm.dwStyle = CFS_CANDIDATEPOS;
+        candForm.ptCurrentPos.x = SLOWORD( res );
+        candForm.ptCurrentPos.y = SHIWORD( res ) + es->line_height;
+
+        ImmSetCandidateWindow( himc, &candForm );
+
+        ImmReleaseContext( hwnd, himc );
+    }
+#endif
 }
 
@@ -4773,4 +5088,20 @@
     }
 
+#ifdef __WIN32OS2__
+    es->compStr = NULL;
+    es->compStrLen = 0;
+    es->moveCaret = TRUE;
+    {
+        HIMC  himc;
+        DWORD conversionMode;
+
+        himc = ImmGetContext( hwnd );
+
+        ImmGetConversionStatus( himc, &conversionMode, &es->sentenceMode );
+
+        ImmReleaseContext( hwnd, himc );
+    }
+#endif
+
     return TRUE;
 }
@@ -4904,4 +5235,7 @@
     es->font = font;
     dc = GetDC(hwnd);
+#ifdef __WIN32OS2__
+    // todo : set font of IME window
+#endif
     if (font)
         old_font = SelectObject(dc, font);
Index: trunk/src/user32/listbox.c
===================================================================
--- trunk/src/user32/listbox.c	(revision 21307)
+++ trunk/src/user32/listbox.c	(revision 21308)
@@ -3028,9 +3028,16 @@
             // always DBCS char
             CHAR charA[ 2 ];
-
+            INT  lenA = 1;
+
+            if( IsDBCSLeadByte(( CHAR )( wParam >> 8 )))
+            {
                 charA[ 0 ] = ( CHAR )( wParam >> 8 );
                 charA[ 1 ] = ( CHAR )wParam;
-
-            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, 2, ( LPWSTR )&charW, 1);
+                lenA = 2;
+            }
+            else
+                charA[ 0 ] = ( CHAR )wParam;
+
+            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, lenA, ( LPWSTR )&charW, 1);
         }
         return LISTBOX_HandleChar( hwnd, descr, charW );
Index: trunk/src/user32/oslibmsgtranslate.cpp
===================================================================
--- trunk/src/user32/oslibmsgtranslate.cpp	(revision 21307)
+++ trunk/src/user32/oslibmsgtranslate.cpp	(revision 21308)
@@ -15,4 +15,6 @@
  *
  */
+#define  INCL_NLS
+#define  INCL_GPI
 #define  INCL_WIN
 #define  INCL_PM
@@ -42,4 +44,6 @@
 #include "user32api.h"
 
+#include <os2im.h>
+#include <im32.h>
 
 #define DBG_LOCALLOG    DBG_oslibmsgtranslate
@@ -48,4 +52,6 @@
 static BOOL fGenerateDoubleClick = FALSE;
 static MSG  doubleClickMsg = {0};
+
+extern UINT WINAPI GetACP(void); // from winnls.h
 
 //For wheel mouse translation
@@ -753,4 +759,88 @@
         if( scanCode != 0 )
         {
+            switch( SHORT2FROMMP( os2Msg->mp2 ))
+            {
+                // for Korean
+                case VK_DBE_HANJA :
+                    bWinVKey = 0x19;
+                    break;
+
+                case VK_DBE_HANGEUL :
+                    bWinVKey = 0x15;
+                    break;
+
+                case VK_DBE_JAMO :
+                    bWinVKey = 0;
+                    break;
+
+                // for Japan
+                case VK_DBE_KATAKANA :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_HIRAGANA :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_SBCSCHAR :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_DBCSCHAR :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_SBCSDBCSCHAR :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_ROMAN :
+                    bWinVKey = 0;
+                    break;
+
+                // for PRC-Chinese
+                case VK_DBE_HANZI :
+                    bWinVKey = 0;
+                    break;
+
+                // for Taiwan
+                case VK_DBE_TSANGJYE :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_PHONETIC :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_CONV :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_NOCONV :
+                    bWinVKey = 0;
+                    break;
+
+                case VK_DBE_ALPHANUMERIC :
+                    switch( GetACP())
+                    {
+                        case 949 :  // Korea
+                        case 1361 :
+                            bWinVKey = 0x15;
+                            break;
+
+                        case 932 :  // Japan
+                        case 942 :
+                        case 943 :
+
+                        case 936 :  // PRC
+                        case 1381 :
+
+                        case 950 :  // Taiwan
+                        default :
+                            bWinVKey = 0;
+                    }
+                    break;
+
+                default :
                     KeyTranslatePMScanToWinVKey(usPMScanCode,
                                                 FALSE,
@@ -758,4 +848,6 @@
                                                 &wWinScan,
                                                 &fWinExtended);
+            }
+
             winMsg->wParam = bWinVKey;
         }
@@ -1079,4 +1171,216 @@
         break;
 
+    case WM_IMENOTIFY:
+        dprintf(("WM_IMENOTIFY"));
+
+        winMsg->wParam = 0;
+        winMsg->lParam = 0;
+
+        switch(( ULONG )os2Msg->mp1 )
+        {
+            case IMN_STARTCONVERSION :
+                winMsg->message = WM_IME_STARTCOMPOSITION_W;
+                break;
+
+            case IMN_ENDCONVERSION :
+                winMsg->message = WM_IME_ENDCOMPOSITION_W;
+                break;
+
+            case IMN_CONVERSIONFULL :
+                winMsg->message = WM_IME_COMPOSITIONFULL_W;
+                break;
+
+            case IMN_IMECHANGED :
+                winMsg->message = WM_IME_SELECT_W;
+                // todo
+                // fall through
+
+            default :
+                goto dummymessage;
+
+        }
+        break;
+
+    case WM_IMEREQUEST:
+        winMsg->wParam = 0;
+        winMsg->lParam = 0;
+
+        switch(( ULONG )os2Msg->mp1 )
+        {
+            case IMR_INSTANCEACTIVATE :
+            {
+                USHORT usIMR_IA = LOUSHORT( os2Msg->mp2 );
+
+                winMsg->message = WM_IME_SETCONTEXT_W;
+                winMsg->wParam = HIUSHORT( os2Msg->mp2 );
+
+                if( usIMR_IA & IMR_IA_STATUS )
+                    winMsg->lParam |= ISC_SHOWUIGUIDELINE_W;
+
+                if( usIMR_IA & IMR_IA_CONVERSION )
+                    winMsg->lParam |= ISC_SHOWUICOMPOSITIONWINDOW_W;
+
+                if( usIMR_IA & IMR_IA_CANDIDATE )
+                    winMsg->lParam |= ISC_SHOWUIALLCANDIDATEWINDOW_W;
+
+                if( usIMR_IA & IMR_IA_INFOMSG )
+                    winMsg->lParam |= 0; // todo
+
+                if( usIMR_IA & IMR_IA_REGWORD )
+                    winMsg->lParam |= 0; // todo
+                break;
+            }
+
+            case IMR_STATUS :
+                winMsg->message = WM_IME_NOTIFY_W;
+
+                switch(( ULONG )os2Msg->mp2 )
+                {
+                    case IMR_STATUS_SHOW :
+                        winMsg->wParam = IMN_OPENSTATUSWINDOW_W;
+                        break;
+
+                    case IMR_STATUS_HIDE :
+                        winMsg->wParam = IMN_CLOSESTATUSWINDOW_W;
+                        break;
+
+                    case IMR_STATUS_INPUTMODE : // IMN_SETOPENSTATUS followed by IMN_SETCONVERSIONMODE
+                        winMsg->wParam = IMN_SETOPENSTATUS_W;
+                        break;
+
+                    case IMR_STATUS_CONVERSIONMODE :
+                        winMsg->wParam = IMN_SETSENTENCEMODE_W;
+                        break;
+
+                    case IMR_STATUS_STATUSPOS :
+                        winMsg->wParam = IMN_SETSTATUSWINDOWPOS_W;
+                        break;
+
+                    case IMR_STATUS_STRING :
+                    case IMR_STATUS_STRINGATTR :
+                    case IMR_STATUS_CURSORPOS :
+                    case IMR_STATUS_CURSORATTR :
+
+                    default :
+                        // todo
+                        goto dummymessage;
+
+                }
+                break;
+
+            case IMR_CONVRESULT :
+            {
+                ULONG ulIMR = ( ULONG )os2Msg->mp2;
+
+                winMsg->message = WM_IME_COMPOSITION_W;
+                winMsg->wParam = 0; // todo : current DBCS char
+
+                if( ulIMR & IMR_CONV_CONVERSIONSTRING )
+                    winMsg->lParam |= GCS_COMPSTR_W;
+
+                if( ulIMR & IMR_CONV_CONVERSIONATTR )
+                    winMsg->lParam |= GCS_COMPATTR_W;
+
+                if( ulIMR & IMR_CONV_CONVERSIONCLAUSE )
+                    winMsg->lParam |= GCS_COMPCLAUSE_W;
+
+                if( ulIMR & IMR_CONV_READINGSTRING )
+                    winMsg->lParam |= GCS_COMPREADSTR_W;
+
+                if( ulIMR & IMR_CONV_READINGATTR )
+                    winMsg->lParam |= GCS_COMPREADATTR_W;
+
+                if( ulIMR & IMR_CONV_READINGCLAUSE )
+                    winMsg->lParam |= GCS_COMPREADCLAUSE_W;
+
+                if( ulIMR & IMR_CONV_CURSORPOS )
+                    winMsg->lParam |= GCS_CURSORPOS_W;
+
+                if( ulIMR & IMR_CONV_CURSORATTR )
+                    winMsg->lParam |= 0; // todo
+
+                if( ulIMR & IMR_CONV_CHANGESTART )
+                    winMsg->lParam |= GCS_DELTASTART_W;
+
+                if( ulIMR & IMR_CONV_INSERTCHAR )
+                    winMsg->lParam |= CS_INSERTCHAR_W;
+
+                if( ulIMR & IMR_CONV_NOMOVECARET )
+                    winMsg->lParam |= CS_NOMOVECARET_W;
+
+                if( ulIMR & IMR_CONV_CONVERSIONFONT )
+                    winMsg->lParam |= 0; // todo
+
+                if( ulIMR & IMR_CONV_CONVERSIONPOS )
+                    winMsg->lParam |= 0; // todo
+
+                if( ulIMR & IMR_RESULT_RESULTSTRING )
+                    winMsg->lParam = GCS_RESULTSTR_W; // clear all composition info
+
+                if( ulIMR & IMR_RESULT_RESULTATTR )
+                    winMsg->lParam |= 0; // todo
+
+                if( ulIMR & IMR_RESULT_RESULTCLAUSE )
+                    winMsg->lParam |= GCS_RESULTCLAUSE_W;
+
+                if( ulIMR & IMR_RESULT_READINGSTRING )
+                    winMsg->lParam |= GCS_RESULTREADSTR_W;
+
+                if( ulIMR & IMR_RESULT_READINGATTR )
+                    winMsg->lParam |= 0; // todo
+
+                if( ulIMR & IMR_RESULT_READINGCLAUSE )
+                    winMsg->lParam |= GCS_RESULTREADCLAUSE_W;
+
+                if( ulIMR && ( winMsg->lParam == 0 ))
+                    goto dummymessage;
+                break;
+            }
+
+            case IMR_CANDIDATE :
+                winMsg->message = WM_IME_NOTIFY_W;
+                switch(( ULONG )os2Msg->mp2 )
+                {
+                    case IMR_CANDIDATE_SHOW :
+                    case IMR_CANDIDATE_HIDE :
+                    case IMR_CANDIDATE_SELECT :
+                    case IMR_CANDIDATE_CHANGE :
+                    case IMR_CANDIDATE_CANDIDATEPOS :
+                    default :
+                        // todo
+                        goto dummymessage;
+                }
+                break;
+
+            case IMR_INFOMSG :
+                winMsg->message = WM_IME_NOTIFY_W;
+                winMsg->wParam = IMN_GUIDELINE_W;
+                break;
+
+            case IMR_REGWORD :
+                goto dummymessage;
+
+            case IMR_IMECHANGE :
+                winMsg->message = WM_IME_SELECT_W;
+                // todo
+                goto dummymessage;
+
+            case IMR_CONFIG :
+                // todo
+                goto dummymessage;
+
+            case IMR_DICTIONARY :
+                // todo
+                goto dummymessage;
+
+            case IMR_OTHERINFO :
+                // todo
+                goto dummymessage;
+        }
+        break;
+
+#if 0 // application cannot receive this message
+    case WM_IMECONTROL:
+#endif
     case WM_INITMENU:
     case WM_MENUSELECT:
Index: trunk/src/user32/pmwindow.cpp
===================================================================
--- trunk/src/user32/pmwindow.cpp	(revision 21307)
+++ trunk/src/user32/pmwindow.cpp	(revision 21308)
@@ -61,4 +61,8 @@
 #include "user32api.h"
 #include <kbdhook.h>
+#include <heapstring.h>
+
+#include <os2im.h>
+#include <im32.h>
 
 #define DBG_LOCALLOG    DBG_pmwindow
@@ -140,4 +144,6 @@
 #endif
 
+extern "C" ULONG OSLibImSetMsgQueueProperty( ULONG, ULONG );
+
 //******************************************************************************
 // Initialize PM; create hab, message queue and register special Win32 window classes
@@ -194,4 +200,8 @@
     BOOL rc = WinSetCp(hmq, GetDisplayCodepage());
     dprintf(("InitPM: WinSetCP was %sOK", rc ? "" : "not "));
+
+    /* IM instace is created per message queue, that is, thread */
+    if( IsDBCSEnv())
+        OSLibImSetMsgQueueProperty( hmq, MQP_INSTANCE_PERMQ );
 
     //CD polling window class
@@ -1004,4 +1014,27 @@
         dprintf(("OS2: %s %x %x %x", (msg == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL", win32wnd->getWindowHandle(), mp1, mp2));
         win32wnd->DispatchMsgA(pWinMsg);
+        break;
+
+    case WM_IMEREQUEST:
+    case WM_IMECONTROL:
+    case WM_IMENOTIFY:
+        if( pWinMsg->message )
+        {
+            win32wnd->DispatchMsgA( pWinMsg );
+
+            if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
+               ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
+            {
+                MSG m;
+
+                m.message = WM_IME_NOTIFY_W;
+                m.wParam = IMN_SETCONVERSIONMODE_W;
+                m.lParam = 0;
+
+                win32wnd->DispatchMsgA( &m );
+            }
+        }
+        else
+            goto RunDefWndProc;
         break;
 
@@ -2210,4 +2243,28 @@
         break;
 
+    case WM_IMEREQUEST:
+    case WM_IMECONTROL:
+    case WM_IMENOTIFY:
+        if( pWinMsg->message )
+        {
+            dprintf(("Frame window received IME message"));
+            win32wnd->DispatchMsgA( pWinMsg );
+
+            if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
+               ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
+            {
+                MSG m;
+
+                m.message = WM_IME_NOTIFY_W;
+                m.wParam = IMN_SETCONVERSIONMODE_W;
+                m.lParam = 0;
+
+                win32wnd->DispatchMsgA( &m );
+            }
+        }
+        else
+            goto RunDefWndProc;
+        break;
+
 #ifdef DEBUG
     case WM_DDE_INITIATE:
Index: trunk/src/version/dbgwrap.cpp
===================================================================
--- trunk/src/version/dbgwrap.cpp	(revision 21307)
+++ trunk/src/version/dbgwrap.cpp	(revision 21308)
@@ -15,4 +15,7 @@
 #include <heapstring.h>
 #include <version.h>
+
+#define DBG_LOCALLOG    DBG_trace
+#include <dbglocal.h>
 
 #define DBGWRAP_MODULE "VERSION"
Index: trunk/src/win16ldr/odin.c
===================================================================
--- trunk/src/win16ldr/odin.c	(revision 21307)
+++ trunk/src/win16ldr/odin.c	(revision 21308)
@@ -1,7 +1,8 @@
-#ifndef MSC6
+#ifdef WATCOMC
 #include <windows.h>
 #else
 #include "msc60win.h"
 #endif
+//#include <ddeml.h>
 #include <stdlib.h>
 #include <string.h>
@@ -19,4 +20,15 @@
 HANDLE hModule = 0;
 
+typedef void (FAR * PASCAL FUNC_SetPELdr)(LPCSTR);
+
+#ifdef DDE_COMM
+HDDEDATA CALLBACK MyDdeCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2);
+
+DWORD idInst = 0;
+HSZ   hszServer = 0, hszTopic = 0;
+
+#define MSG_DDE_WILDCONNECT	WM_USER+1
+#define MSG_DDE_CONNECT		WM_USER+2
+#endif
 
 //*****************************************************************************************
@@ -25,4 +37,40 @@
 {
     MSG msg;
+	FUNC_SetPELdr pfnSetPELdr;
+	char  szPEPath[260];
+	LPSTR tmp;
+			               
+	hDll = LoadLibrary("odindll.dll");
+	if(hDll == 0) {
+		return 0;
+	}
+
+	pfnSetPELdr = (FUNC_SetPELdr)GetProcAddress(hDll, "SETPELDR");
+	if(pfnSetPELdr == NULL) {
+		return 0;
+	}                 
+	//check if the caller specified the path of the PE loader; if so, pass
+	//it on to odindll
+    tmp = strstr(lpCmdLine, "/PELDR=[");
+    if(tmp) {
+    	tmp += 8;	//skip /peldr=[
+    	strcpy(szPEPath, tmp);
+    	tmp = szPEPath;
+    	
+    	while(*tmp != ']' && *tmp != 0) tmp++;
+    	
+    	if(*tmp == ']') {
+    		*tmp = 0;
+    		pfnSetPELdr(szPEPath);
+    	}               
+    	
+    	//now skip this parameter                
+    	tmp = strstr(lpCmdLine, "/PELDR=[");
+    	while(*tmp != ']' && *tmp != 0) tmp++;     
+    	if(*tmp == ']') {
+    		tmp++;
+    	}
+		lpCmdLine = tmp;    	
+    }
 
     if (!hPrevInstance)
@@ -32,4 +80,21 @@
     if (!InitInstance(hInstance, nCmdShow))
         return (FALSE);
+
+#ifdef DDE_COMM
+    if(DdeInitialize(&idInst, MyDdeCallback, APPCLASS_STANDARD, 0) != DMLERR_NO_ERROR) {
+        return FALSE;
+    }
+    hszServer = DdeCreateStringHandle(idInst, "Win16OdinServer", CP_WINANSI);
+    if(hszServer == 0) {
+        return FALSE;
+    }
+    hszTopic = DdeCreateStringHandle(idInst, "Win16Broadcast", CP_WINANSI);
+    if(hszTopic == 0) {
+        return FALSE;
+    }
+    if(DdeNameService(idInst, hszServer, 0, DNS_REGISTER) == 0) {
+        return FALSE;
+    }
+#endif
 
     while(*lpCmdLine == ' ') lpCmdLine++;
@@ -48,8 +113,14 @@
 		
 		sprintf(errormsg, "WinExec %s failed with error %d", lpCmdLine, hModule);
-		MessageBox(hwnd, errormsg, "Ïnternal Error", MB_ICONHAND);
+		MessageBox(hwnd, errormsg, "Internal Error", MB_ICONHAND);
 		DestroyWindow(hwnd);
 	}
 		
+#ifdef DDE_COMM
+    DdeNameService(idInst, hszServer, 0, DNS_UNREGISTER);		
+    DdeFreeStringHandle(idInst, hszServer);
+    DdeFreeStringHandle(idInst, hszTopic);
+    DdeUninitialize(idInst);
+#endif
 	FreeLibrary(hDll);
     return (msg.wParam);
@@ -60,9 +131,4 @@
 {
 	WNDCLASS wc;
-	
-	hDll = LoadLibrary("odindll.dll");
-	if(hDll == 0) {
-		return 0;
-	}
 	
     wc.style = NULL;
@@ -88,5 +154,9 @@
         "Win16OdinClass",
         "Odin Win16 Program Launcher",
+#if 1 
+		WS_POPUP,
+#else        
         WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+#endif        
         CW_USEDEFAULT,
         CW_USEDEFAULT,
@@ -127,4 +197,11 @@
             break;
 
+#ifdef DDE_COMM
+        case MSG_DDE_WILDCONNECT:
+            break;
+        case MSG_DDE_CONNECT:
+            MessageBox(0, "MyDdeCallback", "WILDCONNECT", MB_OK);
+            break;
+#endif
         default:
             return (DefWindowProc(hWnd, message, wParam, lParam));
@@ -132,4 +209,62 @@
     return (NULL);
 }
-//*****************************************************************************************
-//*****************************************************************************************
+#ifdef DDE_COMM
+//*****************************************************************************************
+//*****************************************************************************************
+HDDEDATA CALLBACK MyDdeCallback(UINT wType, UINT wFmt, HCONV hConv, 
+                                HSZ hszTopic,  HSZ hszItem, 
+                                HDDEDATA hData, DWORD dwData1, DWORD dwData2)
+{
+//    WORD i, j;
+//    WORD cItems, iFmt;
+//    HDDEDATA hDataRet;
+
+    char msg[128];
+
+////     MessageBeep(500);
+//    sprintf(msg, "type=%x format=%x %x %x %x %x %x %x", wType, wFmt, hConv, hszTopic, hszItem, hData, dwData1, dwData2);
+//    MessageBox(0, "MyDdeCallback", "test", MB_OK);
+
+    if(wType == XTYP_EXECUTE && wFmt == CF_TEXT) 
+    {
+        char szExec[64];
+
+        DdeGetData(hData, (LPBYTE)szExec, 64, 0);
+        szExec[63] = 0;
+        MessageBox(0, "MyDdeCallback", szExec, MB_OK);
+        return (HDDEDATA)TRUE;
+    }
+    /*
+     * Process wild initiates here
+     */
+    if (wType == XTYP_WILDCONNECT) {
+        HSZ ahsz[(1 + 1) * 2];
+        /*
+         * He wants a hsz list of all our available app/topic pairs
+         * that conform to hszTopic and hszItem(App).
+         */
+
+//        MessageBox(0, "MyDdeCallback", "WILDCONNECT", MB_OK);
+
+//        if (!ValidateContext((PCONVCONTEXT)lData1)) {
+//            return(FALSE);
+//        }
+
+        if (hszItem != hszServer && hszItem != 0) {
+            // we only support the hszAppName service
+            return(0);
+        }
+
+        ahsz[0] = hszServer;
+        ahsz[1] = hszTopic;
+        // cap off the list with 0s
+        ahsz[2] = ahsz[3] = 0L;
+
+        // send it back
+        return(DdeCreateDataHandle(idInst, (LPBYTE)&ahsz[0], sizeof(HSZ) * 4, 0L, 0, wFmt, 0));
+    }
+    return 0;
+}
+//*****************************************************************************************
+//*****************************************************************************************
+#endif
Index: trunk/src/win16ldr/odindll.c
===================================================================
--- trunk/src/win16ldr/odindll.c	(revision 21307)
+++ trunk/src/win16ldr/odindll.c	(revision 21308)
@@ -1,8 +1,6 @@
-#ifndef MSC6
 #include <windows.h>
-#else
-#include "msc60win.h"
-#endif
 #include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 #include "peexe.h"
 
@@ -10,23 +8,38 @@
 UINT FAR _loadds PASCAL MyWinExec(LPCSTR lpszCmdLine, UINT fuShowCmd);
 
+BOOL    FAR _loadds PASCAL MyPostMessage(HWND, UINT, WPARAM, LPARAM);
+LRESULT FAR _loadds PASCAL MySendMessage(HWND, UINT, WPARAM, LPARAM);
+
 BOOL GetPEFileHeader (LPVOID lpFile, PIMAGE_FILE_HEADER pHeader);
 BOOL GetPEOptionalHeader (LPVOID lpFile, PIMAGE_OPTIONAL_HEADER pHeader);
 
-#if defined(__WATCOMC__)
-typedef DWORD (FAR * WINAPI * FUNC_GetVersion)(void);
-typedef UINT  (FAR * WINAPI * FUNC_WinExec)(LPCSTR, UINT);
-#else
-typedef DWORD (FAR * WINAPI FUNC_GetVersion)(void);
-typedef UINT  (FAR * WINAPI FUNC_WinExec)(LPCSTR, UINT);
-#endif
+typedef DWORD (FAR * PASCAL FUNC_GetVersion)(void);
+typedef UINT  (FAR * PASCAL FUNC_WinExec)(LPCSTR, UINT);
+#ifdef PATCH_POSTSENDMSG
+typedef BOOL    (FAR * PASCAL FUNC_PostMessage)(HWND, UINT, WPARAM, LPARAM);
+typedef LRESULT (FAR * PASCAL FUNC_SendMessage)(HWND, UINT, WPARAM, LPARAM);
+#endif
+
+BYTE  oldcodeEXEC;
+DWORD olddataEXEC;
+UINT  selEXEC;
+BYTE FAR *jumpEXEC;
 
 BYTE  oldcodeVER;
 DWORD olddataVER;
 UINT  selVER;
-BYTE  oldcodeEXEC;
-DWORD olddataEXEC;
-UINT  selEXEC;
 BYTE FAR *jumpVER;
-BYTE FAR *jumpEXEC;
+
+#ifdef PATCH_POSTSENDMSG
+BYTE  oldcodeSEND;
+DWORD olddataSEND;
+UINT  selSEND;
+BYTE FAR *jumpSEND;
+
+BYTE  oldcodePOST;
+DWORD olddataPOST;
+UINT  selPOST;
+BYTE FAR *jumpPOST;
+#endif
 
 BOOL fUnloaded = FALSE;
@@ -35,37 +48,68 @@
 char szPEPath[256] = {0};
 
+FUNC_GetVersion orggetver   = NULL;
+FUNC_WinExec    orgwinexec  = NULL;
+#ifdef PATCH_POSTSENDMSG
+FUNC_SendMessage orgsendmsg = NULL;
+FUNC_PostMessage orgpostmsg = NULL;
+#endif
+
 //*****************************************************************************************
 //*****************************************************************************************
 int FAR _loadds CALLBACK LibMain(HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine)
 {
-	FUNC_GetVersion getver;
-	FUNC_WinExec winexec;
 	DWORD FAR *addr;
 	
-    if (fInit == FALSE) {
+    if(fInit == FALSE) 
+    {
     	fInit = TRUE;
 
-		GetProfileString("Odin", "PEPath", "PE.EXE", szPEPath, sizeof(szPEPath));
-		getver      = (FUNC_GetVersion)&GetVersion;
+		GetProfileString("PELDR", "LdrPath", "PE.EXE", szPEPath, sizeof(szPEPath));
+		
+		orggetver   = (FUNC_GetVersion)GetVersion;
 		selVER      = AllocSelector(0);
-		PrestoChangoSelector(SELECTOROF(getver), selVER);
-
-		jumpVER     = MAKELP(selVER, OFFSETOF(getver));
+		PrestoChangoSelector(SELECTOROF(orggetver), selVER);
+
+		jumpVER     = MAKELP(selVER, OFFSETOF(orggetver));
 		addr        = (DWORD FAR *)(jumpVER+1);
 		oldcodeVER  = *jumpVER;
 		olddataVER  = *addr;
 		*jumpVER    = 0xEA;	//jmp
-		*addr       = (DWORD)&MyGetVersion;
-
-		winexec     = (FUNC_WinExec)&WinExec;	
+		*addr       = (DWORD)MyGetVersion;
+
+		orgwinexec  = (FUNC_WinExec)WinExec;	
 		selEXEC     = AllocSelector(0);
-		PrestoChangoSelector(SELECTOROF(winexec), selEXEC);
-
-		jumpEXEC    = MAKELP(selEXEC, OFFSETOF(winexec));
+		PrestoChangoSelector(SELECTOROF(orgwinexec), selEXEC);
+
+		jumpEXEC    = MAKELP(selEXEC, OFFSETOF(orgwinexec));
 		addr        = (DWORD FAR *)(jumpEXEC+1);
 		oldcodeEXEC = *jumpEXEC;
 		olddataEXEC = *addr;
 		*jumpEXEC   = 0xEA;	//jmp
-		*addr       = (DWORD)&MyWinExec;
+		*addr       = (DWORD)MyWinExec;
+
+#ifdef PATCH_POSTSENDMSG
+		orgsendmsg  = (FUNC_SendMessage)SendMessage;	
+		selSEND     = AllocSelector(0);
+		PrestoChangoSelector(SELECTOROF(orgsendmsg), selSEND);
+
+		jumpSEND    = MAKELP(selSEND, OFFSETOF(orgsendmsg));
+		addr        = (DWORD FAR *)(jumpSEND+1);
+		oldcodeSEND = *jumpSEND;
+		olddataSEND = *addr;
+		*jumpSEND   = 0xEA;	//jmp
+		*addr       = (DWORD)MySendMessage;
+
+		orgpostmsg  = (FUNC_PostMessage)PostMessage;	
+		selPOST     = AllocSelector(0);
+		PrestoChangoSelector(SELECTOROF(orgpostmsg), selPOST);
+
+		jumpPOST    = MAKELP(selPOST, OFFSETOF(orgpostmsg));
+		addr        = (DWORD FAR *)(jumpPOST+1);
+		oldcodePOST = *jumpPOST;
+		olddataPOST = *addr;
+		*jumpPOST   = 0xEA;	//jmp
+		*addr       = (DWORD)MyPostMessage;
+#endif		
     }
     return 1;
@@ -89,4 +133,14 @@
 	    *jumpEXEC = oldcodeEXEC;
 	    *addr     = olddataEXEC;
+
+#ifdef PATCH_POSTSENDMSG
+    	addr        = (DWORD FAR *)(jumpSEND + 1);
+    	*jumpSEND   = oldcodeSEND;
+    	*addr       = olddataSEND;
+                            
+        addr        = (DWORD FAR *)(jumpPOST + 1);
+        *jumpPOST   = oldcodePOST;
+        *addr       = olddataPOST;
+#endif        
     }
   	return 1;
@@ -97,4 +151,62 @@
 {
  	return 0x00005F0C;
+}
+#ifdef PATCH_POSTSENDMSG
+//*****************************************************************************************
+//*****************************************************************************************
+BOOL FAR _loadds PASCAL MyPostMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+    DWORD FAR *addr;
+    BOOL       ret;
+    char       buffer[64];
+
+    addr        = (DWORD FAR *)(jumpPOST + 1);
+    *jumpPOST   = oldcodePOST;
+    *addr       = olddataPOST;
+
+#ifdef DEBUG
+    if(hwnd == HWND_BROADCAST) {
+        sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
+        MessageBox(0, "PostMessage", buffer, MB_OK);
+    }
+#endif
+    ret = PostMessage(hwnd, Msg, wParam, lParam);
+
+    *jumpPOST   = 0xEA;	//jmp
+    *addr       = (DWORD)&MyPostMessage;
+
+    return ret;
+}
+//*****************************************************************************************
+//*****************************************************************************************
+LRESULT FAR _loadds PASCAL MySendMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+    DWORD FAR *addr;
+    BOOL       ret;
+    char       buffer[64];
+
+    addr        = (DWORD FAR *)(jumpSEND + 1);
+    *jumpSEND   = oldcodeSEND;
+    *addr       = olddataSEND;
+
+#ifdef DEBUG
+    if(hwnd == HWND_BROADCAST) {
+        sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
+        MessageBox(0, "SendMessage", buffer, MB_OK);
+    }
+#endif
+    ret = SendMessage(hwnd, Msg, wParam, lParam);
+
+    *jumpSEND   = 0xEA;	//jmp
+    *addr       = (DWORD)&MySendMessage;
+
+    return ret;
+}                       
+#endif 
+//*****************************************************************************************
+//*****************************************************************************************
+void FAR _loadds PASCAL SetPELdr(LPCSTR lpszPELdr)
+{                        
+	strcpy(szPEPath, lpszPELdr);
 }
 //*****************************************************************************************
@@ -116,4 +228,6 @@
 	BOOL fFail = TRUE;
 
+    if(szPEPath[0] == 0) goto calloldfunc;
+    
 	of.cBytes = sizeof(OFSTRUCT);
 	
@@ -124,10 +238,12 @@
 	strcpy(cmdline, lpszCmdLine);
 	
+	//isolate path of executable	
 	while(*cmdline == ' ') cmdline++;
 	tmp = cmdline;
 	while(*tmp != ' ' && *tmp != 0) tmp++;
-	tmp++;
 	*tmp = 0;
 	
+	//open it to check the executable type; we only care about PE (win32) executables 
+	//we'll let the original WinExec function handle everything else
 	hFile = OpenFile(cmdline, &of, OF_READ);
   	bytesRead = _lread(hFile, &doshdr, sizeof(doshdr));
@@ -163,4 +279,5 @@
   	}
 
+    //Ok, it's a PE executable. Use the PE loader to launch it
 	tmp = cmdline;
 	hMem4 = hMem1;
@@ -194,12 +311,16 @@
 		_lclose(hFile);
 
+    //restore original WinExec entrypoint
     addr      = (DWORD FAR *)(jumpEXEC + 1);
     *jumpEXEC = oldcodeEXEC;
     *addr     = olddataEXEC;
 	
+	//and call it	
 	if(fFail) {
+		//non-PE executable
 		 ret = WinExec(lpszCmdLine, fuShowCmd);
 	}
 	else {
+		//PE executable
 		ret = WinExec(cmdline, fuShowCmd);
 		if(ret >= 32) {
@@ -216,4 +337,5 @@
 	}
 	
+	//put back our WinExec override	                   
 	*jumpEXEC   = 0xEA;	//jmp
 	*addr       = (DWORD)&MyWinExec;
Index: trunk/src/win16ldr/odindll.def
===================================================================
--- trunk/src/win16ldr/odindll.def	(revision 21307)
+++ trunk/src/win16ldr/odindll.def	(revision 21308)
@@ -17,2 +17,3 @@
 	MYGETVERSION	@1
 	MYWINEXEC		@2
+	SETPELDR        @3
Index: trunk/src/ws2_32/ws2_32.def
===================================================================
--- trunk/src/ws2_32/ws2_32.def	(revision 21307)
+++ trunk/src/ws2_32/ws2_32.def	(revision 21308)
@@ -16,59 +16,29 @@
 ; WS2HELP.dll
 
-  accept                                           = WSOCK32.1
-  bind                                             = WSOCK32.2
-  closesocket                                      = WSOCK32.3
-  connect                                          = WSOCK32.4
-  gethostbyaddr                                    = WSOCK32.51
-  gethostbyname                                    = WSOCK32.52
-  gethostname                                      = WSOCK32.57
-  getpeername                                      = WSOCK32.5
-  getprotobyname                                   = WSOCK32.53
-  getprotobynumber                                 = WSOCK32.54
-  getservbyname                                    = WSOCK32.55
-  getservbyport                                    = WSOCK32.56
-  getsockname                                      = WSOCK32.6
-  htonl                                            = WSOCK32.8
-  htons                                            = WSOCK32.9
-  inet_addr                                        = WSOCK32.10
-  inet_ntoa                                        = WSOCK32.11
-  ioctlsocket                                      = WSOCK32.12
-  listen                                           = WSOCK32.13
-  ntohl                                            = WSOCK32.14
-  ntohs                                            = WSOCK32.15
-  recv                                             = WSOCK32.16
-  recvfrom                                         = WSOCK32.17
-  select                                           = WSOCK32.18
-  send                                             = WSOCK32.19
-  sendto                                           = WSOCK32.20
-  shutdown                                         = WSOCK32.22
-  socket                                           = WSOCK32.23
-  WSAEventSelect                                   = WSOCK32.3001
-  WSAEnumNetworkEvents                             = WSOCK32.3002
          
 EXPORTS
-  accept                                           @1
-  bind                                             @2
-  closesocket                                      @3
-  connect                                          @4
-  getpeername                                      @5
-  getsockname                                      @6
+   accept                      = _accept@12                            @1
+   bind                        = _bind@12                              @2
+   closesocket                 = _closesocket@4                        @3
+   connect                     = _connect@12                           @4
+   getpeername                 = _getpeername@12                       @5
+   getsockname                 = _getsockname@12                       @6
   getsockopt = _WS2getsockopt@20                   @7
-  htonl                                            @8
-  htons                                            @9
-  ioctlsocket                                      @10
-  inet_addr                                        @11
-  inet_ntoa                                        @12
-  listen                                           @13
-  ntohl                                            @14
-  ntohs                                            @15
-  recv                                             @16
-  recvfrom                                         @17
-  select                                           @18
-  send                                             @19
-  sendto                                           @20
+   htonl                       = _htonl@4                              @8
+   htons                       = _htons@4                              @9
+   ioctlsocket                 = _ioctlsocket@12                       @10
+   inet_addr                   = _inet_addr@4                          @11
+   inet_ntoa                   = _inet_ntoa@4                          @12
+   listen                      = _listen@8                             @13
+   ntohl                       = _ntohl@4                              @14
+   ntohs                       = _ntohs@4                              @15
+   recv                        = _recv@16                              @16
+   recvfrom                    = _recvfrom@24                          @17
+   select                      = _select@20                            @18
+   send                        = _send@16                              @19
+   sendto                      = _sendto@24                            @20
   setsockopt = _WS2setsockopt@20                   @21
-  shutdown                                         @22
-  socket                                           @23
+   shutdown                    = _shutdown@8                           @22
+   socket                      = _socket@12                            @23
 
 ; WSApSetPostRoutine                               @24
@@ -85,8 +55,9 @@
 ; WSAEnumNameSpaceProvidersA                       @34
 ; WSAEnumNameSpaceProvidersW                       @35
-  WSAEnumNetworkEvents                             @36
+  WSAEnumNetworkEvents = _WSAEnumNetworkEvents@12  @36
   WSAEnumProtocolsA = _WSAEnumProtocolsA@12        @37
   WSAEnumProtocolsW = _WSAEnumProtocolsW@12        @38
-  WSAEventSelect                                   @39
+  WSAEventSelect    = _WSAEventSelect@12           @39
+
 ; WSAGetOverlappedResult                           @40
 ; WSAGetQOSByName                                  @41
@@ -101,11 +72,11 @@
   WSAIoctl                    = _WSAIoctl@36       @50
 
-  gethostbyaddr                                    @51
-  gethostbyname                                    @52
-  gethostname                                      @57
-  getprotobyname                                   @53
-  getprotobynumber                                 @54
-  getservbyname                                    @55
-  getservbyport                                    @56
+  gethostbyaddr               = _gethostbyaddr@12                     @51
+  gethostbyname               = _gethostbyname@4                      @52
+  gethostname                 = _gethostname@8                        @57
+  getprotobyname              = _getprotobyname@4                     @53
+  getprotobynumber            = _getprotobynumber@4                   @54
+  getservbyname               = _getservbyname@8                      @55
+  getservbyport               = _getservbyport@8                      @56
 
 ; WSAJoinLeaf                                      @58
Index: trunk/src/wsock32/makefile
===================================================================
--- trunk/src/wsock32/makefile	(revision 21307)
+++ trunk/src/wsock32/makefile	(revision 21308)
@@ -46,5 +46,4 @@
 $(ODIN32_LIB)/user32.lib \
 $(ODIN32_LIB)/libwrap.lib \
-$(ODIN32_LIB)/iphlpapi.lib \
 $(ODIN32_LIB)/$(ODINCRT).lib \
 so32dll.lib \
Index: trunk/src/wsock32/wsock32.cpp
===================================================================
--- trunk/src/wsock32/wsock32.cpp	(revision 21307)
+++ trunk/src/wsock32/wsock32.cpp	(revision 21308)
@@ -55,5 +55,9 @@
 #include <winuser32.h>
 #include <wprocess.h>
-#include <misc.h>
+#include <dbglog.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
 
 #include "wsock32.h"
@@ -212,4 +216,7 @@
             strcpy(msg, "WSAEHOSTUNREACH");
             break;
+        case WSAETIMEDOUT:
+            strcpy(msg, "WSAETIMEDOUT");
+            break;
         default:
             strcpy(msg, "unknown");
@@ -663,6 +670,16 @@
 
    if(ret == SOCKET_ERROR) {
- 	WSASetLastError(wsaErrno());
-        return SOCKET_ERROR;
+        if(wsaErrno() == WSAEWOULDBLOCK) {
+            struct timeval tv;
+            int optlen = sizeof(tv);
+            ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen);
+            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
+                  dprintf(("WSAEWOULDBLOCK: recv timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
+                  WSASetLastError(WSAETIMEDOUT);
+            }
+            else  WSASetLastError(WSAEWOULDBLOCK);
+            ret = SOCKET_ERROR;
+        }
+        else WSASetLastError(wsaErrno());
    }
    else 
@@ -684,5 +701,5 @@
         else
 	if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
-		dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
+		dprintf(("recv returned 0, but socket is still connected -> return WSAEWOULDBLOCK"));
  		WSASetLastError(WSAEWOULDBLOCK);
 		return SOCKET_ERROR;
@@ -699,5 +716,5 @@
    }
 
-   //Reset FD_READ event flagfor  WSAAsyncSelect thread if one was created for this socket
+   //Reset FD_READ event flag for WSAAsyncSelect thread if one was created for this socket
    EnableAsyncEvent(s, FD_READ);
    return ret;
@@ -732,5 +749,16 @@
 
    if(ret == SOCKET_ERROR) {
- 	WSASetLastError(wsaErrno());
+        if(wsaErrno() == WSAEWOULDBLOCK) {
+            struct timeval tv;
+            int optlen = sizeof(tv);
+            ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen);
+            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
+                  dprintf(("WSAEWOULDBLOCK: recvfrom timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
+                  WSASetLastError(WSAETIMEDOUT);
+            }
+            else  WSASetLastError(WSAEWOULDBLOCK);
+            ret = SOCKET_ERROR;
+        }
+ 	else WSASetLastError(wsaErrno());
    }
    else {
@@ -789,5 +817,16 @@
 
    if(ret == SOCKET_ERROR) {
- 	WSASetLastError(wsaErrno());
+        if(wsaErrno() == WSAEWOULDBLOCK) {
+            struct timeval tv;
+            int optlen = sizeof(tv);
+            ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen);
+            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
+                  dprintf(("WSAEWOULDBLOCK: send timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
+                  WSASetLastError(WSAETIMEDOUT);
+            }
+            else  WSASetLastError(WSAEWOULDBLOCK);
+            ret = SOCKET_ERROR;
+        }
+ 	else WSASetLastError(wsaErrno());
    }
    else WSASetLastError(NO_ERROR);
@@ -844,5 +883,16 @@
 
    if(ret == SOCKET_ERROR) {
- 	WSASetLastError(wsaErrno());
+        if(wsaErrno() == WSAEWOULDBLOCK) {
+            struct timeval tv;
+            int optlen = sizeof(tv);
+            ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen);
+            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
+                  dprintf(("WSAEWOULDBLOCK: sendto timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
+                  WSASetLastError(WSAETIMEDOUT);
+            }
+            else  WSASetLastError(WSAEWOULDBLOCK);
+            ret = SOCKET_ERROR;
+        }
+ 	else WSASetLastError(wsaErrno());
    }
    else WSASetLastError(NO_ERROR);
@@ -906,11 +956,11 @@
 
 	sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
-	if(readfds) {
+	if(readfds && nrread) {
 		memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
 	}
-	if(writefds) {
+	if(writefds && nrwrite) {
 		memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
 	}
-	if(exceptfds) {
+	if(exceptfds && nrexcept) {
 		memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
 	}
@@ -940,5 +990,6 @@
                		for(i=0;i<nrread;i++) {
                   		if(socktmp[i] != -1) {
-	                     		readfds->fd_array[i] = socktmp[i];
+	                     		readfds->fd_array[j] = socktmp[i];
+	                     		dprintf(("Socket %d read pending", socktmp[i]));
 					j++;
 				}
@@ -952,5 +1003,6 @@
                		for(i=0;i<nrwrite;i++) {
                   		if(socktmp[i] != -1) {
-	                     		writefds->fd_array[i] = socktmp[i];
+	                     		writefds->fd_array[j] = socktmp[i];
+	                     		dprintf(("Socket %d write pending", socktmp[i]));
 					j++;
 				}
@@ -963,5 +1015,5 @@
                		for(i=0;i<nrexcept;i++) {
                   		if(socktmp[i] != -1) {
-	                     		exceptfds->fd_array[i] = socktmp[i];
+	                     		exceptfds->fd_array[j] = socktmp[i];
 					j++;
 				}
@@ -984,4 +1036,51 @@
    return ret;
 }
+#ifdef DEBUG_LOGGING
+//******************************************************************************
+//******************************************************************************
+char *debugsockopt(int optname)
+{
+    switch(optname) {
+    case SO_DONTLINGER:
+         return "SO_DONTLINGER";
+    case SO_LINGER:
+         return "SO_LINGER";
+    case SO_REUSEADDR:
+         return "SO_REUSEADDR";
+    case SO_SNDTIMEO:
+         return "SO_SNDTIMEO";
+    case SO_RCVTIMEO:
+         return "SO_RCVTIMEO";
+    case SO_SNDBUF:
+         return "SO_SNDBUF";
+    case SO_RCVBUF:
+         return "SO_RCVBUF";
+    case SO_BROADCAST:
+         return "SO_BROADCAST";
+    case SO_DEBUG:
+         return "SO_DEBUG";
+    case SO_KEEPALIVE:
+         return "SO_KEEPALIVE";
+    case SO_DONTROUTE:
+         return "SO_DONTROUTE";
+    case SO_OOBINLINE:
+         return "SO_OOBINLINE";
+    case SO_TYPE:
+         return "SO_TYPE";
+    case SO_ERROR:
+         return "SO_ERROR";
+    case SO_SNDLOWAT:
+         return "SO_SNDLOWAT";
+    case SO_RCVLOWAT:
+         return "SO_RCVLOWAT";
+    case SO_USELOOPBACK:
+         return "SO_USELOOPBACK";
+    case SO_ACCEPTCONN:
+         return "SO_ACCEPTCONN";
+    default:
+        return "unknown option";
+    }
+}
+#endif
 //******************************************************************************
 //******************************************************************************
@@ -1064,10 +1163,40 @@
         case SO_SNDTIMEO:
         case SO_RCVTIMEO:
+        {
+            	if(optlen < (int)sizeof(int))
+                {
+                        dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small"));
+               		WSASetLastError(WSAEFAULT);
+               		return SOCKET_ERROR;
+            	}
           // convert "int" to "struct timeval"
           struct timeval tv;
-          tv.tv_sec = *optval / 1000;
-          tv.tv_usec = (*optval % 1000) * 1000;
+                tv.tv_sec = (*(int *)optval) / 1000;
+                tv.tv_usec = ((*(int *)optval) % 1000) * 1000;
+                if(optname == SO_SNDTIMEO) {
+                     dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
+                }
+                else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
+
           ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) );
           break;
+        }
+
+	case SO_REUSEADDR:
+            	if(optlen < (int)sizeof(int)) {
+                        dprintf(("SO_REUSEADDR, optlen too small"));
+               		WSASetLastError(WSAEFAULT);
+               		return SOCKET_ERROR;
+            	}
+                dprintf(("option SO_REUSEADDR value %d", *(int *)optval));
+                ret = setsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen);
+                if(ret) {
+                    dprintf(("setsockopt SO_REUSEADDR failed!!"));
+                }
+                ret = setsockopt(s, level, SO_REUSEPORT_OS2, (char *)optval, optlen);
+                if(ret) {
+                    dprintf(("setsockopt SO_REUSEPORT failed!!"));
+                }
+		break;
 
 	case SO_BROADCAST:
@@ -1076,10 +1205,15 @@
 	case SO_DONTROUTE:
         case SO_OOBINLINE:
-	case SO_REUSEADDR:
+        case SO_ERROR:
+        case SO_SNDLOWAT:
+        case SO_RCVLOWAT:
+        case SO_ACCEPTCONN:
+        case SO_USELOOPBACK:
             	if(optlen < (int)sizeof(int)) {
-                        dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
+                        dprintf(("%s optlen too small", debugsockopt(optname)));
                		WSASetLastError(WSAEFAULT);
                		return SOCKET_ERROR;
             	}
+                dprintf(("option %s = %x", debugsockopt(optname), *(int *)optval));
                 ret = setsockopt(s, level, optname, (char *)optval, optlen);
 		break;
@@ -1153,5 +1287,5 @@
            {
                u_int flLoop;
-               if (optlen < sizeof(u_char))
+               if (optlen < sizeof(u_int))
                {
                    dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
@@ -1161,5 +1295,5 @@
                flLoop = (*optval == 0) ? 0 : 1;
                dprintf(("IP_MULTICAST_LOOP %d", *optval));
-               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
+               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, sizeof(u_char));
                break;
            }
@@ -1167,5 +1301,5 @@
            case IP_MULTICAST_TTL:
            case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
-               if (optlen < sizeof(u_char))
+               if (optlen < sizeof(u_int))
                {
                    dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
@@ -1173,5 +1307,6 @@
                    return SOCKET_ERROR;
                }
-               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
+               dprintf(("IP_MULTICAST_TTL %d", *optval));
+               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, sizeof(u_char));
                break;
 
@@ -1210,4 +1345,11 @@
                dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", val));
                ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&val, optlen);
+               break;
+
+           case IP_DONTFRAGMENT:
+           case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2):
+               //MSDN says these options are silently ignored
+               dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored"));
+               ret = 0;
                break;
 
@@ -1269,4 +1411,37 @@
 		break;
 
+	case SO_REUSEADDR:
+            	if(optlen == NULL || *optlen < sizeof(int)) {
+               		WSASetLastError(WSAEFAULT);
+               		return SOCKET_ERROR;
+            	}
+                ret = getsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen);
+                dprintf(("getsockopt SO_REUSEADDR returned %d", *(int *)optval, optname));
+		break;
+		break;
+
+        case SO_SNDTIMEO:
+        case SO_RCVTIMEO:
+        {
+            	if(optlen == NULL || *optlen < sizeof(int))
+                {
+                        dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small"));
+               		WSASetLastError(WSAEFAULT);
+               		return SOCKET_ERROR;
+            	}
+                struct timeval tv;
+                int size = sizeof(tv);
+                ret = getsockopt(s, level, optname, (char *)&tv, &size );
+
+                // convert "struct timeval" to "int"
+                *(int *)optval = (tv.tv_sec * 1000) + tv.tv_usec/1000;
+                if(optname == SO_SNDTIMEO) {
+                     dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
+                }
+                else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
+
+                break;
+        }
+
 	case SO_SNDBUF:
 	case SO_RCVBUF:
@@ -1276,6 +1451,9 @@
 	case SO_DONTROUTE:
 	case SO_OOBINLINE:
-	case SO_REUSEADDR:
 	case SO_TYPE:
+        case SO_ERROR:
+        case SO_SNDLOWAT:
+        case SO_RCVLOWAT:
+        case SO_USELOOPBACK:
             	if(optlen == NULL || *optlen < sizeof(int)) {
                		WSASetLastError(WSAEFAULT);
@@ -1283,5 +1461,7 @@
             	}
                 ret = getsockopt(s, level, optname, (char *)optval, optlen);
+                dprintf(("getsockopt %s returned %d", debugsockopt(optname), *(int *)optval));
 		break;
+
 	case SO_ACCEPTCONN:
             	if(optlen == NULL || *optlen < sizeof(int)) {
@@ -1294,4 +1474,5 @@
                    	*(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
                    	*optlen = sizeof(BOOL);
+                        dprintf(("SO_ACCEPTCONN returned %d", *(BOOL *)optval));
                 }
 		break;
@@ -1357,8 +1538,9 @@
                break;
 
+           case IP_MULTICAST_LOOP_WS2: //for buggy applications that intended to call ws_32.getsockopt
            case IP_MULTICAST_LOOP:
            case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
            {
-               if (*optlen < sizeof(u_char))
+               if (*optlen < sizeof(u_int))
                {
                    dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
@@ -1366,4 +1548,5 @@
                    return SOCKET_ERROR;
                }
+               memset(optval, 0, *optlen);
                ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
                break;
@@ -1372,5 +1555,5 @@
            case IP_MULTICAST_TTL:
            case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
-               if (*optlen < sizeof(u_char))
+               if (*optlen < sizeof(u_int))
                {
                    dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
@@ -1378,5 +1561,7 @@
                    return SOCKET_ERROR;
                }
+               memset(optval, 0, *optlen);
                ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
+               dprintf(("getsockopt IP_MULTICAST_TTL_OS2 returned %d, size %d", (int)*optval, *optlen));
                break;
 
@@ -1389,4 +1574,5 @@
                    return SOCKET_ERROR;
                }
+               memset(optval, 0, *optlen);
                ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
                break;
@@ -1415,4 +1601,20 @@
                }
                break;
+
+           case IP_DONTFRAGMENT:
+           case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2):
+               //MSDN says these options are silently ignored
+               if (*optlen < sizeof(u_int))
+               {
+                   dprintf(("IP_DONTFRAGMENT, IP_DONTFRAGMENT_WS2, optlen too small"));
+                   WSASetLastError(WSAEFAULT);
+                   return SOCKET_ERROR;
+               }
+               dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored"));
+               *optlen = sizeof(u_int);
+               *(int *)optval = 0;
+               ret = 0;
+               break;
+
 
            default:
@@ -1481,4 +1683,9 @@
 //      I.e. start ISDNPM without dialing in. gethostbyname will query
 //      each name server and retry several times (60+ seconds per name server)
+//
+static struct ws_hostent localhost;
+static DWORD  localhost_address;
+static DWORD  localhost_addrlist[2] = {(DWORD)&localhost_address, 0};
+static DWORD  localhost_aliaslist[1] = {0};
 //******************************************************************************
 ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
@@ -1493,7 +1700,49 @@
 
     dprintf(("gethostbyname %s", name));
-    if(gethostname(localhostname, sizeof(localhostname)) == NO_ERROR) 
+    if (!gethostname(localhostname, sizeof(localhostname)))
     {
-        if(!strcmp(name, localhostname)) {
+        /*
+         * This is a fast non-blocking path for the hostname of this machine.
+         * It's probably not 100% correct though..
+         */
+        if (!strcmp(name, localhostname))
+        {
+            /*
+             * Lookup lan0 address, and move on to lo address if that fails.
+             */
+            sock_init();                /* ??? */
+            int s = socket(PF_INET, SOCK_STREAM, 0);
+            if (s >= 0)
+            {
+                struct ifreq  ifr = {0};
+                strcpy(ifr.ifr_name, "lan0");
+                int rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr));
+                if (rc == -1)
+                {
+                    strcpy(ifr.ifr_name, "lo");
+                    rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr));
+                }
+                soclose(s);
+
+                if (rc != -1)
+                {
+                    /* ASSUMES: family is AF_INET */
+                    /* Doesn't work with aliases on lan0. */
+                    struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
+
+                    localhost_address       = *(unsigned long *)&addr->sin_addr;
+                    localhost.h_name        = "localhost"; /* This is what the old workaround did. */
+                    localhost.h_addrtype    = AF_INET;
+                    localhost.h_length      = 4;
+                    localhost.h_addr_list   = (char **)&localhost_addrlist[0];
+                    localhost.h_aliases     = (char **)&localhost_aliaslist[0];
+                    WSASetLastError(NO_ERROR);
+                    return &localhost;
+                }
+            }
+
+            /*
+             * bail out..
+             */
             strcpy(localhostname, "localhost");
             name = localhostname;
Index: trunk/src/wsock32/wsock32.def
===================================================================
--- trunk/src/wsock32/wsock32.def	(revision 21307)
+++ trunk/src/wsock32/wsock32.def	(revision 21308)
@@ -107,4 +107,9 @@
 ;  TransmitFile                = _OS2TransmitFile
 
+;
+; ENDOFEXPORTS
+; Internal function marker
+;
+
 ; -----------------------
 ; ODIN internal functions
Index: trunk/src/wsock32/wsock32.h
===================================================================
--- trunk/src/wsock32/wsock32.h	(revision 21307)
+++ trunk/src/wsock32/wsock32.h	(revision 21308)
@@ -24,4 +24,5 @@
 #define IP_TTL              7
 #define IP_TOS              8
+#define IP_DONTFRAGMENT     9
 #endif
 
