Changeset 21308 for trunk/src


Ignore:
Timestamp:
Jun 18, 2009, 6:27:45 PM (16 years ago)
Author:
ydario
Message:

Minor updates, backout imm changes.

Location:
trunk/src
Files:
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/comdlg32/initcomdlg32.cpp

    r9990 r21308  
    5454   switch (fdwReason)
    5555   {
    56     case DLL_PROCESS_ATTACH:
    57     {
    58         /*
    59          * Find default printer and write name to win.ini
    60          * Format: queuename,driver,portname
    61          */
    62         char szWinDefPrn[256];
    63         szWinDefPrn[0] = '\0';
    64 
    65         /*
    66          * OS/2 stores the default printer as a combination of printerdevice and queue.
    67          *
    68          *   Printer Device is related to one port. It may have multiple printer
    69          *       drivers because the port may serve multiple queues with different drivers.
    70          *   The Ports are related to multiple queues.
    71          *
    72          * So we take the default default printer+queue combination and finds the
    73          */
    74         char szDefPrnDev[20];
    75         char szDefPrnQue[20];
    76         if (PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "PRINTER", "",
    77                                   szDefPrnDev, sizeof(szDefPrnDev)) > 1
    78             &&  PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER", "QUEUE", "",
    79                                       szDefPrnQue, sizeof(szDefPrnQue)) > 1
    80             &&  szDefPrnDev[0]
    81             &&  szDefPrnQue[0]
    82            )
    83         {
    84             char *psz;
    85             /* remove everything beyond the first ';' */
    86             if ((psz = strchr(szDefPrnDev, ';')) != NULL)
    87                 *psz = '\0';
    88             if ((psz = strchr(szDefPrnQue, ';')) != NULL)
    89                 *psz = '\0';
    90 
    91             /*
    92              * Now we must lookup the port name from the device settings.
    93              *  This is a string of this form:
    94              *      <port>;<driver1>[,<driver2>;<queue1>[,<queue2>];?;?;
    95              */
    96             ULONG   cb = 0;
    97             if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev, &cb)
    98                 &&  cb > 0)
    99             {
    100                 char *pszBufD = (char*)malloc(cb + 1);
    101                 if (pszBufD
    102                     &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_PRINTER", szDefPrnDev,
    103                                               NULL, pszBufD, cb + 1)
    104                     > 1
    105                    )
    106                 {
    107                     /*
    108                      * Now get the Default printer driver for the queue.
    109                      *  This is stored as a ';' separated list of drivers, the first one is the default.
    110                      */
    111                     if (PrfQueryProfileSize(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue, &cb)
    112                         &&  cb > 0)
    113                     {
    114                         char *pszBufQ = (char*)malloc(cb + 1);
    115                         if (pszBufQ
    116                             &&  PrfQueryProfileString(HINI_SYSTEMPROFILE, "PM_SPOOLER_QUEUE_DD", szDefPrnQue,
    117                                                       NULL, pszBufQ, cb + 1)
    118                             > 1
    119                            )
    120                         {
    121                             /*
    122                              * We got everything now. just find the parts we need.
    123                              *  First printer driver from QUEUE_DD
    124                              *  Port name of the device.
    125                              */
    126                             if ((psz = strchr(pszBufQ, ';')) != NULL)
    127                                 *psz = '\0';
    128                             if ((psz = strchr(pszBufQ, ',')) != NULL) //paranoia! in case comman separated list of some kind.
    129                                 *psz = '\0';
    130                             if ((psz = strchr(pszBufD, ';')) != NULL)
    131                                 *psz = '\0';
    132                             if ((psz = strchr(pszBufD, ',')) != NULL) //paranoia in case comman separated list of some kind.
    133                                 *psz = '\0';
    134 
    135                             /*
    136                              * Now make default printer string for the win.ini.
    137                              */
    138                             strcpy(szWinDefPrn, szDefPrnQue);
    139                             strcat(strcat(szWinDefPrn, ","), pszBufQ);
    140                             strcat(strcat(szWinDefPrn, ","), pszBufD);
    141                             dprintf(("LibMainComdlg32: Successfully found default printer.'%s'", szWinDefPrn));
    142                             free(pszBufQ);
    143                         }
    144                     }
    145                     else
    146                     {
    147                         /* OS/2 the device may exist though the default queue is destroyed.
    148                          * it may still exist even if there are no queues on the system at all!
    149                          */
    150                         dprintf(("LibMainComdlg32: no queue driver entry for '%s'.", szDefPrnQue));
    151                     }
    152 
    153                     free(pszBufD);
    154                 }
    155             }
    156             else
    157             {
    158                 /* OS/2 doesn't remove the default settings if the default queue/printer is deleted. */
    159                 dprintf(("LibMainComdlg32: can't find device settings for '%s'.", szDefPrnDev));
    160             }
    161         }
    162         else
    163         {
    164             dprintf(("LibMainComdlg32: no default printer? szDefPrnDev='%s' szDefPrnQue='%s'.", szDefPrnDev, szDefPrnQue));
    165         }
    166 
    167         //Now get real printer name the one that will be used in DC calls
    168         WriteProfileStringA("windows", "device", szWinDefPrn);
    169 
    170         return COMDLG32_DllEntryPoint(hinstDLL, fdwReason, fImpLoad);
    171     }
     56   case DLL_PROCESS_ATTACH:
     57       return COMDLG32_DllEntryPoint(hinstDLL, fdwReason, fImpLoad);
    17258
    17359   case DLL_THREAD_ATTACH:
  • trunk/src/kernel32/initkernel32.cpp

    r21302 r21308  
    6060#include <stats.h>
    6161#include <heapshared.h>
     62#include <heapstring.h>
    6263#include <_ras.h>
    6364
     
    7172 extern DWORD kernel32_PEResTab;
    7273}
     74
     75extern PFN pfnImSetMsgQueueProperty;
    7376
    7477       ULONG   flAllocMem = 0;    /* flag to optimize DosAllocMem to use all the memory on SMP machines */
     
    7982       BOOL    fInit     = FALSE;
    8083       BOOL    fWin32k   = FALSE;
     84       HMODULE imHandle = 0;
     85       char    szModName[ 256 ] = "";
    8186
    8287/****************************************************************************/
     
    224229            CODEPAGE_Init();
    225230
     231            if( IsDBCSEnv() && DosLoadModule( szModName, sizeof( szModName ), "OS2IM.DLL", &imHandle ) == 0 )
     232                DosQueryProcAddr( imHandle, 140, NULL, &pfnImSetMsgQueueProperty );
     233
    226234            InitSystemInfo(ulSysinfo);
    227235            //Set up environment as found in NT
     
    272280    dprintf(("kernel32 exit %d\n", ulReason));
    273281
     282    if( IsDBCSEnv() && imHandle )
     283        DosFreeModule( imHandle );
     284
    274285    //Flush and delete all open memory mapped files
    275286    Win32MemMap::deleteAll();
  • trunk/src/kernel32/oslibmisc.cpp

    r21302 r21308  
    2828#include "dbglocal.h"
    2929
     30typedef APIRET ( APIENTRY *PFN_IMSETMSGQUEUEPROPERTY )( HMQ, ULONG );
     31
     32PFN_IMSETMSGQUEUEPROPERTY pfnImSetMsgQueueProperty = NULL;
     33
    3034//******************************************************************************
    3135//TODO: not reentrant!
     
    351355//******************************************************************************
    352356//******************************************************************************
    353 
     357ULONG OSLibImSetMsgQueueProperty( ULONG hmq, ULONG ulFlag )
     358{
     359    USHORT sel;
     360    APIRET rc;
     361
     362    if( !pfnImSetMsgQueueProperty )
     363        return 1;
     364
     365    sel = RestoreOS2FS();
     366    rc = pfnImSetMsgQueueProperty( hmq, ulFlag );
     367    SetFS( sel );
     368
     369    return rc;
     370}
     371//******************************************************************************
     372//******************************************************************************
     373
  • trunk/src/kernel32/oslibmisc.h

    r21302 r21308  
    103103void OSLibQueryBeginLibpath(char *lpszBeginlibpath, int size);
    104104
     105ULONG OSLibImSetMsgQueueProperty( ULONG hmq, ULONG ulFlag );
     106
    105107#ifdef __cplusplus
    106108}
  • trunk/src/kernel32/thread.cpp

    r21302 r21308  
    3434#include <handlemanager.h>
    3535#include <codepage.h>
     36#include <heapstring.h>
    3637
    3738#include "hmhandle.h"
     
    4849
    4950static ULONG priorityclass = NORMAL_PRIORITY_CLASS;
     51
     52#define MQP_INSTANCE_PERMQ              0x00000001 // from os2im.h
    5053
    5154//******************************************************************************
     
    689692    dprintf(("Win32ThreadProc: hab %x hmq %x", winteb->o.odin.hab, winteb->o.odin.hmq));
    690693    dprintf(("Stack top 0x%x, stack end 0x%x", winteb->stack_top, winteb->stack_low));
     694
     695    if( IsDBCSEnv())
     696        /* IM instace is created per message queue, that is, thread */
     697        OSLibImSetMsgQueueProperty( winteb->o.odin.hmq, MQP_INSTANCE_PERMQ );
    691698
    692699    //Note: The Win32 exception structure referenced by FS:[0] is the same
  • trunk/src/kernel32/windllbase.cpp

    r21302 r21308  
    708708        PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "CRTDLL32", "CRTDLL");
    709709    }
     710    if(PROFILE_GetOdinIniString(DLLRENAMEWIN_SECTION, "IMM32", "", renameddll,
     711                                sizeof(renameddll)-1) <= 1)
     712    {
     713        PROFILE_SetOdinIniString(DLLRENAMEWIN_SECTION, "IMM32", "IMM32OS2");
     714        PROFILE_SetOdinIniString(DLLRENAMEOS2_SECTION, "IMM32OS2", "IMM32");
     715    }
    710716}
    711717//******************************************************************************
  • trunk/src/oleaut32/stubs.cpp

    r10634 r21308  
    173173//*****************************************************************************
    174174//*****************************************************************************
     175HRESULT WIN32API VarDecFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, DECIMAL *pdecOut)
     176{
     177    dprintf(("OLEAUT32: VarDecFromStr - stub"));
     178    return S_OK;
     179}
     180
     181//*****************************************************************************
     182//*****************************************************************************
    175183HRESULT WIN32API VarDecFromDisp(IDispatch *pdispIn, LCID lcid, DECIMAL *pdecOut)
    176184{
     
    256264{
    257265    dprintf(("OLEAUT32: VarCyFromDec - stub"));
     266    return S_OK;
     267}
     268
     269//*****************************************************************************
     270//*****************************************************************************
     271HRESULT WIN32API VarBstrFromDec(DECIMAL *pdecIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
     272{
     273    dprintf(("OLEAUT32: VarBstrFromDec - stub"));
    258274    return S_OK;
    259275}
  • trunk/src/oleaut32/variant.c

    r10629 r21308  
    201201    {0x00    ,   0,  0          , VT_NULL}
    202202};
    203 
    204 
    205 /************** Form wine: oleaut32/variant.h **************/
    206 
    207 /* Value of sign for a positive decimal number */
    208 #define DECIMAL_POS 0
    209 
    210 /* Native headers don't change the union ordering for DECIMAL sign/scale (duh).
    211  * This means that the signscale member is only useful for setting both members to 0.
    212  * SIGNSCALE creates endian-correct values so that we can properly set both at once
    213  * to values other than 0.
    214  */
    215 #ifdef WORDS_BIGENDIAN
    216 #define SIGNSCALE(sign,scale) (((scale) << 8) | sign)
    217 #else
    218 #define SIGNSCALE(sign,scale) (((sign) << 8) | scale)
    219 #endif
    220 /* Macros for getting at a DECIMAL's parts */
    221 #define DEC_SIGN(d)      ((d)->u.s.sign)
    222 #define DEC_SCALE(d)     ((d)->u.s.scale)
    223 #define DEC_SIGNSCALE(d) ((d)->u.signscale)
    224 #define DEC_HI32(d)      ((d)->Hi32)
    225 #define DEC_MID32(d)     ((d)->u1.s1.Mid32)
    226 #define DEC_LO32(d)      ((d)->u1.s1.Lo32)
    227 #define DEC_LO64(d)      ((d)->u1.Lo64)
    228 
    229 /* DECIMAL */
    230 #define _VarDecFromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_DECIMAL)
    231 /* R8 (double) */
    232 #define _VarR8FromStr(str,lcid,flags,out) VARIANT_NumberFromBstr(str,lcid,flags,(BYTE*)out,VT_R8)
    233 
    234 /* Internal flags for low level conversion functions */
    235 #define  VAR_BOOLONOFF 0x0400 /* Convert bool to "On"/"Off" */
    236 #define  VAR_BOOLYESNO 0x0800 /* Convert bool to "Yes"/"No" */
    237 #define  VAR_NEGATIVE  0x1000 /* Number is negative */
    238 
    239 /* The localised characters that make up a valid number */
    240 typedef struct tagVARIANT_NUMBER_CHARS
    241 {
    242   WCHAR cNegativeSymbol;
    243   WCHAR cPositiveSymbol;
    244   WCHAR cDecimalPoint;
    245   WCHAR cDigitSeperator;
    246   WCHAR cCurrencyLocal;
    247   WCHAR cCurrencyLocal2;
    248   WCHAR cCurrencyDecimalPoint;
    249   WCHAR cCurrencyDigitSeperator;
    250 } VARIANT_NUMBER_CHARS;
    251 
    252 void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS*,LCID,DWORD);
    253 /********** End of Form wine: oleaut32/variant.h ************/
    254 
    255 /* Write a number from a UI8 and sign */
    256 #ifdef __WIN32OS2__
    257 static WCHAR *VARIANT_WriteNumber(ULONG ulVal, WCHAR* szOut)
    258 {
    259   //FIXME("%s: Hack! No real ULONG64 support here, using ULONG instead. ulVal=%x!!\n", __FUNCTION__, ulVal);
    260 #else
    261 static WCHAR *VARIANT_WriteNumber(ULONG64 ulVal, WCHAR* szOut)
    262   {
    263 #endif
    264 
    265   do
    266   {
    267     WCHAR ulNextDigit = ulVal % 10;
    268 
    269     *szOut-- = '0' + ulNextDigit;
    270     ulVal = (ulVal - ulNextDigit) / 10;
    271   } while (ulVal);
    272 
    273   szOut++;
    274   return szOut;
    275 }
    276 
    277 /* Create a (possibly localised) BSTR from a UI8 and sign */
    278 static BSTR VARIANT_MakeBstr(LCID lcid, DWORD dwFlags, WCHAR *szOut)
    279 {
    280   WCHAR szConverted[256];
    281 
    282   if (dwFlags & VAR_NEGATIVE)
    283     *--szOut = '-';
    284 
    285   if (dwFlags & LOCALE_USE_NLS)
    286   {
    287     /* Format the number for the locale */
    288     szConverted[0] = '\0';
    289     GetNumberFormatW(lcid,
    290                      dwFlags & LOCALE_NOUSEROVERRIDE,
    291                      szOut, NULL, szConverted, sizeof(szConverted)/sizeof(WCHAR));
    292     szOut = szConverted;
    293   }
    294   return SysAllocStringByteLen((LPCSTR)szOut, strlenW(szOut) * sizeof(WCHAR));
    295 }
    296 
    297 
    298 /******************************************************************************
    299  * VarBstrFromDec (OLEAUT32.232)
    300  *
    301  * Convert a VT_DECIMAL to a VT_BSTR.
    302  *
    303  * PARAMS
    304  *  pDecIn   [I] Source
    305  *  lcid     [I] LCID for the conversion
    306  *  dwFlags  [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
    307  *  pbstrOut [O] Destination
    308  *
    309  * RETURNS
    310  *  Success: S_OK.
    311  *  Failure: E_INVALIDARG, if pbstrOut is invalid.
    312  *           E_OUTOFMEMORY, if memory allocation fails.
    313  */
    314 HRESULT WINAPI VarBstrFromDec(DECIMAL* pDecIn, LCID lcid, ULONG dwFlags, BSTR* pbstrOut)
    315 {
    316   TRACE("%s: entering function. pDecIn->lo32: %x, pDecIn->Mid32: %x, pDecIn->Hi32: %x, sign: %x, dwFlags: %x\n",
    317         __FUNCTION__, DEC_LO32(pDecIn), DEC_MID32(pDecIn), DEC_HI32(pDecIn), DEC_SIGN(pDecIn), dwFlags);
    318   if (!pbstrOut)
    319     return E_INVALIDARG;
    320 
    321   if (!DEC_SCALE(pDecIn) && !DEC_HI32(pDecIn))
    322   {
    323     WCHAR szBuff[256], *szOut = szBuff + sizeof(szBuff)/sizeof(WCHAR) - 1;
    324 
    325     /* Create the basic number string */
    326     *szOut-- = '\0';
    327 
    328 
    329 #ifdef __WIN32OS2__
    330     szOut = VARIANT_WriteNumber(DEC_LO32(pDecIn), szOut);
    331 #else
    332     szOut = VARIANT_WriteNumber(DEC_LO64(pDecIn), szOut);
    333 #endif
    334     if (DEC_SIGN(pDecIn))
    335       dwFlags |= VAR_NEGATIVE;
    336 
    337     *pbstrOut = VARIANT_MakeBstr(lcid, dwFlags, szOut);
    338     TRACE("%s: returning %s\n", __FUNCTION__, debugstr_w(*pbstrOut));
    339     return *pbstrOut ? S_OK : E_OUTOFMEMORY;
    340   }
    341   FIXME("semi-stub\n");
    342   return E_INVALIDARG;
    343 }
    344 
    345 
    346 /* Copy data from one variant to another. */
    347 static inline void VARIANT_CopyData(const VARIANT *srcVar, VARTYPE vt, void *pOut)
    348 {
    349   //  TRACE("%s: entering function.\n", __FUNCTION__);
    350   switch (vt)
    351   {
    352   case VT_I1:
    353   case VT_UI1: memcpy(pOut, &V_UI1(srcVar), sizeof(BYTE)); break;
    354   case VT_BOOL:
    355   case VT_I2:
    356   case VT_UI2: memcpy(pOut, &V_UI2(srcVar), sizeof(SHORT)); break;
    357   case VT_R4:
    358   case VT_INT:
    359   case VT_I4:
    360   case VT_UINT:
    361   case VT_UI4: memcpy(pOut, &V_UI4(srcVar), sizeof (LONG)); break;
    362   case VT_R8:
    363   case VT_DATE:
    364   case VT_CY:
    365   case VT_I8:
    366 #ifdef __WIN32OS2__
    367     /*  case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break; */
    368     /*  case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break; */
    369   case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
    370 #else
    371   case VT_UI8: memcpy(pOut, &V_UI8(srcVar), sizeof (LONGLONG)); break;
    372   case VT_INT_PTR: memcpy(pOut, &V_INT_PTR(srcVar), sizeof (INT_PTR)); break;
    373   case VT_DECIMAL: memcpy(pOut, &V_DECIMAL(srcVar), sizeof (DECIMAL)); break;
    374 #endif
    375   default:
    376     FIXME("%s: VT_ type %d unhandled, please report!\n", __FUNCTION__,  vt);
    377   }
    378 }
    379 
    380 /* Form wine: oleaut32/vartype.c */
    381 /* Coerce VT_BSTR to a numeric type */
    382 HRESULT VARIANT_NumberFromBstr(OLECHAR* pStrIn, LCID lcid, ULONG ulFlags,
    383                                void* pOut, VARTYPE vt)
    384 {
    385   VARIANTARG dstVar;
    386   HRESULT hRet;
    387   NUMPARSE np;
    388   BYTE rgb[1024];
    389 
    390   TRACE("%s: (StrIn: %s, LCID: 0x%08lx, ulFlags: 0x%08lx )\n", __FUNCTION__, pStrIn, lcid, ulFlags );
    391 
    392   /* Use VarParseNumFromStr/VarNumFromParseNum as MSDN indicates */
    393   np.cDig = sizeof(rgb) / sizeof(BYTE);
    394   np.dwInFlags = NUMPRS_STD;
    395 
    396   hRet = VarParseNumFromStr(pStrIn, lcid, ulFlags, &np, rgb);
    397 
    398   if (SUCCEEDED(hRet))
    399   {
    400     /* 1 << vt gives us the VTBIT constant for the destination number type */
    401     hRet = VarNumFromParseNum(&np, rgb, 1 << vt, &dstVar);
    402     if (SUCCEEDED(hRet)) {
    403       VARIANT_CopyData(&dstVar, vt, pOut);
    404       TRACE("%s: Returning dstVar-> type : %x", __FUNCTION__, V_VT(&dstVar));
    405     }
    406   }
    407   return hRet;
    408 }
    409 
    410203
    411204/******************************************************************************
     
    20391832void WINAPI VariantInit(VARIANTARG* pvarg)
    20401833{
    2041   TRACE("%s: (%p)\n", __FUNCTION__, pvarg);
     1834  TRACE("(%p)\n",pvarg);
    20421835
    20431836  memset(pvarg, 0, sizeof (VARIANTARG));
     
    20581851{
    20591852  HRESULT res = S_OK;
    2060   TRACE("%s: (%p)\n",__FUNCTION__, pvarg);
     1853  TRACE("(%p)\n",pvarg);
    20611854
    20621855  res = ValidateVariantType( V_VT(pvarg) );
     
    21181911  HRESULT res = S_OK;
    21191912
    2120   TRACE("%s: (Dest: %p, Src: %p), vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, V_VT(pvargSrc));
     1913  TRACE("(%p, %p), vt=%d\n", pvargDest, pvargSrc, V_VT(pvargSrc));
    21211914
    21221915  res = ValidateVariantType( V_VT(pvargSrc) );
     
    23392132        VARIANTARG varg;
    23402133        VariantInit( &varg );
    2341         TRACE("%s: (Dest: %p, source: %p, LCID: %ld, wFlags: %u, VARTYPE: %u) vt=%d\n", __FUNCTION__, pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
     2134
     2135        TRACE("(%p, %p, %ld, %u, %u) vt=%d\n", pvargDest, pvargSrc, lcid, wFlags, vt, V_VT(pvargSrc));
    23422136    TRACE("Src Var:\n");
    23432137    dump_Variant(pvargSrc);
     
    23762170                         */
    23772171                        VARIANTARG Variant;
    2378 
    23792172                        VariantInit( &Variant );
    23802173                        res = VariantCopyInd( &Variant, pvargSrc );
     
    23862179                                VariantClear( &Variant );
    23872180                        }
     2181
    23882182                }
    23892183                else
     
    24032197                V_VT(pvargDest) = vt;
    24042198
    2405     TRACE("Dest Var (re: %x)\n", res);
     2199    TRACE("Dest Var:\n");
    24062200    dump_Variant(pvargDest);
    24072201
     
    29812775        LPSTR pNewString = NULL;
    29822776
    2983         TRACE("%s: ( strIn: %p -> %s, lcid: 0x%08lx, dwFlags: 0x%08lx, plOut: %p ), stub\n", __FUNCTION__, strIn, debugstr_w(strIn), lcid, dwFlags, plOut );
     2777        TRACE("( %p, 0x%08lx, 0x%08lx, %p ), stub\n", strIn, lcid, dwFlags, plOut );
    29842778
    29852779        /* Check if we have a valid argument
     
    33053099}
    33063100
    3307 #if 0
    33083101/******************************************************************************
    33093102 *              VarR8FromStr            [OLEAUT32.84]
     
    33363129
    33373130        return S_OK;
    3338 }
    3339 #endif
    3340 
    3341 /************************************************************************
    3342  * VarR8FromStr (OLEAUT32.84)
    3343  *
    3344  * Convert a VT_BSTR to a VT_R8.
    3345  *
    3346  * PARAMS
    3347  *  strIn   [I] Source
    3348  *  lcid    [I] LCID for the conversion
    3349  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
    3350  *  pDblOut [O] Destination
    3351  *
    3352  * RETURNS
    3353  *  Success: S_OK.
    3354  *  Failure: E_INVALIDARG, if strIn or pDblOut is invalid.
    3355  *           DISP_E_TYPEMISMATCH, if the type cannot be converted
    3356  */
    3357 HRESULT WINAPI VarR8FromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, double *pDblOut)
    3358 {
    3359   return _VarR8FromStr(strIn, lcid, dwFlags, pDblOut);
    33603131}
    33613132
     
    35623333   return S_OK;
    35633334}
    3564 
    3565 
    35663335
    35673336/******************************************************************************
     
    47164485
    47174486
    4718 #define GET_NUMBER_TEXT(fld,name) \
    4719   buff[0] = 0; \
    4720   if (!GetLocaleInfoW(lcid, lctype|fld, buff, 2)) \
    4721     WARN("%s: buffer too small for " #fld "\n", __FUNCTION__); \
    4722   else \
    4723     if (buff[0]) lpChars->name = buff[0]; /* \
    4724   TRACE("lcid 0x%lx, " #name "=%d '%c'\n", lcid, lpChars->name, lpChars->name)*/
    4725 
    4726 /* Get the valid number characters for an lcid */
    4727 void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, DWORD dwFlags)
    4728 {
    4729   static const VARIANT_NUMBER_CHARS defaultChars = { '-','+','.',',','$',0,'.',',' };
    4730   LCTYPE lctype = dwFlags & LOCALE_NOUSEROVERRIDE;
    4731   WCHAR buff[4];
    4732 
    4733   memcpy(lpChars, &defaultChars, sizeof(defaultChars));
    4734   GET_NUMBER_TEXT(LOCALE_SNEGATIVESIGN, cNegativeSymbol);
    4735   GET_NUMBER_TEXT(LOCALE_SPOSITIVESIGN, cPositiveSymbol);
    4736   GET_NUMBER_TEXT(LOCALE_SDECIMAL, cDecimalPoint);
    4737   GET_NUMBER_TEXT(LOCALE_STHOUSAND, cDigitSeperator);
    4738   GET_NUMBER_TEXT(LOCALE_SMONDECIMALSEP, cCurrencyDecimalPoint);
    4739   GET_NUMBER_TEXT(LOCALE_SMONTHOUSANDSEP, cCurrencyDigitSeperator);
    4740 
    4741   /* Local currency symbols are often 2 characters */
    4742   lpChars->cCurrencyLocal2 = '\0';
    4743   switch(GetLocaleInfoW(lcid, lctype|LOCALE_SCURRENCY, buff, sizeof(buff)/sizeof(WCHAR)))
    4744   {
    4745     case 3: lpChars->cCurrencyLocal2 = buff[1]; /* Fall through */
    4746     case 2: lpChars->cCurrencyLocal  = buff[0];
    4747             break;
    4748     default: WARN("buffer too small for LOCALE_SCURRENCY\n");
    4749   }
    4750   TRACE("lcid 0x%lx, cCurrencyLocal =%d,%d '%c','%c'\n", lcid, lpChars->cCurrencyLocal,
    4751         lpChars->cCurrencyLocal2, lpChars->cCurrencyLocal, lpChars->cCurrencyLocal2);
    4752 }
    4753 
    4754 /* Number Parsing States */
    4755 #define B_PROCESSING_EXPONENT 0x1
    4756 #define B_NEGATIVE_EXPONENT   0x2
    4757 #define B_EXPONENT_START      0x4
    4758 #define B_INEXACT_ZEROS       0x8
    4759 #define B_LEADING_ZERO        0x10
    4760 #define B_PROCESSING_HEX      0x20
    4761 #define B_PROCESSING_OCT      0x40
    4762 /**********************************************************************
    4763  *              VarParseNumFromStr [OLEAUT32.46]
    4764  *
    4765  * Parse a string containing a number into a NUMPARSE structure.
    4766  *
    4767  * PARAMS
    4768  *  lpszStr [I]   String to parse number from
    4769  *  lcid    [I]   Locale Id for the conversion
    4770  *  dwFlags [I]   0, or LOCALE_NOUSEROVERRIDE to use system default number chars
    4771  *  pNumprs [I/O] Destination for parsed number
    4772  *  rgbDig  [O]   Destination for digits read in
    4773  *
    4774  * RETURNS
    4775  *  Success: S_OK. pNumprs and rgbDig contain the parsed representation of
    4776  *           the number.
    4777  *  Failure: E_INVALIDARG, if any parameter is invalid.
    4778  *           DISP_E_TYPEMISMATCH, if the string is not a number or is formatted
    4779  *           incorrectly.
    4780  *           DISP_E_OVERFLOW, if rgbDig is too small to hold the number.
    4781  *
    4782  * NOTES
    4783  *  pNumprs must have the following fields set:
    4784  *   cDig: Set to the size of rgbDig.
    4785  *   dwInFlags: Set to the allowable syntax of the number using NUMPRS_ flags
    4786  *            from "oleauto.h".
    4787  *
    4788  * FIXME
    4789  *  - I am unsure if this function should parse non-arabic (e.g. Thai)
    4790  *   numerals, so this has not been implemented.
    4791  */
    4792 HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags,
    4793                                   NUMPARSE *pNumprs, BYTE *rgbDig)
    4794 {
    4795   VARIANT_NUMBER_CHARS chars;
    4796   BYTE rgbTmp[1024];
    4797   DWORD dwState = B_EXPONENT_START|B_INEXACT_ZEROS;
    4798   int iMaxDigits = sizeof(rgbTmp) / sizeof(BYTE);
    4799   int cchUsed = 0;
    4800 
    4801   TRACE("%s: (%s, %ld, dwFlags: 0x%08lx,%p,%p, NUMPARSE->dwInFlags: %x)\n", __FUNCTION__, debugstr_w(lpszStr), lcid, dwFlags, pNumprs, rgbDig, pNumprs->dwInFlags);
    4802 
    4803   if (!pNumprs || !rgbDig)
    4804     return E_INVALIDARG;
    4805 
    4806   if (pNumprs->cDig < iMaxDigits)
    4807     iMaxDigits = pNumprs->cDig;
    4808 
    4809   pNumprs->cDig = 0;
    4810   pNumprs->dwOutFlags = 0;
    4811   pNumprs->cchUsed = 0;
    4812   pNumprs->nBaseShift = 0;
    4813   pNumprs->nPwr10 = 0;
    4814 
    4815   if (!lpszStr)
    4816     return DISP_E_TYPEMISMATCH;
    4817 
    4818   VARIANT_GetLocalisedNumberChars(&chars, lcid, dwFlags);
    4819 
    4820   /* First consume all the leading symbols and space from the string */
    4821   while (1)
    4822   {
    4823     if (pNumprs->dwInFlags & NUMPRS_LEADING_WHITE && isspaceW(*lpszStr))
    4824     {
    4825       pNumprs->dwOutFlags |= NUMPRS_LEADING_WHITE;
    4826       do
    4827       {
    4828         cchUsed++;
    4829         lpszStr++;
    4830       } while (isspaceW(*lpszStr));
    4831     }
    4832     else if (pNumprs->dwInFlags & NUMPRS_LEADING_PLUS &&
    4833              *lpszStr == chars.cPositiveSymbol &&
    4834              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS))
    4835     {
    4836       pNumprs->dwOutFlags |= NUMPRS_LEADING_PLUS;
    4837       cchUsed++;
    4838       lpszStr++;
    4839     }
    4840     else if (pNumprs->dwInFlags & NUMPRS_LEADING_MINUS &&
    4841              *lpszStr == chars.cNegativeSymbol &&
    4842              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS))
    4843     {
    4844       pNumprs->dwOutFlags |= (NUMPRS_LEADING_MINUS|NUMPRS_NEG);
    4845       cchUsed++;
    4846       lpszStr++;
    4847     }
    4848     else if (pNumprs->dwInFlags & NUMPRS_CURRENCY &&
    4849              !(pNumprs->dwOutFlags & NUMPRS_CURRENCY) &&
    4850              *lpszStr == chars.cCurrencyLocal &&
    4851              (!chars.cCurrencyLocal2 || lpszStr[1] == chars.cCurrencyLocal2))
    4852     {
    4853       pNumprs->dwOutFlags |= NUMPRS_CURRENCY;
    4854       cchUsed++;
    4855       lpszStr++;
    4856       /* Only accept currency characters */
    4857       chars.cDecimalPoint = chars.cCurrencyDecimalPoint;
    4858       chars.cDigitSeperator = chars.cCurrencyDigitSeperator;
    4859     }
    4860     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == '(' &&
    4861              !(pNumprs->dwOutFlags & NUMPRS_PARENS))
    4862     {
    4863       pNumprs->dwOutFlags |= NUMPRS_PARENS;
    4864       cchUsed++;
    4865       lpszStr++;
    4866     }
    4867     else
    4868       break;
    4869   } /* End of while */
    4870 
    4871   if(pNumprs->dwOutFlags & (1<<VT_LPWSTR))
    4872     {
    4873  TRACE("  I'm here");     
    4874     }
    4875   if (!(pNumprs->dwOutFlags & NUMPRS_CURRENCY))
    4876   {
    4877     /* Only accept non-currency characters */
    4878     chars.cCurrencyDecimalPoint = chars.cDecimalPoint;
    4879     chars.cCurrencyDigitSeperator = chars.cDigitSeperator;
    4880   }
    4881 
    4882   if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) &&
    4883     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
    4884   {
    4885       dwState |= B_PROCESSING_HEX;
    4886       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
    4887       cchUsed=cchUsed+2;
    4888       lpszStr=lpszStr+2;
    4889   }
    4890   else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) &&
    4891     pNumprs->dwInFlags & NUMPRS_HEX_OCT)
    4892   {
    4893       dwState |= B_PROCESSING_OCT;
    4894       pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
    4895       cchUsed=cchUsed+2;
    4896       lpszStr=lpszStr+2;
    4897   }
    4898 
    4899   /* Strip Leading zeros */
    4900   while (*lpszStr == '0')
    4901   {
    4902     dwState |= B_LEADING_ZERO;
    4903     cchUsed++;
    4904     lpszStr++;
    4905   }
    4906 
    4907   while (*lpszStr)
    4908   {
    4909     if (isdigitW(*lpszStr))
    4910     {
    4911       if (dwState & B_PROCESSING_EXPONENT)
    4912       {
    4913         int exponentSize = 0;
    4914         if (dwState & B_EXPONENT_START)
    4915         {
    4916           while (*lpszStr == '0')
    4917           {
    4918             /* Skip leading zero's in the exponent */
    4919             cchUsed++;
    4920             lpszStr++;
    4921           }
    4922           if (!isdigitW(*lpszStr))
    4923             break; /* No exponent digits - invalid */
    4924         }
    4925 
    4926         while (isdigitW(*lpszStr))
    4927         {
    4928           exponentSize *= 10;
    4929           exponentSize += *lpszStr - '0';
    4930           cchUsed++;
    4931           lpszStr++;
    4932         }
    4933         if (dwState & B_NEGATIVE_EXPONENT)
    4934           exponentSize = -exponentSize;
    4935         /* Add the exponent into the powers of 10 */
    4936         pNumprs->nPwr10 += exponentSize;
    4937         dwState &= ~(B_PROCESSING_EXPONENT|B_EXPONENT_START);
    4938         lpszStr--; /* back up to allow processing of next char */
    4939       }
    4940       else
    4941       {
    4942         if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX)
    4943           && !(dwState & B_PROCESSING_OCT))
    4944         {
    4945           pNumprs->dwOutFlags |= NUMPRS_INEXACT;
    4946 
    4947           if (*lpszStr != '0')
    4948             dwState &= ~B_INEXACT_ZEROS; /* Inexact number with non-trailing zeros */
    4949 
    4950           /* This digit can't be represented, but count it in nPwr10 */
    4951           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
    4952             pNumprs->nPwr10--;
    4953           else
    4954             pNumprs->nPwr10++;
    4955         }
    4956         else
    4957         {
    4958           if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) {
    4959             return DISP_E_TYPEMISMATCH;
    4960           }
    4961 
    4962           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
    4963             pNumprs->nPwr10--; /* Count decimal points in nPwr10 */
    4964 
    4965           rgbTmp[pNumprs->cDig] = *lpszStr - '0';
    4966         }
    4967         pNumprs->cDig++;
    4968         cchUsed++;
    4969       }
    4970     }
    4971     else if (*lpszStr == chars.cDigitSeperator && pNumprs->dwInFlags & NUMPRS_THOUSANDS)
    4972     {
    4973       pNumprs->dwOutFlags |= NUMPRS_THOUSANDS;
    4974       cchUsed++;
    4975     }
    4976     else if (*lpszStr == chars.cDecimalPoint &&
    4977              pNumprs->dwInFlags & NUMPRS_DECIMAL &&
    4978              !(pNumprs->dwOutFlags & (NUMPRS_DECIMAL|NUMPRS_EXPONENT)))
    4979     {
    4980       pNumprs->dwOutFlags |= NUMPRS_DECIMAL;
    4981       cchUsed++;
    4982 
    4983       /* Remove trailing zeros from the whole number part */
    4984       while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
    4985       {
    4986         pNumprs->nPwr10++;
    4987         pNumprs->cDig--;
    4988       }
    4989 
    4990       /* If we have no digits so far, skip leading zeros */
    4991       if (!pNumprs->cDig)
    4992       {
    4993         while (lpszStr[1] == '0')
    4994         {
    4995           dwState |= B_LEADING_ZERO;
    4996           cchUsed++;
    4997           lpszStr++;
    4998         }
    4999       }
    5000     }
    5001     else if ((*lpszStr == 'e' || *lpszStr == 'E') &&
    5002              pNumprs->dwInFlags & NUMPRS_EXPONENT &&
    5003              !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
    5004     {
    5005       dwState |= B_PROCESSING_EXPONENT;
    5006       pNumprs->dwOutFlags |= NUMPRS_EXPONENT;
    5007       cchUsed++;
    5008     }
    5009     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cPositiveSymbol)
    5010     {
    5011       cchUsed++; /* Ignore positive exponent */
    5012     }
    5013     else if (dwState & B_PROCESSING_EXPONENT && *lpszStr == chars.cNegativeSymbol)
    5014     {
    5015       dwState |= B_NEGATIVE_EXPONENT;
    5016       cchUsed++;
    5017     }
    5018     else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
    5019              (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
    5020              dwState & B_PROCESSING_HEX)
    5021     {
    5022       if (pNumprs->cDig >= iMaxDigits)
    5023       {
    5024         return DISP_E_OVERFLOW;
    5025       }
    5026       else
    5027       {
    5028         if (*lpszStr >= 'a')
    5029           rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
    5030         else
    5031           rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
    5032       }
    5033       pNumprs->cDig++;
    5034       cchUsed++;
    5035     }
    5036     else
    5037       break; /* Stop at an unrecognised character */
    5038 
    5039     lpszStr++;
    5040   }
    5041 
    5042   if (!pNumprs->cDig && dwState & B_LEADING_ZERO)
    5043   {
    5044     /* Ensure a 0 on its own gets stored */
    5045     pNumprs->cDig = 1;
    5046     rgbTmp[0] = 0;
    5047   }
    5048 
    5049   if (pNumprs->dwOutFlags & NUMPRS_EXPONENT && dwState & B_PROCESSING_EXPONENT)
    5050   {
    5051     pNumprs->cchUsed = cchUsed;
    5052     return DISP_E_TYPEMISMATCH; /* Failed to completely parse the exponent */
    5053   }
    5054 
    5055   if (pNumprs->dwOutFlags & NUMPRS_INEXACT)
    5056   {
    5057     if (dwState & B_INEXACT_ZEROS)
    5058       pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* All zeros doesn't set NUMPRS_INEXACT */
    5059   } else if(pNumprs->dwInFlags & NUMPRS_HEX_OCT)
    5060   {
    5061     /* copy all of the digits into the output digit buffer */
    5062     /* this is exactly what windows does although it also returns */
    5063     /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
    5064     memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
    5065 
    5066     if (dwState & B_PROCESSING_HEX) {
    5067       /* hex numbers have always the same format */
    5068       pNumprs->nPwr10=0;
    5069       pNumprs->nBaseShift=4;
    5070     } else {
    5071       if (dwState & B_PROCESSING_OCT) {
    5072         /* oct numbers have always the same format */
    5073         pNumprs->nPwr10=0;
    5074         pNumprs->nBaseShift=3;
    5075       } else {
    5076         while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
    5077         {
    5078           if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
    5079             pNumprs->nPwr10--;
    5080           else
    5081             pNumprs->nPwr10++;
    5082 
    5083           pNumprs->cDig--;
    5084         }
    5085       }
    5086     }
    5087   } else
    5088   {
    5089     /* Remove trailing zeros from the last (whole number or decimal) part */
    5090     while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
    5091     {
    5092       if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
    5093         pNumprs->nPwr10--;
    5094       else
    5095         pNumprs->nPwr10++;
    5096 
    5097       pNumprs->cDig--;
    5098     }
    5099   }
    5100 
    5101   if (pNumprs->cDig <= iMaxDigits)
    5102     pNumprs->dwOutFlags &= ~NUMPRS_INEXACT; /* Ignore stripped zeros for NUMPRS_INEXACT */
    5103   else
    5104     pNumprs->cDig = iMaxDigits; /* Only return iMaxDigits worth of digits */
    5105 
    5106   /* Copy the digits we processed into rgbDig */
    5107   memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
    5108 
    5109   /* Consume any trailing symbols and space */
    5110   while (1)
    5111   {
    5112     if ((pNumprs->dwInFlags & NUMPRS_TRAILING_WHITE) && isspaceW(*lpszStr))
    5113     {
    5114       pNumprs->dwOutFlags |= NUMPRS_TRAILING_WHITE;
    5115       do
    5116       {
    5117         cchUsed++;
    5118         lpszStr++;
    5119       } while (isspaceW(*lpszStr));
    5120     }
    5121     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_PLUS &&
    5122              !(pNumprs->dwOutFlags & NUMPRS_LEADING_PLUS) &&
    5123              *lpszStr == chars.cPositiveSymbol)
    5124     {
    5125       pNumprs->dwOutFlags |= NUMPRS_TRAILING_PLUS;
    5126       cchUsed++;
    5127       lpszStr++;
    5128     }
    5129     else if (pNumprs->dwInFlags & NUMPRS_TRAILING_MINUS &&
    5130              !(pNumprs->dwOutFlags & NUMPRS_LEADING_MINUS) &&
    5131              *lpszStr == chars.cNegativeSymbol)
    5132     {
    5133       pNumprs->dwOutFlags |= (NUMPRS_TRAILING_MINUS|NUMPRS_NEG);
    5134       cchUsed++;
    5135       lpszStr++;
    5136     }
    5137     else if (pNumprs->dwInFlags & NUMPRS_PARENS && *lpszStr == ')' &&
    5138              pNumprs->dwOutFlags & NUMPRS_PARENS)
    5139     {
    5140       cchUsed++;
    5141       lpszStr++;
    5142       pNumprs->dwOutFlags |= NUMPRS_NEG;
    5143     }
    5144     else
    5145       break;
    5146   }
    5147 
    5148   if (pNumprs->dwOutFlags & NUMPRS_PARENS && !(pNumprs->dwOutFlags & NUMPRS_NEG))
    5149   {
    5150     pNumprs->cchUsed = cchUsed;
    5151     return DISP_E_TYPEMISMATCH; /* Opening parenthesis not matched */
    5152   }
    5153 
    5154   if (pNumprs->dwInFlags & NUMPRS_USE_ALL && *lpszStr != '\0')
    5155     return DISP_E_TYPEMISMATCH; /* Not all chars were consumed */
    5156 
    5157   if (!pNumprs->cDig)
    5158     return DISP_E_TYPEMISMATCH; /* No Number found */
    5159 
    5160   pNumprs->cchUsed = cchUsed;
    5161   TRACE("%s: Returning, NUMPARS->cchUsed: %x, NUMPARS->cDig: %x, pNumprs->dwOutFlags: %x, NUMPARS->nBaseShift: %x,, NUMPARS->nPwr10: %x\n",
    5162         __FUNCTION__, cchUsed, pNumprs->cDig, pNumprs->dwOutFlags, pNumprs->nBaseShift, pNumprs->nPwr10);
    5163   return S_OK;
    5164 }
    5165 
    5166 #if 0
    51674487/**********************************************************************
    51684488 *              VarParseNumFromStr [OLEAUT32.46]
     
    52044524    return S_OK;
    52054525}
    5206 #endif
    52074526
    52084527
    52094528/**********************************************************************
    52104529 *              VarNumFromParseNum [OLEAUT32.47]
    5211  *
    5212  * Convert a NUMPARSE structure into a numeric Variant type.
    5213  *
    5214  * PARAMS
    5215  *  pNumprs  [I] Source for parsed number. cDig must be set to the size of rgbDig
    5216  *  rgbDig   [I] Source for the numbers digits
    5217  *  dwVtBits [I] VTBIT_ flags from "oleauto.h" indicating the acceptable dest types
    5218  *  pVarDst  [O] Destination for the converted Variant value.
    5219  *
    5220  * RETURNS
    5221  *  Success: S_OK. pVarDst contains the converted value.
    5222  *  Failure: E_INVALIDARG, if any parameter is invalid.
    5223  *           DISP_E_OVERFLOW, if the number is too big for the types set in dwVtBits.
    5224  *
    5225  * NOTES
    5226  *  - The smallest favoured type present in dwVtBits that can represent the
    5227  *    number in pNumprs without losing precision is used.
    5228  *  - Signed types are preferrred over unsigned types of the same size.
    5229  *  - Preferred types in order are: integer, float, double, currency then decimal.
    5230  *  - Rounding (dropping of decimal points) occurs without error. See VarI8FromR8()
    5231  *    for details of the rounding method.
    5232  *  - pVarDst is not cleared before the result is stored in it.
    52334530 */
    52344531HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
    52354532                                  ULONG dwVtBits, VARIANT * pvar)
    52364533{
    5237 #ifdef __WIN32OS2__
    52384534    DWORD xint;
    52394535    int i;
    5240 
    5241     TRACE("%s: NUMPARSE->cDig: %x, NUMPARSE->nBaseShift: %x, NUMPARSE->dwOutFlags: %x dwVtBits=%lx. rgbDig: \n",
    5242           __FUNCTION__, pnumprs->cDig, pnumprs->nBaseShift, pnumprs->dwOutFlags, dwVtBits);
     4536    FIXME("(..,dwVtBits=%lx,....), partial stub!\n",dwVtBits);
    52434537
    52444538    xint = 0;
    52454539    for (i=0;i<pnumprs->cDig;i++)
    5246       xint = xint*10 + rgbDig[i];
     4540        xint = xint*10 + rgbDig[i];
    52474541
    52484542    if (pnumprs->dwOutFlags & NUMPRS_NEG) {
    52494543        xint = xint * -1;
    52504544    }
    5251     TRACE("%s: xint: %x (%ld)\n", __FUNCTION__, xint, xint);
    52524545
    52534546    VariantInit(pvar);
     
    52814574    }
    52824575
    5283     if (dwVtBits & VTBIT_DECIMAL)
    5284       {
    5285         int i;
    5286         ULONG carry;
    5287         /*    ULONG64 tmp; */
    5288         ULONG tmp;
    5289         DECIMAL* pDec = &V_DECIMAL(pvar);
    5290        
    5291         V_VT(pvar) = VT_DECIMAL;
    5292        
    5293         DECIMAL_SETZERO(pDec);
    5294         DEC_LO32(pDec) = 0;
    5295        
    5296         if (pnumprs->dwOutFlags & NUMPRS_NEG)
    5297           DEC_SIGN(pDec) = DECIMAL_NEG;
    5298         else
    5299           DEC_SIGN(pDec) = DECIMAL_POS;
    5300 
    5301         /* Factor the significant digits */
    5302         for (i = 0; i < pnumprs->cDig; i++)
    5303           {
    5304             if(0xffffffff /10 - 9 < DEC_LO32(pDec) ) {
    5305               /* Overflow expected. This code only support 32Bit numbers for now */
    5306               FIXME("%s: Converted number will be  > 32bit! Only partial implementation. Returning DISP_E_OVERFLOW.", __FUNCTION__);
    5307               DEC_LO32(pDec) =  UI4_MAX;
    5308               return DISP_E_OVERFLOW;
    5309             }
    5310 
    5311             tmp = DEC_LO32(pDec) * 10 + rgbDig[i];
    5312 
    5313             /* No support for numbers > 32 bit for now. */           
    5314             DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
    5315             DEC_MID32(pDec) = (ULONG)0;
    5316             DEC_HI32(pDec) = (ULONG)0;
    5317 
    5318             /* The following is not working because of missing ULONG64 !! */
    5319 #if 0
    5320             carry = (ULONG)(tmp >> 32);
    5321             DEC_LO64(pDec)=tmp;
    5322             DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
    5323             tmp = (ULONG)DEC_MID32(pDec) * 10 + carry;
    5324             carry = (ULONG)(tmp >> 32);
    5325             DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
    5326             tmp = (ULONG)DEC_HI32(pDec) * 10 + carry;
    5327             DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
    5328 #endif
    5329 
    5330             if (tmp >> 32 & UI4_MAX)
    5331               {
    5332               VarNumFromParseNum_DecOverflow:
    5333                 TRACE("Overflow\n");
    5334                 DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
    5335                 return DISP_E_OVERFLOW;
    5336               }
    5337           }
    5338        
    5339         TRACE("Done... LO32: %x, MID32: %x, HI32: %x, DEC_LO64: %x, SignScale: %x, sign: %x\n",
    5340               DEC_LO32(pDec), DEC_MID32(pDec), DEC_HI32(pDec), DEC_LO64(pDec), DEC_SIGNSCALE(pDec), DEC_SIGN(pDec) );
    5341        
    5342         return S_OK;
    5343       }
    5344    
    5345     FIXME("%s: (..,dwVtBits=%lx,....), partial stub!\n", __FUNCTION__, dwVtBits);
    53464576        FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint);
    53474577        return E_FAIL;
    5348 } /* End of __WIN32OS2__ */
    5349 
    5350 #else
    5351 
    5352   /* Scale factors and limits for double arithmetic */
    5353   static const double dblMultipliers[11] = {
    5354     1.0, 10.0, 100.0, 1000.0, 10000.0, 100000.0,
    5355     1000000.0, 10000000.0, 100000000.0, 1000000000.0, 10000000000.0
    5356   };
    5357   static const double dblMinimums[11] = {
    5358     R8_MIN, R8_MIN*10.0, R8_MIN*100.0, R8_MIN*1000.0, R8_MIN*10000.0,
    5359     R8_MIN*100000.0, R8_MIN*1000000.0, R8_MIN*10000000.0,
    5360     R8_MIN*100000000.0, R8_MIN*1000000000.0, R8_MIN*10000000000.0
    5361   };
    5362   static const double dblMaximums[11] = {
    5363     R8_MAX, R8_MAX/10.0, R8_MAX/100.0, R8_MAX/1000.0, R8_MAX/10000.0,
    5364     R8_MAX/100000.0, R8_MAX/1000000.0, R8_MAX/10000000.0,
    5365     R8_MAX/100000000.0, R8_MAX/1000000000.0, R8_MAX/10000000000.0
    5366   };
    5367 
    5368   int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
    5369 
    5370   TRACE("(%p,%p,0x%lx,%p)\n", pNumprs, rgbDig, dwVtBits, pVarDst);
    5371 
    5372   if (pNumprs->nBaseShift)
    5373   {
    5374     /* nBaseShift indicates a hex or octal number */
    5375     ULONG64 ul64 = 0;
    5376     LONG64 l64;
    5377     int i;
    5378 
    5379     /* Convert the hex or octal number string into a UI64 */
    5380     for (i = 0; i < pNumprs->cDig; i++)
    5381     {
    5382       if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
    5383       {
    5384         TRACE("Overflow multiplying digits\n");
    5385         return DISP_E_OVERFLOW;
    5386       }
    5387       ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
    5388     }
    5389 
    5390     /* also make a negative representation */
    5391     l64=-ul64;
    5392 
    5393     /* Try signed and unsigned types in size order */
    5394     if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
    5395     {
    5396       V_VT(pVarDst) = VT_I1;
    5397       if (ul64 <= I1_MAX)
    5398           V_I1(pVarDst) = ul64;
    5399       else
    5400           V_I1(pVarDst) = l64;
    5401       return S_OK;
    5402     }
    5403     else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
    5404     {
    5405       V_VT(pVarDst) = VT_UI1;
    5406       V_UI1(pVarDst) = ul64;
    5407       return S_OK;
    5408     }
    5409     else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
    5410     {
    5411       V_VT(pVarDst) = VT_I2;
    5412       if (ul64 <= I2_MAX)
    5413           V_I2(pVarDst) = ul64;
    5414       else
    5415           V_I2(pVarDst) = l64;
    5416       return S_OK;
    5417     }
    5418     else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
    5419     {
    5420       V_VT(pVarDst) = VT_UI2;
    5421       V_UI2(pVarDst) = ul64;
    5422       return S_OK;
    5423     }
    5424     else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
    5425     {
    5426       V_VT(pVarDst) = VT_I4;
    5427       if (ul64 <= I4_MAX)
    5428           V_I4(pVarDst) = ul64;
    5429       else
    5430           V_I4(pVarDst) = l64;
    5431       return S_OK;
    5432     }
    5433     else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
    5434     {
    5435       V_VT(pVarDst) = VT_UI4;
    5436       V_UI4(pVarDst) = ul64;
    5437       return S_OK;
    5438     }
    5439     else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
    5440     {
    5441       V_VT(pVarDst) = VT_I8;
    5442       V_I8(pVarDst) = ul64;
    5443       return S_OK;
    5444     }
    5445     else if (dwVtBits & VTBIT_UI8)
    5446     {
    5447       V_VT(pVarDst) = VT_UI8;
    5448       V_UI8(pVarDst) = ul64;
    5449       return S_OK;
    5450     }
    5451     else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
    5452     {
    5453       V_VT(pVarDst) = VT_DECIMAL;
    5454       DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
    5455       DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
    5456       DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
    5457       return S_OK;
    5458     }
    5459     else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
    5460     {
    5461       V_VT(pVarDst) = VT_R4;
    5462       if (ul64 <= I4_MAX)
    5463           V_R4(pVarDst) = ul64;
    5464       else
    5465           V_R4(pVarDst) = l64;
    5466       return S_OK;
    5467     }
    5468     else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
    5469     {
    5470       V_VT(pVarDst) = VT_R8;
    5471       if (ul64 <= I4_MAX)
    5472           V_R8(pVarDst) = ul64;
    5473       else
    5474           V_R8(pVarDst) = l64;
    5475       return S_OK;
    5476     }
    5477     TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
    5478     return DISP_E_OVERFLOW;
    5479   }
    5480 
    5481   /* Count the number of relevant fractional and whole digits stored,
    5482    * And compute the divisor/multiplier to scale the number by.
    5483    */
    5484   if (pNumprs->nPwr10 < 0)
    5485   {
    5486     if (-pNumprs->nPwr10 >= pNumprs->cDig)
    5487     {
    5488       /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
    5489       wholeNumberDigits = 0;
    5490       fractionalDigits = pNumprs->cDig;
    5491       divisor10 = -pNumprs->nPwr10;
    5492     }
    5493     else
    5494     {
    5495       /* An exactly represented real number e.g. 1.024 */
    5496       wholeNumberDigits = pNumprs->cDig + pNumprs->nPwr10;
    5497       fractionalDigits = pNumprs->cDig - wholeNumberDigits;
    5498       divisor10 = pNumprs->cDig - wholeNumberDigits;
    5499     }
    5500   }
    5501   else if (pNumprs->nPwr10 == 0)
    5502   {
    5503     /* An exactly represented whole number e.g. 1024 */
    5504     wholeNumberDigits = pNumprs->cDig;
    5505     fractionalDigits = 0;
    5506   }
    5507   else /* pNumprs->nPwr10 > 0 */
    5508   {
    5509     /* A whole number followed by nPwr10 0's e.g. 102400 */
    5510     wholeNumberDigits = pNumprs->cDig;
    5511     fractionalDigits = 0;
    5512     multiplier10 = pNumprs->nPwr10;
    5513   }
    5514 
    5515   TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", pNumprs->cDig,
    5516         pNumprs->nPwr10, wholeNumberDigits, fractionalDigits);
    5517   TRACE("mult %d; div %d\n", multiplier10, divisor10);
    5518 
    5519   if (dwVtBits & (INTEGER_VTBITS|VTBIT_DECIMAL) &&
    5520       (!fractionalDigits || !(dwVtBits & (REAL_VTBITS|VTBIT_CY|VTBIT_DECIMAL))))
    5521   {
    5522     /* We have one or more integer output choices, and either:
    5523      *  1) An integer input value, or
    5524      *  2) A real number input value but no floating output choices.
    5525      * Alternately, we have a DECIMAL output available and an integer input.
    5526      *
    5527      * So, place the integer value into pVarDst, using the smallest type
    5528      * possible and preferring signed over unsigned types.
    5529      */
    5530     BOOL bOverflow = FALSE, bNegative;
    5531     ULONG64 ul64 = 0;
    5532     int i;
    5533 
    5534     /* Convert the integer part of the number into a UI8 */
    5535     for (i = 0; i < wholeNumberDigits; i++)
    5536     {
    5537       if (ul64 > (UI8_MAX / 10 - rgbDig[i]))
    5538       {
    5539         TRACE("Overflow multiplying digits\n");
    5540         bOverflow = TRUE;
    5541         break;
    5542       }
    5543       ul64 = ul64 * 10 + rgbDig[i];
    5544     }
    5545 
    5546     /* Account for the scale of the number */
    5547     if (!bOverflow && multiplier10)
    5548     {
    5549       for (i = 0; i < multiplier10; i++)
    5550       {
    5551         if (ul64 > (UI8_MAX / 10))
    5552         {
    5553           TRACE("Overflow scaling number\n");
    5554           bOverflow = TRUE;
    5555           break;
    5556         }
    5557         ul64 = ul64 * 10;
    5558       }
    5559     }
    5560 
    5561     /* If we have any fractional digits, round the value.
    5562      * Note we don't have to do this if divisor10 is < 1,
    5563      * because this means the fractional part must be < 0.5
    5564      */
    5565     if (!bOverflow && fractionalDigits && divisor10 > 0)
    5566     {
    5567       const BYTE* fracDig = rgbDig + wholeNumberDigits;
    5568       BOOL bAdjust = FALSE;
    5569 
    5570       TRACE("first decimal value is %d\n", *fracDig);
    5571 
    5572       if (*fracDig > 5)
    5573         bAdjust = TRUE; /* > 0.5 */
    5574       else if (*fracDig == 5)
    5575       {
    5576         for (i = 1; i < fractionalDigits; i++)
    5577         {
    5578           if (fracDig[i])
    5579           {
    5580             bAdjust = TRUE; /* > 0.5 */
    5581             break;
    5582           }
    5583         }
    5584         /* If exactly 0.5, round only odd values */
    5585         if (i == fractionalDigits && (ul64 & 1))
    5586           bAdjust = TRUE;
    5587       }
    5588 
    5589       if (bAdjust)
    5590       {
    5591         if (ul64 == UI8_MAX)
    5592         {
    5593           TRACE("Overflow after rounding\n");
    5594           bOverflow = TRUE;
    5595         }
    5596         ul64++;
    5597       }
    5598     }
    5599 
    5600     /* Zero is not a negative number */
    5601     bNegative = pNumprs->dwOutFlags & NUMPRS_NEG && ul64 ? TRUE : FALSE;
    5602 
    5603     TRACE("Integer value is %lld, bNeg %d\n", ul64, bNegative);
    5604 
    5605     /* For negative integers, try the signed types in size order */
    5606     if (!bOverflow && bNegative)
    5607     {
    5608       if (dwVtBits & (VTBIT_I1|VTBIT_I2|VTBIT_I4|VTBIT_I8))
    5609       {
    5610         if (dwVtBits & VTBIT_I1 && ul64 <= -I1_MIN)
    5611         {
    5612           V_VT(pVarDst) = VT_I1;
    5613           V_I1(pVarDst) = -ul64;
    5614           return S_OK;
    5615         }
    5616         else if (dwVtBits & VTBIT_I2 && ul64 <= -I2_MIN)
    5617         {
    5618           V_VT(pVarDst) = VT_I2;
    5619           V_I2(pVarDst) = -ul64;
    5620           return S_OK;
    5621         }
    5622         else if (dwVtBits & VTBIT_I4 && ul64 <= -((LONGLONG)I4_MIN))
    5623         {
    5624           V_VT(pVarDst) = VT_I4;
    5625           V_I4(pVarDst) = -ul64;
    5626           return S_OK;
    5627         }
    5628         else if (dwVtBits & VTBIT_I8 && ul64 <= (ULONGLONG)I8_MAX + 1)
    5629         {
    5630           V_VT(pVarDst) = VT_I8;
    5631           V_I8(pVarDst) = -ul64;
    5632           return S_OK;
    5633         }
    5634         else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
    5635         {
    5636           /* Decimal is only output choice left - fast path */
    5637           V_VT(pVarDst) = VT_DECIMAL;
    5638           DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_NEG,0);
    5639           DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
    5640           DEC_LO64(&V_DECIMAL(pVarDst)) = -ul64;
    5641           return S_OK;
    5642         }
    5643       }
    5644     }
    5645     else if (!bOverflow)
    5646     {
    5647       /* For positive integers, try signed then unsigned types in size order */
    5648       if (dwVtBits & VTBIT_I1 && ul64 <= I1_MAX)
    5649       {
    5650         V_VT(pVarDst) = VT_I1;
    5651         V_I1(pVarDst) = ul64;
    5652         return S_OK;
    5653       }
    5654       else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
    5655       {
    5656         V_VT(pVarDst) = VT_UI1;
    5657         V_UI1(pVarDst) = ul64;
    5658         return S_OK;
    5659       }
    5660       else if (dwVtBits & VTBIT_I2 && ul64 <= I2_MAX)
    5661       {
    5662         V_VT(pVarDst) = VT_I2;
    5663         V_I2(pVarDst) = ul64;
    5664         return S_OK;
    5665       }
    5666       else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
    5667       {
    5668         V_VT(pVarDst) = VT_UI2;
    5669         V_UI2(pVarDst) = ul64;
    5670         return S_OK;
    5671       }
    5672       else if (dwVtBits & VTBIT_I4 && ul64 <= I4_MAX)
    5673       {
    5674         V_VT(pVarDst) = VT_I4;
    5675         V_I4(pVarDst) = ul64;
    5676         return S_OK;
    5677       }
    5678       else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
    5679       {
    5680         V_VT(pVarDst) = VT_UI4;
    5681         V_UI4(pVarDst) = ul64;
    5682         return S_OK;
    5683       }
    5684       else if (dwVtBits & VTBIT_I8 && ul64 <= I8_MAX)
    5685       {
    5686         V_VT(pVarDst) = VT_I8;
    5687         V_I8(pVarDst) = ul64;
    5688         return S_OK;
    5689       }
    5690       else if (dwVtBits & VTBIT_UI8)
    5691       {
    5692         V_VT(pVarDst) = VT_UI8;
    5693         V_UI8(pVarDst) = ul64;
    5694         return S_OK;
    5695       }
    5696       else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
    5697       {
    5698         /* Decimal is only output choice left - fast path */
    5699         V_VT(pVarDst) = VT_DECIMAL;
    5700         DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
    5701         DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
    5702         DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
    5703         return S_OK;
    5704       }
    5705     }
    5706   }
    5707 
    5708   if (dwVtBits & REAL_VTBITS)
    5709   {
    5710     /* Try to put the number into a float or real */
    5711     BOOL bOverflow = FALSE, bNegative = pNumprs->dwOutFlags & NUMPRS_NEG;
    5712     double whole = 0.0;
    5713     int i;
    5714 
    5715     /* Convert the number into a double */
    5716     for (i = 0; i < pNumprs->cDig; i++)
    5717       whole = whole * 10.0 + rgbDig[i];
    5718 
    5719     TRACE("Whole double value is %16.16g\n", whole);
    5720 
    5721     /* Account for the scale */
    5722     while (multiplier10 > 10)
    5723     {
    5724       if (whole > dblMaximums[10])
    5725       {
    5726         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
    5727         bOverflow = TRUE;
    5728         break;
    5729       }
    5730       whole = whole * dblMultipliers[10];
    5731       multiplier10 -= 10;
    5732     }
    5733     if (multiplier10)
    5734     {
    5735       if (whole > dblMaximums[multiplier10])
    5736       {
    5737         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY);
    5738         bOverflow = TRUE;
    5739       }
    5740       else
    5741         whole = whole * dblMultipliers[multiplier10];
    5742     }
    5743 
    5744     TRACE("Scaled double value is %16.16g\n", whole);
    5745 
    5746     while (divisor10 > 10)
    5747     {
    5748       if (whole < dblMinimums[10])
    5749       {
    5750         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
    5751         bOverflow = TRUE;
    5752         break;
    5753       }
    5754       whole = whole / dblMultipliers[10];
    5755       divisor10 -= 10;
    5756     }
    5757     if (divisor10)
    5758     {
    5759       if (whole < dblMinimums[divisor10])
    5760       {
    5761         dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */
    5762         bOverflow = TRUE;
    5763       }
    5764       else
    5765         whole = whole / dblMultipliers[divisor10];
    5766     }
    5767     if (!bOverflow)
    5768       TRACE("Final double value is %16.16g\n", whole);
    5769 
    5770     if (dwVtBits & VTBIT_R4 &&
    5771         ((whole <= R4_MAX && whole >= R4_MIN) || whole == 0.0))
    5772     {
    5773       TRACE("Set R4 to final value\n");
    5774       V_VT(pVarDst) = VT_R4; /* Fits into a float */
    5775       V_R4(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
    5776       return S_OK;
    5777     }
    5778 
    5779     if (dwVtBits & VTBIT_R8)
    5780     {
    5781       TRACE("Set R8 to final value\n");
    5782       V_VT(pVarDst) = VT_R8; /* Fits into a double */
    5783       V_R8(pVarDst) = pNumprs->dwOutFlags & NUMPRS_NEG ? -whole : whole;
    5784       return S_OK;
    5785     }
    5786 
    5787     if (dwVtBits & VTBIT_CY)
    5788     {
    5789       if (SUCCEEDED(VarCyFromR8(bNegative ? -whole : whole, &V_CY(pVarDst))))
    5790       {
    5791         V_VT(pVarDst) = VT_CY; /* Fits into a currency */
    5792         TRACE("Set CY to final value\n");
    5793         return S_OK;
    5794       }
    5795       TRACE("Value Overflows CY\n");
    5796     }
    5797   }
    5798 
    5799   if (dwVtBits & VTBIT_DECIMAL)
    5800   {
    5801     int i;
    5802     ULONG carry;
    5803     ULONG64 tmp;
    5804     DECIMAL* pDec = &V_DECIMAL(pVarDst);
    5805 
    5806     DECIMAL_SETZERO(pDec);
    5807     DEC_LO32(pDec) = 0;
    5808 
    5809     if (pNumprs->dwOutFlags & NUMPRS_NEG)
    5810       DEC_SIGN(pDec) = DECIMAL_NEG;
    5811     else
    5812       DEC_SIGN(pDec) = DECIMAL_POS;
    5813 
    5814     /* Factor the significant digits */
    5815     for (i = 0; i < pNumprs->cDig; i++)
    5816     {
    5817       tmp = (ULONG64)DEC_LO32(pDec) * 10 + rgbDig[i];
    5818       carry = (ULONG)(tmp >> 32);
    5819       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
    5820       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
    5821       carry = (ULONG)(tmp >> 32);
    5822       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
    5823       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
    5824       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
    5825 
    5826       if (tmp >> 32 & UI4_MAX)
    5827       {
    5828 VarNumFromParseNum_DecOverflow:
    5829         TRACE("Overflow\n");
    5830         DEC_LO32(pDec) = DEC_MID32(pDec) = DEC_HI32(pDec) = UI4_MAX;
    5831         return DISP_E_OVERFLOW;
    5832       }
    5833     }
    5834 
    5835     /* Account for the scale of the number */
    5836     while (multiplier10 > 0)
    5837     {
    5838       tmp = (ULONG64)DEC_LO32(pDec) * 10;
    5839       carry = (ULONG)(tmp >> 32);
    5840       DEC_LO32(pDec) = (ULONG)(tmp & UI4_MAX);
    5841       tmp = (ULONG64)DEC_MID32(pDec) * 10 + carry;
    5842       carry = (ULONG)(tmp >> 32);
    5843       DEC_MID32(pDec) = (ULONG)(tmp & UI4_MAX);
    5844       tmp = (ULONG64)DEC_HI32(pDec) * 10 + carry;
    5845       DEC_HI32(pDec) = (ULONG)(tmp & UI4_MAX);
    5846 
    5847       if (tmp >> 32 & UI4_MAX)
    5848         goto VarNumFromParseNum_DecOverflow;
    5849       multiplier10--;
    5850     }
    5851     DEC_SCALE(pDec) = divisor10;
    5852 
    5853     V_VT(pVarDst) = VT_DECIMAL;
    5854     return S_OK;
    5855   }
    5856   return DISP_E_OVERFLOW; /* No more output choices */
    5857 }
    5858 #endif
     4578}
     4579
    58594580
    58604581/**********************************************************************
     
    58754596    return E_NOTIMPL;
    58764597}
    5877 
    5878 /**********************************************************************
    5879  *              VarFormatNumber [OLEAUT32.107]
    5880  */
    5881 HRESULT WINAPI VarFormatNumber(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
    5882 {
    5883   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    5884   return E_NOTIMPL;
    5885 }
    5886 
    5887 
    5888 /**********************************************************************
    5889  *              VarFormatPercent [OLEAUT32.117]
    5890  */
    5891 HRESULT WINAPI VarFormatPercent(LPVARIANT pvarIn, int iNumDig, int iIncLead, int iUseParens, int iGroup, ULONG dwFlags, BSTR* pbstrOut)
    5892 {
    5893   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    5894   return E_NOTIMPL;
    5895 }
    5896 
    5897 
    5898 /**********************************************************************
    5899  *              VarWeekdayName [OLEAUT32.128]
    5900  */
    5901 HRESULT WINAPI VarWeekdayName(int iWeekday, int fAbbrey, int iFirstDay, ULONG dwFlags, BSTR* pbstrOut)
    5902 {
    5903   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    5904   return E_NOTIMPL;
    5905 }
    5906 
    5907 
    5908 /**********************************************************************
    5909  *              VarMonthName [OLEAUT32.129]
    5910  */
    5911 HRESULT WINAPI VarMonthName(int iMonth, int fAbbrey, ULONG dwFlags, BSTR* pbstrOut)
    5912 {
    5913   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    5914   return E_NOTIMPL;
    5915 }
    5916 
    59174598
    59184599/**********************************************************************
     
    63395020    case VT_UI4  : rVal = V_UNION(right,ulVal); break;
    63405021    case VT_UINT : rVal = V_UNION(right,ulVal); break;
    6341 #ifdef __WIN32OS2__
    6342     case VT_R8   : rVal = V_UNION(right,dblVal); break;
    6343 #endif
    63445022    default: rOk = FALSE;
    63455023    }
     
    64295107
    64305108/**********************************************************************
    6431  *              VarOr [OLEAUT32.157]
    6432  *
    6433  * Perform a logical or (OR) operation on two variants.
    6434  *
    6435  * PARAMS
    6436  *  pVarLeft  [I] First variant
    6437  *  pVarRight [I] Variant to OR with pVarLeft
    6438  *  pVarOut   [O] Destination for OR result
    6439  *
    6440  * RETURNS
    6441  *  Success: S_OK. pVarOut contains the result of the operation with its type
    6442  *           taken from the table listed under VarXor().
    6443  *  Failure: An HRESULT error code indicating the error.
    6444  *
    6445  * NOTES
    6446  *  See the Notes section of VarXor() for further information.
    6447  */
    6448 HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
    6449 {
    6450   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6451   return E_NOTIMPL;
    6452 
    6453 
    6454 #if 0
    6455     VARTYPE vt = VT_I4;
    6456     VARIANT varLeft, varRight, varStr;
    6457     HRESULT hRet;
    6458 
    6459 #if 0
    6460     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft),
    6461           debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight),
    6462           debugstr_VF(pVarRight), pVarOut);
    6463 #endif
    6464     if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) ||
    6465         V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN ||
    6466         V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH ||
    6467         V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD)
    6468         return DISP_E_BADVARTYPE;
    6469 
    6470     V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY;
    6471 
    6472     if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL)
    6473     {
    6474         /* NULL OR Zero is NULL, NULL OR value is value */
    6475         if (V_VT(pVarLeft) == VT_NULL)
    6476             pVarLeft = pVarRight; /* point to the non-NULL var */
    6477 
    6478         V_VT(pVarOut) = VT_NULL;
    6479         V_I4(pVarOut) = 0;
    6480 
    6481         switch (V_VT(pVarLeft))
    6482         {
    6483         case VT_DATE: case VT_R8:
    6484             if (V_R8(pVarLeft))
    6485                 goto VarOr_AsEmpty;
    6486             return S_OK;
    6487         case VT_BOOL:
    6488             if (V_BOOL(pVarLeft))
    6489                 *pVarOut = *pVarLeft;
    6490             return S_OK;
    6491          case VT_I2: case VT_UI2:
    6492             if (V_I2(pVarLeft))
    6493                 goto VarOr_AsEmpty;
    6494             return S_OK;
    6495         case VT_I1:
    6496             if (V_I1(pVarLeft))
    6497                 goto VarOr_AsEmpty;
    6498             return S_OK;
    6499         case VT_UI1:
    6500             if (V_UI1(pVarLeft))
    6501                 *pVarOut = *pVarLeft;
    6502             return S_OK;
    6503         case VT_R4:
    6504             if (V_R4(pVarLeft))
    6505                 goto VarOr_AsEmpty;
    6506             return S_OK;
    6507         case VT_I4: case VT_UI4: case VT_INT: case VT_UINT:
    6508             if (V_I4(pVarLeft))
    6509                 goto VarOr_AsEmpty;
    6510             return S_OK;
    6511         case VT_CY:
    6512             if (V_CY(pVarLeft).int64)
    6513                 goto VarOr_AsEmpty;
    6514             return S_OK;
    6515         case VT_I8: case VT_UI8:
    6516             if (V_I8(pVarLeft))
    6517                 goto VarOr_AsEmpty;
    6518             return S_OK;
    6519         case VT_DECIMAL:
    6520             if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft)))
    6521                 goto VarOr_AsEmpty;
    6522             return S_OK;
    6523         case VT_BSTR:
    6524         {
    6525             VARIANT_BOOL b;
    6526 
    6527             if (!V_BSTR(pVarLeft))
    6528                 return DISP_E_BADVARTYPE;
    6529 
    6530             hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b);
    6531             if (SUCCEEDED(hRet) && b)
    6532             {
    6533                 V_VT(pVarOut) = VT_BOOL;
    6534                 V_BOOL(pVarOut) = b;
    6535             }
    6536             return hRet;
    6537         }
    6538         case VT_NULL: case VT_EMPTY:
    6539             V_VT(pVarOut) = VT_NULL;
    6540             return S_OK;
    6541         default:
    6542             return DISP_E_BADVARTYPE;
    6543         }
    6544     }
    6545 
    6546     if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY)
    6547     {
    6548         if (V_VT(pVarLeft) == VT_EMPTY)
    6549             pVarLeft = pVarRight; /* point to the non-EMPTY var */
    6550 
    6551 VarOr_AsEmpty:
    6552         /* Since one argument is empty (0), OR'ing it with the other simply
    6553          * gives the others value (as 0|x => x). So just convert the other
    6554          * argument to the required result type.
    6555          */
    6556         switch (V_VT(pVarLeft))
    6557         {
    6558         case VT_BSTR:
    6559             if (!V_BSTR(pVarLeft))
    6560                 return DISP_E_BADVARTYPE;
    6561 
    6562             hRet = VariantCopy(&varStr, pVarLeft);
    6563             if (FAILED(hRet))
    6564                 goto VarOr_Exit;
    6565             pVarLeft = &varStr;
    6566             hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
    6567             if (FAILED(hRet))
    6568                 goto VarOr_Exit;
    6569             /* Fall Through ... */
    6570         case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2:
    6571             V_VT(pVarOut) = VT_I2;
    6572             break;
    6573         case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8:
    6574         case VT_I1: case VT_UI2: case VT_I4: case VT_UI4:
    6575         case VT_INT: case VT_UINT: case VT_UI8:
    6576             V_VT(pVarOut) = VT_I4;
    6577             break;
    6578         case VT_I8:
    6579             V_VT(pVarOut) = VT_I8;
    6580             break;
    6581         default:
    6582             return DISP_E_BADVARTYPE;
    6583         }
    6584         hRet = VariantCopy(&varLeft, pVarLeft);
    6585         if (FAILED(hRet))
    6586             goto VarOr_Exit;
    6587         pVarLeft = &varLeft;
    6588         hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut));
    6589         goto VarOr_Exit;
    6590     }
    6591 
    6592     if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL)
    6593     {
    6594         V_VT(pVarOut) = VT_BOOL;
    6595         V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight);
    6596         return S_OK;
    6597     }
    6598 
    6599     if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1)
    6600     {
    6601         V_VT(pVarOut) = VT_UI1;
    6602         V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight);
    6603         return S_OK;
    6604     }
    6605 
    6606     if (V_VT(pVarLeft) == VT_BSTR)
    6607     {
    6608         hRet = VariantCopy(&varStr, pVarLeft);
    6609         if (FAILED(hRet))
    6610             goto VarOr_Exit;
    6611         pVarLeft = &varStr;
    6612         hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL);
    6613         if (FAILED(hRet))
    6614             goto VarOr_Exit;
    6615     }
    6616 
    6617     if (V_VT(pVarLeft) == VT_BOOL &&
    6618         (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR))
    6619     {
    6620         vt = VT_BOOL;
    6621     }
    6622     else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 ||
    6623         V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) &&
    6624         (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 ||
    6625         V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR))
    6626     {
    6627         vt = VT_I2;
    6628     }
    6629     else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8)
    6630     {
    6631         if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT)
    6632             return DISP_E_TYPEMISMATCH;
    6633         vt = VT_I8;
    6634     }
    6635 
    6636     hRet = VariantCopy(&varLeft, pVarLeft);
    6637     if (FAILED(hRet))
    6638         goto VarOr_Exit;
    6639 
    6640     hRet = VariantCopy(&varRight, pVarRight);
    6641     if (FAILED(hRet))
    6642         goto VarOr_Exit;
    6643 
    6644     if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4)
    6645         V_VT(&varLeft) = VT_I4; /* Don't overflow */
    6646     else
    6647     {
    6648         double d;
    6649 
    6650         if (V_VT(&varLeft) == VT_BSTR &&
    6651             FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d)))
    6652             hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL);
    6653         if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt)
    6654             hRet = VariantChangeType(&varLeft, &varLeft, 0, vt);
    6655         if (FAILED(hRet))
    6656             goto VarOr_Exit;
    6657     }
    6658 
    6659     if (vt == VT_I4 && V_VT(&varRight) == VT_UI4)
    6660         V_VT(&varRight) = VT_I4; /* Don't overflow */
    6661     else
    6662     {
    6663         double d;
    6664 
    6665         if (V_VT(&varRight) == VT_BSTR &&
    6666             FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d)))
    6667             hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL);
    6668         if (SUCCEEDED(hRet) && V_VT(&varRight) != vt)
    6669             hRet = VariantChangeType(&varRight, &varRight, 0, vt);
    6670         if (FAILED(hRet))
    6671             goto VarOr_Exit;
    6672     }
    6673 
    6674     V_VT(pVarOut) = vt;
    6675     if (vt == VT_I8)
    6676     {
    6677         V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight);
    6678     }
    6679     else if (vt == VT_I4)
    6680     {
    6681         V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight);
    6682     }
    6683     else
    6684     {
    6685         V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight);
    6686     }
    6687 
    6688 VarOr_Exit:
    6689     VariantClear(&varStr);
    6690     VariantClear(&varLeft);
    6691     VariantClear(&varRight);
    6692     return hRet;
    6693 #endif
    6694 }
    6695 
    6696 
    6697 /**********************************************************************
    6698  *              VarXor [OLEAUT32.167]
    6699  */
    6700 HRESULT WINAPI VarXor(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
    6701 {
    6702   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6703 
    6704   return E_NOTIMPL;
    6705 }
    6706 
    6707 /**********************************************************************
    67085109 *              VarNot [OLEAUT32.174]
    67095110 *
     
    67325133    TRACE("rc=%d, Result:\n", (int) rc);
    67335134    dump_Variant(result);
    6734     return rc;
    6735 }
    6736 
    6737 /**********************************************************************
    6738  *              VarNeg [OLEAUT32.173]
    6739  *
    6740  * Negate the value of a variant.
    6741  *
    6742  * PARAMS
    6743  *  pVarIn  [I] Source variant
    6744  *  pVarOut [O] Destination for converted value
    6745  *
    6746  * RETURNS
    6747  *  Success: S_OK. pVarOut contains the converted value.
    6748  *  Failure: An HRESULT error code indicating the error.
    6749  *
    6750  * NOTES
    6751  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
    6752  *    according to the following table:
    6753  *| Input Type       Output Type
    6754  *| ----------       -----------
    6755  *|  VT_EMPTY         VT_I2
    6756  *|  VT_UI1           VT_I2
    6757  *|  VT_BOOL          VT_I2
    6758  *|  VT_BSTR          VT_R8
    6759  *|  All Others       Unchanged (unless promoted)
    6760  *  - Where the negated value of a variant does not fit in its base type, the type
    6761  *    is promoted according to the following table:
    6762  *| Input Type       Promoted To
    6763  *| ----------       -----------
    6764  *|   VT_I2            VT_I4
    6765  *|   VT_I4            VT_R8
    6766  *|   VT_I8            VT_R8
    6767  *  - The native version of this function returns DISP_E_BADVARTYPE for valid
    6768  *    variant types that cannot be negated, and returns DISP_E_TYPEMISMATCH
    6769  *    for types which are not valid. Since this is in contravention of the
    6770  *    meaning of those error codes and unlikely to be relied on by applications,
    6771  *    this implementation returns errors consistent with the other high level
    6772  *    variant math functions.
    6773  */
    6774 HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut)
    6775 {
    6776   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6777   return E_NOTIMPL;
    6778 }
    6779 
    6780 /**********************************************************************
    6781  * VarAbs [OLEAUT32.168]
    6782  *
    6783  * Convert a variant to its absolute value.
    6784  *
    6785  * PARAMS
    6786  *  pVarIn  [I] Source variant
    6787  *  pVarOut [O] Destination for converted value
    6788  *
    6789  * RETURNS
    6790  *  Success: S_OK. pVarOut contains the absolute value of pVarIn.
    6791  *  Failure: An HRESULT error code indicating the error.
    6792  *
    6793  * NOTES
    6794  *  - This function does not process by-reference variants.
    6795  *  - The type of the value stored in pVarOut depends on the type of pVarIn,
    6796  *    according to the following table:
    6797  *| Input Type       Output Type
    6798  *| ----------       -----------
    6799  *| VT_BOOL          VT_I2
    6800  *| VT_BSTR          VT_R8
    6801  *| (All others)     Unchanged
    6802  */
    6803 HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut)
    6804 {
    6805   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6806   return E_NOTIMPL;
    6807 }
    6808 
    6809 /**********************************************************************
    6810  *              VarFix [OLEAUT32.169]
    6811  */
    6812 HRESULT WINAPI VarFix(LPVARIANT pvarIn, LPVARIANT pvarResult)
    6813 {
    6814   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6815   return E_NOTIMPL;
    6816 }
    6817 
    6818 /**********************************************************************
    6819  *              VarInt [OLEAUT32.172]
    6820  */
    6821 HRESULT WINAPI VarInt(LPVARIANT pvarIn, LPVARIANT pvarResult)
    6822 {
    6823   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6824   return E_NOTIMPL;
    6825 }
    6826 
    6827 /**********************************************************************
    6828  *              VarImp [OLEAUT32.154]
    6829  */
    6830 HRESULT WINAPI VarImp(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
    6831 {
    6832   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6833   return E_NOTIMPL;
    6834 }
    6835 
    6836 /**********************************************************************
    6837  *              VarMod [OLEAUT32.155]
    6838  */
    6839 HRESULT WINAPI VarMod(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
    6840 {
    6841   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6842   return E_NOTIMPL;
    6843 }
    6844 
    6845 /**********************************************************************
    6846  *              VarEqv [OLEAUT32.152]
    6847  *
    6848  * Determine if two variants contain the same value.
    6849  *
    6850  * PARAMS
    6851  *  pVarLeft  [I] First variant to compare
    6852  *  pVarRight [I] Variant to compare to pVarLeft
    6853  *  pVarOut   [O] Destination for comparison result
    6854  *
    6855  * RETURNS
    6856  *  Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE
    6857  *           if equivalent or non-zero otherwise.
    6858  *  Failure: An HRESULT error code indicating the error.
    6859  *
    6860  * NOTES
    6861  *  - This function simply calls VarXor() on pVarLeft and pVarRight and inverts
    6862  *    the result.
    6863  */
    6864 HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut)
    6865 {
    6866   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6867   return E_NOTIMPL;
    6868 }
    6869 
    6870 
    6871 /**********************************************************************
    6872  *              VarIdiv [OLEAUT32.153]
    6873  */
    6874 HRESULT WINAPI VarIdiv(LPVARIANT pvarLeft, LPVARIANT pvarRight, LPVARIANT pvarResult)
    6875 {
    6876   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6877 
    6878   return E_NOTIMPL;
    6879 }
    6880 
    6881 /**********************************************************************
    6882  *              VarRound [OLEAUT32.175]
    6883  */
    6884 HRESULT VarRound(LPVARIANT  pvarIn, INT cDecimals, LPVARIANT  pvarResult)
    6885 {
    6886   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    6887 
    6888   return E_NOTIMPL;
    6889 }
    6890 
    6891 /**********************************************************************
    6892  *              VarPow [OLEAUT32.158]
    6893  *
    6894  */
    6895 HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
    6896 {
    6897     HRESULT hr;
    6898     VARIANT dl,dr;
    6899 
    6900 #if 0
    6901     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), debugstr_VF(left),
    6902           right, debugstr_VT(right), debugstr_VF(right), result);
    6903 #endif
    6904 
    6905     hr = VariantChangeType(&dl,left,0,VT_R8);
    6906     if (!SUCCEEDED(hr)) {
    6907         ERR("Could not change passed left argument to VT_R8, handle it differently.\n");
    6908         return E_FAIL;
    6909     }
    6910     hr = VariantChangeType(&dr,right,0,VT_R8);
    6911     if (!SUCCEEDED(hr)) {
    6912         ERR("Could not change passed right argument to VT_R8, handle it differently.\n");
    6913         return E_FAIL;
    6914     }
    6915     V_VT(result) = VT_R8;
    6916     V_R8(result) = pow(V_R8(&dl),V_R8(&dr));
    6917     return S_OK;
    6918 }
    6919 
    6920 /**********************************************************************
    6921  *              VarAdd [OLEAUT32.141]
    6922  * FIXME: From MSDN: If ... Then
    6923  * Both expressions are of the string type Concatenated.
    6924  * One expression is a string type and the other a character Addition.
    6925  * One expression is numeric and the other is a string Addition.
    6926  * Both expressions are numeric Addition.
    6927  * Either expression is NULL NULL is returned.
    6928  * Both expressions are empty  Integer subtype is returned.
    6929  *
    6930  */
    6931 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
    6932 {
    6933     HRESULT rc = E_FAIL;
    6934 
    6935 #if 0
    6936     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
    6937           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
    6938 #endif
    6939 
    6940     if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
    6941         return VariantCopy(result,right);
    6942 
    6943     if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
    6944         return VariantCopy(result,left);
    6945 
    6946     /* check if we add doubles */
    6947     if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
    6948         BOOL         lOk        = TRUE;
    6949         BOOL         rOk        = TRUE;
    6950         double       lVal = -1;
    6951         double       rVal = -1;
    6952         double       res  = -1;
    6953 
    6954         lOk = TRUE;
    6955         switch (V_VT(left)&VT_TYPEMASK) {
    6956         case VT_I1   : lVal = V_UNION(left,cVal);   break;
    6957         case VT_I2   : lVal = V_UNION(left,iVal);   break;
    6958         case VT_I4   : lVal = V_UNION(left,lVal);   break;
    6959         case VT_INT  : lVal = V_UNION(left,lVal);   break;
    6960         case VT_UI1  : lVal = V_UNION(left,bVal);   break;
    6961         case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
    6962         case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
    6963         case VT_UINT : lVal = V_UNION(left,ulVal);  break;
    6964         case VT_R4   : lVal = V_UNION(left,fltVal);  break;
    6965         case VT_R8   : lVal = V_UNION(left,dblVal);  break;
    6966         case VT_NULL : lVal = 0.0;  break;
    6967         default: lOk = FALSE;
    6968         }
    6969 
    6970         rOk = TRUE;
    6971         switch (V_VT(right)&VT_TYPEMASK) {
    6972         case VT_I1   : rVal = V_UNION(right,cVal);  break;
    6973         case VT_I2   : rVal = V_UNION(right,iVal);  break;
    6974         case VT_I4   : rVal = V_UNION(right,lVal);  break;
    6975         case VT_INT  : rVal = V_UNION(right,lVal);  break;
    6976         case VT_UI1  : rVal = V_UNION(right,bVal);  break;
    6977         case VT_UI2  : rVal = V_UNION(right,uiVal); break;
    6978         case VT_UI4  : rVal = V_UNION(right,ulVal); break;
    6979         case VT_UINT : rVal = V_UNION(right,ulVal); break;
    6980         case VT_R4   : rVal = V_UNION(right,fltVal);break;
    6981         case VT_R8   : rVal = V_UNION(right,dblVal);break;
    6982         case VT_NULL : rVal = 0.0; break;
    6983         default: rOk = FALSE;
    6984         }
    6985 
    6986         if (lOk && rOk) {
    6987             res = (lVal + rVal);
    6988             V_VT(result) = VT_R8;
    6989             V_UNION(result,dblVal)  = res;
    6990             rc = S_OK;
    6991         } else {
    6992             FIXME("Unhandled type pair %d / %d in double addition.\n",
    6993                 (V_VT(left)&VT_TYPEMASK),
    6994                 (V_VT(right)&VT_TYPEMASK)
    6995             );
    6996         }
    6997         return rc;
    6998     }
    6999 
    7000     /* now check if we add floats. VT_R8 can no longer happen here! */
    7001     if (((V_VT(left)&VT_TYPEMASK) == VT_R4) || ((V_VT(right)&VT_TYPEMASK) == VT_R4)) {
    7002         BOOL         lOk        = TRUE;
    7003         BOOL         rOk        = TRUE;
    7004         float        lVal = -1;
    7005         float        rVal = -1;
    7006         float        res  = -1;
    7007 
    7008         lOk = TRUE;
    7009         switch (V_VT(left)&VT_TYPEMASK) {
    7010         case VT_I1   : lVal = V_UNION(left,cVal);   break;
    7011         case VT_I2   : lVal = V_UNION(left,iVal);   break;
    7012         case VT_I4   : lVal = V_UNION(left,lVal);   break;
    7013         case VT_INT  : lVal = V_UNION(left,lVal);   break;
    7014         case VT_UI1  : lVal = V_UNION(left,bVal);   break;
    7015         case VT_UI2  : lVal = V_UNION(left,uiVal);  break;
    7016         case VT_UI4  : lVal = V_UNION(left,ulVal);  break;
    7017         case VT_UINT : lVal = V_UNION(left,ulVal);  break;
    7018         case VT_R4   : lVal = V_UNION(left,fltVal);  break;
    7019         case VT_NULL : lVal = 0.0;  break;
    7020         default: lOk = FALSE;
    7021         }
    7022 
    7023         rOk = TRUE;
    7024         switch (V_VT(right)&VT_TYPEMASK) {
    7025         case VT_I1   : rVal = V_UNION(right,cVal);  break;
    7026         case VT_I2   : rVal = V_UNION(right,iVal);  break;
    7027         case VT_I4   : rVal = V_UNION(right,lVal);  break;
    7028         case VT_INT  : rVal = V_UNION(right,lVal);  break;
    7029         case VT_UI1  : rVal = V_UNION(right,bVal);  break;
    7030         case VT_UI2  : rVal = V_UNION(right,uiVal); break;
    7031         case VT_UI4  : rVal = V_UNION(right,ulVal); break;
    7032         case VT_UINT : rVal = V_UNION(right,ulVal); break;
    7033         case VT_R4   : rVal = V_UNION(right,fltVal);break;
    7034         case VT_NULL : rVal = 0.0; break;
    7035         default: rOk = FALSE;
    7036         }
    7037 
    7038         if (lOk && rOk) {
    7039             res = (lVal + rVal);
    7040             V_VT(result) = VT_R4;
    7041             V_UNION(result,fltVal)  = res;
    7042             rc = S_OK;
    7043         } else {
    7044             FIXME("Unhandled type pair %d / %d in float addition.\n",
    7045                 (V_VT(left)&VT_TYPEMASK),
    7046                 (V_VT(right)&VT_TYPEMASK)
    7047             );
    7048         }
    7049         return rc;
    7050     }
    7051 
    7052     /* Handle strings as concat */
    7053     if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
    7054         (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
    7055         V_VT(result) = VT_BSTR;
    7056         return VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
    7057     } else {
    7058 
    7059         /* Integers */
    7060         BOOL         lOk        = TRUE;
    7061         BOOL         rOk        = TRUE;
    7062         LONGLONG     lVal = -1;
    7063         LONGLONG     rVal = -1;
    7064         LONGLONG     res  = -1;
    7065         int          resT = 0; /* Testing has shown I2 + I2 == I2, all else
    7066                                   becomes I4                                */
    7067 
    7068         lOk = TRUE;
    7069         switch (V_VT(left)&VT_TYPEMASK) {
    7070         case VT_I1   : lVal = V_UNION(left,cVal);  resT=VT_I4; break;
    7071         case VT_I2   : lVal = V_UNION(left,iVal);  resT=VT_I2; break;
    7072         case VT_I4   : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
    7073         case VT_INT  : lVal = V_UNION(left,lVal);  resT=VT_I4; break;
    7074         case VT_UI1  : lVal = V_UNION(left,bVal);  resT=VT_I4; break;
    7075         case VT_UI2  : lVal = V_UNION(left,uiVal); resT=VT_I4; break;
    7076         case VT_UI4  : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
    7077         case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break;
    7078         case VT_NULL : lVal = 0; resT = VT_I4; break;
    7079         default: lOk = FALSE;
    7080         }
    7081 
    7082         rOk = TRUE;
    7083         switch (V_VT(right)&VT_TYPEMASK) {
    7084         case VT_I1   : rVal = V_UNION(right,cVal);  resT=VT_I4; break;
    7085         case VT_I2   : rVal = V_UNION(right,iVal);  resT=max(VT_I2, resT); break;
    7086         case VT_I4   : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
    7087         case VT_INT  : rVal = V_UNION(right,lVal);  resT=VT_I4; break;
    7088         case VT_UI1  : rVal = V_UNION(right,bVal);  resT=VT_I4; break;
    7089         case VT_UI2  : rVal = V_UNION(right,uiVal); resT=VT_I4; break;
    7090         case VT_UI4  : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
    7091         case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break;
    7092         case VT_NULL : rVal = 0; resT=VT_I4; break;
    7093         default: rOk = FALSE;
    7094         }
    7095 
    7096         if (lOk && rOk) {
    7097             res = (lVal + rVal);
    7098             V_VT(result) = resT;
    7099             switch (resT) {
    7100             case VT_I2   : V_UNION(result,iVal)  = res; break;
    7101             case VT_I4   : V_UNION(result,lVal)  = res; break;
    7102             default:
    7103                 FIXME("Unexpected result variant type %x\n", resT);
    7104                 V_UNION(result,lVal)  = res;
    7105             }
    7106             rc = S_OK;
    7107 
    7108         } else {
    7109             FIXME("unimplemented part (0x%x + 0x%x)\n",V_VT(left), V_VT(right));
    7110         }
    7111     }
    7112 #if 0
    7113     TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
    7114           debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
    7115 #endif
    7116     return rc;
    7117 }
    7118 
    7119 /**********************************************************************
    7120  *              VarSub [OLEAUT32.159]
    7121  *
    7122  */
    7123 HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
    7124 {
    7125     HRESULT rc = E_FAIL;
    7126     VARTYPE lvt,rvt,resvt;
    7127     VARIANT lv,rv;
    7128     BOOL found;
    7129 
    7130 #if 0
    7131     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
    7132           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
    7133 #endif
    7134 
    7135     VariantInit(&lv);VariantInit(&rv);
    7136     lvt = V_VT(left)&VT_TYPEMASK;
    7137     rvt = V_VT(right)&VT_TYPEMASK;
    7138     found = FALSE;resvt = VT_VOID;
    7139     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_DATE)|(1<<VT_R4)|(1<<VT_R8))) {
    7140         found = TRUE;
    7141         resvt = VT_R8;
    7142     }
    7143     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)))) {
    7144         found = TRUE;
    7145         resvt = VT_I4;
    7146     }
    7147     if (!found) {
    7148         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
    7149         return E_FAIL;
    7150     }
    7151     rc = VariantChangeType(&lv, left, 0, resvt);
    7152     if (FAILED(rc)) {
    7153         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
    7154         return rc;
    7155     }
    7156     rc = VariantChangeType(&rv, right, 0, resvt);
    7157     if (FAILED(rc)) {
    7158         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
    7159         return rc;
    7160     }
    7161     switch (resvt) {
    7162     case VT_R8:
    7163         V_VT(result) = resvt;
    7164         V_R8(result) = V_R8(&lv) - V_R8(&rv);
    7165         rc = S_OK;
    7166         break;
    7167     case VT_I4:
    7168         V_VT(result) = resvt;
    7169         V_I4(result) = V_I4(&lv) - V_I4(&rv);
    7170         rc = S_OK;
    7171         break;
    7172     }
    7173 #if 0
    7174     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
    7175           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
    7176 #endif
    7177     return rc;
    7178 }
    7179 
    7180 
    7181 /**********************************************************************
    7182  *              VarDiv [OLEAUT32.143]
    7183  *
    7184  */
    7185 HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
    7186 {
    7187     HRESULT rc = E_FAIL;
    7188     VARTYPE lvt,rvt,resvt;
    7189     VARIANT lv,rv;
    7190     BOOL found;
    7191 
    7192 #if 0
    7193     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
    7194           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
    7195 #endif
    7196 
    7197     VariantInit(&lv);VariantInit(&rv);
    7198     lvt = V_VT(left)&VT_TYPEMASK;
    7199     rvt = V_VT(right)&VT_TYPEMASK;
    7200     found = FALSE;resvt = VT_VOID;
    7201     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
    7202         found = TRUE;
    7203         resvt = VT_R8;
    7204     }
    7205     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)))) {
    7206         found = TRUE;
    7207         resvt = VT_I4;
    7208     }
    7209     if (!found) {
    7210         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
    7211         return E_FAIL;
    7212     }
    7213     rc = VariantChangeType(&lv, left, 0, resvt);
    7214     if (FAILED(rc)) {
    7215         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
    7216         return rc;
    7217     }
    7218     rc = VariantChangeType(&rv, right, 0, resvt);
    7219     if (FAILED(rc)) {
    7220         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
    7221         return rc;
    7222     }
    7223     switch (resvt) {
    7224     case VT_R8:
    7225         V_VT(result) = resvt;
    7226         V_R8(result) = V_R8(&lv) / V_R8(&rv);
    7227         rc = S_OK;
    7228         break;
    7229     case VT_I4:
    7230         V_VT(result) = resvt;
    7231         V_I4(result) = V_I4(&lv) / V_I4(&rv);
    7232         rc = S_OK;
    7233         break;
    7234     }
    7235 #if 0
    7236     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
    7237           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
    7238 #endif
    7239     return rc;
    7240 }
    7241 
    7242 /**********************************************************************
    7243  *              VarMul [OLEAUT32.156]
    7244  *
    7245  */
    7246 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
    7247 {
    7248     HRESULT rc = E_FAIL;
    7249     VARTYPE lvt,rvt,resvt;
    7250     VARIANT lv,rv;
    7251     BOOL found;
    7252 #if 0
    7253     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
    7254           debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
    7255 #endif
    7256     VariantInit(&lv);VariantInit(&rv);
    7257     lvt = V_VT(left)&VT_TYPEMASK;
    7258     rvt = V_VT(right)&VT_TYPEMASK;
    7259     found = FALSE;resvt=VT_VOID;
    7260     if (((1<<lvt) | (1<<rvt)) & ((1<<VT_R4)|(1<<VT_R8))) {
    7261         found = TRUE;
    7262         resvt = VT_R8;
    7263     }
    7264     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)))) {
    7265         found = TRUE;
    7266         resvt = VT_I4;
    7267     }
    7268     if (!found) {
    7269         FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
    7270         return E_FAIL;
    7271     }
    7272     rc = VariantChangeType(&lv, left, 0, resvt);
    7273     if (FAILED(rc)) {
    7274         FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
    7275         return rc;
    7276     }
    7277     rc = VariantChangeType(&rv, right, 0, resvt);
    7278     if (FAILED(rc)) {
    7279         FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
    7280         return rc;
    7281     }
    7282     switch (resvt) {
    7283     case VT_R8:
    7284         V_VT(result) = resvt;
    7285         V_R8(result) = V_R8(&lv) * V_R8(&rv);
    7286         rc = S_OK;
    7287         break;
    7288     case VT_I4:
    7289         V_VT(result) = resvt;
    7290         V_I4(result) = V_I4(&lv) * V_I4(&rv);
    7291         rc = S_OK;
    7292         break;
    7293     }
    7294 #if 0
    7295     TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
    7296           debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
    7297 #endif
    72985135    return rc;
    72995136}
     
    77375574    return rc;
    77385575}
    7739 
    7740 
    7741 /**********************************************************************
    7742  *              VarDecAdd [OLEAUT32.177]
    7743  */
    7744 HRESULT WINAPI VarDecAdd(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
    7745 {
    7746   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7747   return E_NOTIMPL;
    7748 }
    7749 
    7750 /**********************************************************************
    7751  *              VarDecSub [OLEAUT32.181]
    7752  */
    7753 HRESULT WINAPI VarDecSub(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
    7754 {
    7755   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7756   return E_NOTIMPL;
    7757 }
    7758 
    7759 /**********************************************************************
    7760  *              VarDecMul [OLEAUT32.179]
    7761  */
    7762 HRESULT WINAPI VarDecMul(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
    7763 {
    7764   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7765   return E_NOTIMPL;
    7766 }
    7767 
    7768 /**********************************************************************
    7769  *              VarDecRound [OLEAUT32.203]
    7770  */
    7771 HRESULT WINAPI VarDecRound(LPDECIMAL pdecIn, int iDecimals, LPDECIMAL  pdecResult)
    7772 {
    7773   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7774   return E_NOTIMPL;
    7775 }
    7776 
    7777 /**********************************************************************
    7778  *              VarDecDiv [OLEAUT32.178]
    7779  */
    7780 HRESULT WINAPI VarDecDiv(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight, LPDECIMAL  pdecResult)
    7781 {
    7782   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7783   return E_NOTIMPL;
    7784 }
    7785 
    7786 /**********************************************************************
    7787  *              VarDecCmp [OLEAUT32.204]
    7788  */
    7789 HRESULT WINAPI VarDecCmp(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
    7790 {
    7791   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7792   return E_NOTIMPL;
    7793 }
    7794 
    7795 /**********************************************************************
    7796  *              VarDecAbs [OLEAUT32.182]
    7797  */
    7798 HRESULT WINAPI VarDecAbs(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
    7799 {
    7800   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7801   return E_NOTIMPL;
    7802 }
    7803 
    7804 /**********************************************************************
    7805  *              VarDecFix [OLEAUT32.187]
    7806  */
    7807 HRESULT WINAPI VarDecFix(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
    7808 {
    7809   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7810   return E_NOTIMPL;
    7811 }
    7812 
    7813 /**********************************************************************
    7814  *              VarDecInt [OLEAUT32.188]
    7815  */
    7816 HRESULT WINAPI VarDecInt(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
    7817 {
    7818   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7819   return E_NOTIMPL;
    7820 }
    7821 
    7822 
    7823 /**********************************************************************
    7824  *              VarDecNeg [OLEAUT32.189]
    7825  */
    7826 HRESULT WINAPI VarDecNeg(LPDECIMAL pdecIn, LPDECIMAL pdecResult)
    7827 {
    7828   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7829   return E_NOTIMPL;
    7830 }
    7831 
    7832 /**********************************************************************
    7833  *              VarDecCmpR8 [OLEAUT32.298]
    7834  */
    7835 HRESULT WINAPI VarDecCmpR8(LPDECIMAL pdecLeft, LPDECIMAL  pdecRight)
    7836 {
    7837   FIXME("%s: Not implemented! (returning E_NOTIMPL)", __FUNCTION__);
    7838   return E_NOTIMPL;
    7839 }
    7840 
    7841 /************************************************************************
    7842  * VarDecFromStr (OLEAUT32.197)
    7843  *
    7844  * Convert a VT_BSTR to a DECIMAL.
    7845  *
    7846  * PARAMS
    7847  *  strIn   [I] Source
    7848  *  lcid    [I] LCID for the conversion
    7849  *  dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h")
    7850  *  pDecOut [O] Destination
    7851  *
    7852  * RETURNS
    7853  *  Success: S_OK.
    7854  *  Failure: DISP_E_OVERFLOW, if the value will not fit in the destination
    7855  */
    7856 HRESULT WINAPI VarDecFromStr(OLECHAR* strIn, LCID lcid, ULONG dwFlags, DECIMAL* pDecOut)
    7857 {
    7858   TRACE("%s: now calling VARIANT_NumberFromBstr\n", __FUNCTION__);
    7859   return _VarDecFromStr(strIn, lcid, dwFlags, pDecOut);
    7860 }
    7861 
  • trunk/src/pmkbdhk/makefile

    r7185 r21308  
    77#
    88
     9NOPEHDR=1
    910
    1011#
  • trunk/src/psapi/psapi.DEF

    r2223 r21308  
    1010    EmptyWorking                = _EmptyWorkingSet@4                    @1 
    1111    EnumDeviceDrivers           = _EnumDeviceDrivers@12                 @2 
    12     EnumProcessModules          = _EnumProcessModules@16                @3 
     12    EnumProcessModules          = _PSAPI_EnumProcessModules@16          @3 
    1313    EnumProcesses               = _EnumProcesses@12                     @4 
    1414    GetDeviceDriverBaseNameA    = _GetDeviceDriverBaseNameA@12          @5 
     
    2222    GetModuleFileNameExA        = _GetModuleFileNameExA@16              @13 
    2323    GetModuleFileNameExW        = _GetModuleFileNameExW@16              @14 
    24     GetModuleInformation        = _GetModuleInformation@16              @15
     24    GetModuleInformation        = _PSAPI_GetModuleInformation@16        @15
    2525    GetProcessMemoryInfo        = _GetProcessMemoryInfo@12              @16 
    2626    GetWsChanges                = _GetWsChanges@12                      @17 
  • trunk/src/psapi/psapi.cpp

    r1710 r21308  
    5656}
    5757
     58#ifndef __WIN32OS2__
    5859/***********************************************************************
    5960 *           EnumProcessModules (PSAPI.4)
     
    7071  return TRUE;
    7172}
     73#endif
    7274
    7375/***********************************************************************
     
    191193}
    192194
     195#ifdef __WIN32OS2__
    193196/***********************************************************************
    194197 *           GetModuleFileNameExA (PSAPI.13)
     
    197200  HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
    198201{
    199 #ifdef DEBUG
    200   dprintf(("PSAPI: GetModuleFileNameExA not implemented\n"));
    201 #endif
     202   if(hProcess != GetCurrentProcess()) {
     203       dprintf(("PSAPI: GetModuleFileNameExA not implemented for other processes (%x %x)\n", hProcess, hModule));
     204       return 0;
     205   }
     206   return GetModuleFileNameA(hModule, lpFilename, nSize);
     207}
     208#else
     209/***********************************************************************
     210 *           GetModuleFileNameExA (PSAPI.13)
     211 */
     212DWORD WINAPI GetModuleFileNameExA(
     213  HANDLE hProcess, HMODULE hModule, LPSTR lpFilename, DWORD nSize)
     214{
    202215  if(lpFilename&&nSize)
    203216    lpFilename[0]='\0';
     
    205218  return 0;
    206219}
     220#endif
    207221
    208222/***********************************************************************
     
    221235}
    222236
     237#ifndef __WIN32OS2__
    223238/***********************************************************************
    224239 *           GetModuleInformation (PSAPI.15)
     
    234249  return TRUE;
    235250}
     251#endif
    236252
    237253/***********************************************************************
  • trunk/src/riched32/charlist.c

    r9407 r21308  
    3232
    3333WINE_DEFAULT_DEBUG_CHANNEL(richedit);
     34
     35#ifdef __WIN32OS2__ /* no useful trace in this file! */
     36#define TRACE(a) do {} while (0)
     37#endif
    3438
    3539extern HANDLE RICHED32_hHeap;
  • trunk/src/riched32/reader.c

    r9407 r21308  
    8080
    8181WINE_DEFAULT_DEBUG_CHANNEL(richedit);
     82
     83#ifdef __WIN32OS2__ /* no useful trace in this file! */
     84#define TRACE(a) do {} while (0)
     85#endif
    8286
    8387extern HANDLE RICHED32_hHeap;
  • trunk/src/riched32/richedit.c

    r9859 r21308  
    4343WINE_DEFAULT_DEBUG_CHANNEL(richedit);
    4444
     45#ifdef __WIN32OS2__
     46/** custom build hack. */
     47BOOL (* WINAPI pfnCustomRichedHack_EM_STREAMIN)(HWND, LPSTR) = NULL;
     48#endif
     49
    4550HANDLE RICHED32_hHeap = (HANDLE)NULL;
    4651/* LPSTR  RICHED32_aSubclass = (LPSTR)NULL; */
     
    198203            {
    199204                RTFToBuffer(rtfBuffer, rtfBufferSize);
     205#ifdef __WIN32OS2__
     206                /* This is a very very ugly hack to work around some major parsing errors. */
     207                if (pfnCustomRichedHack_EM_STREAMIN)
     208                    pfnCustomRichedHack_EM_STREAMIN(hwnd, rtfBuffer);
     209                else
     210#endif
    200211                SetWindowTextA(hwnd,rtfBuffer);
    201212                HeapFree(RICHED32_hHeap, 0,rtfBuffer);
     
    843854        return ret;
    844855}
     856
     857
     858#ifdef __WIN32OS2__
     859/** Enables a callback replacement for the SetWindowTextA call finalizing
     860 * the handling of an EM_STREAMIN message.
     861 * @remark don't use this hack.
     862 */
     863BOOL WINAPI ODIN_RichedHack_EM_STREAMIN(BOOL (* WINAPI pfn)(HWND, LPSTR))
     864{
     865    pfnCustomRichedHack_EM_STREAMIN = pfn;
     866    return TRUE;
     867}
     868#endif
     869
  • trunk/src/riched32/textwriter.c

    r9410 r21308  
    4545
    4646WINE_DEFAULT_DEBUG_CHANNEL(richedit);
     47
     48#ifdef __WIN32OS2__ /* no useful trace in this file! */
     49#define TRACE(a) do {} while (0)
     50#endif
    4751
    4852static void     TextClass ();
  • trunk/src/user32/Makefile

    r21303 r21308  
    130130$(ODIN32_LIB)/libuls.lib \
    131131$(ODIN32_LIB)/$(ODINCRT).lib \
     132$(ODIN32_LIB)/imm32os2.lib \
    132133OS2386.LIB \
    133134$(RTLLIB_O)
  • trunk/src/user32/USER32.DEF

    r21303 r21308  
    750750    _clipboardPMToOdinFormat@4                                   @2043 NONAME
    751751    _clipboardOdinToPMFormat@4                                   @2044 NONAME
     752
     753    _GetOS2Icon@4                                                @2045 NONAME
  • trunk/src/user32/edit.c

    r21303 r21308  
    3131#include "ctrlconf.h"
    3232#include <heapstring.h>
     33#include <imm.h>
    3334#endif
    3435
     
    128129    HLOCAL hloc32A;     /* alias for ANSI control receiving EM_GETHANDLE
    129130                   or EM_SETHANDLE */
     131#ifdef __WIN32OS2__
     132    LPWSTR  compStr;
     133    INT     compStrLen;
     134    BOOL    moveCaret;
     135    DWORD   sentenceMode;
     136#endif
    130137} EDITSTATE;
    131138
     
    11131120            // always DBCS char
    11141121            CHAR charA[ 2 ];
    1115 
     1122            INT  lenA = 1;
     1123
     1124            if( IsDBCSLeadByte(( CHAR )( wParam >> 8 )))
     1125            {
    11161126                charA[ 0 ] = ( CHAR )( wParam >> 8 );
    11171127                charA[ 1 ] = ( CHAR )wParam;
    1118 
    1119             MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, 2, ( LPWSTR )&charW, 1);
     1128                lenA = 2;
     1129            }
     1130            else
     1131                charA[ 0 ] = ( CHAR )wParam;
     1132
     1133            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, lenA, ( LPWSTR )&charW, 1);
    11201134        }
    11211135
     
    11231137        break;
    11241138    }
     1139
     1140    case WM_IME_COMPOSITION:
     1141    {
     1142        HIMC    himc;
     1143        LONG    bufSize;
     1144        INT     i;
     1145        BOOL    passToDefWnd = FALSE;
     1146#ifdef DEBUG
     1147        LPSTR   strA;
     1148        INT     lenA;
     1149#endif
     1150
     1151        DPRINTF_EDIT_MSG32("WM_IME_COMPOSITION");
     1152
     1153        himc = ImmGetContext( hwnd );
     1154
     1155        if( es->sentenceMode )
     1156            passToDefWnd = TRUE;
     1157        else if( lParam & GCS_RESULTSTR )
     1158        {
     1159            LPWSTR  resultStr = NULL;
     1160            INT     resultStrLen = 0;
     1161
     1162            dprintf(("WM_IME_COMPOSITION : GCS_RESULTSTR"));
     1163
     1164            bufSize = ImmGetCompositionStringW( himc, GCS_RESULTSTR, NULL, 0 );
     1165            if( bufSize > 0 )
     1166            {
     1167                INT i;
     1168
     1169                resultStrLen = bufSize / sizeof( WCHAR );
     1170                resultStr = malloc( bufSize + sizeof( WCHAR ));
     1171                resultStr[ resultStrLen ] = 0;
     1172
     1173                ImmGetCompositionStringW( himc, GCS_RESULTSTR, resultStr, bufSize );
     1174
     1175#ifdef DEBUG
     1176                lenA = WideCharToMultiByte( CP_ACP, 0, resultStr, resultStrLen, 0, 0, 0, 0 );
     1177                strA = malloc( lenA + 1 );
     1178                WideCharToMultiByte( CP_ACP, 0, resultStr, resultStrLen, strA, lenA, 0, 0 );
     1179                strA[ lenA ] = 0;
     1180                dprintf(("Result String : '%s'", strA ));
     1181                free( strA );
     1182                dprintf(("Composition Len %d", es->compStrLen ));
     1183#endif
     1184                DestroyCaret();
     1185                if( es->compStrLen > 0 )
     1186                {
     1187                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     1188                    for( i = 0; i < es->compStrLen; i++ )
     1189                        EDIT_MoveForward(hwnd, es, TRUE);
     1190                    EDIT_WM_Clear(hwnd, es);
     1191                }
     1192
     1193                EDIT_EM_ReplaceSel(hwnd, es, TRUE, resultStr, TRUE);
     1194
     1195                CreateCaret(hwnd, 0, 2, es->line_height);
     1196                EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
     1197                ShowCaret(hwnd);
     1198
     1199                free( resultStr );
     1200
     1201            }
     1202
     1203            if( es->compStr )
     1204                free( es->compStr );
     1205
     1206            es->compStr = NULL;
     1207            es->compStrLen = 0;
     1208        }
     1209        else if( lParam & GCS_COMPSTR )
     1210        {
     1211            INT prevLen = es->compStrLen;
     1212
     1213            dprintf(("WM_IME_COMPOSITION : GCS_COMPSTR"));
     1214
     1215            if( es->compStr )
     1216                free( es->compStr );
     1217
     1218            es->compStr = NULL;
     1219            es->compStrLen = 0;
     1220
     1221            bufSize = ImmGetCompositionStringW( himc, GCS_COMPSTR, NULL, 0 );
     1222            if( bufSize > 0 )
     1223            {
     1224                HDC     hdc;
     1225                SIZE    size;
     1226                BOOL    oldMoveCaret;
     1227
     1228                es->compStrLen = bufSize / sizeof( WCHAR );
     1229                es->compStr = malloc( bufSize + sizeof( WCHAR ));
     1230                es->compStr[ es->compStrLen ] = 0;
     1231
     1232                ImmGetCompositionStringW( himc, GCS_COMPSTR, es->compStr, bufSize );
     1233
     1234#ifdef DEBUG
     1235                lenA = WideCharToMultiByte( CP_ACP, 0, es->compStr, es->compStrLen, 0, 0, 0, 0 );
     1236                strA = malloc( lenA + 1 );
     1237                WideCharToMultiByte( CP_ACP, 0, es->compStr, es->compStrLen, strA, lenA, 0, 0  );
     1238                strA[ lenA ] = 0;
     1239                dprintf(("Composition String : '%s'", strA ));
     1240                free( strA );
     1241#endif
     1242                hdc = GetDC( hwnd );
     1243                GetTextExtentPoint32W( hdc, es->compStr, es->compStrLen, &size);
     1244                ReleaseDC( hwnd, hdc );
     1245
     1246                oldMoveCaret = es->moveCaret;
     1247
     1248                es->moveCaret = FALSE; // to prevent cursor from flashing too many
     1249
     1250                if( prevLen > 0 )
     1251                {
     1252                    EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     1253                    for( i = 0; i < prevLen; i++ )
     1254                        EDIT_MoveForward(hwnd, es, TRUE);
     1255                    EDIT_WM_Clear(hwnd, es);
     1256                }
     1257
     1258                EDIT_EM_ReplaceSel(hwnd, es, TRUE, es->compStr, TRUE);
     1259
     1260                for( i = 0; i < es->compStrLen; i++ )
     1261                    EDIT_MoveBackward(hwnd, es, FALSE);
     1262
     1263                es->moveCaret = oldMoveCaret;
     1264
     1265                CreateCaret(hwnd, 0, size.cx, es->line_height);
     1266                EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
     1267                ShowCaret(hwnd);
     1268            }
     1269        }
     1270        else
     1271            passToDefWnd = TRUE;
     1272
     1273        ImmReleaseContext( hwnd, himc );
     1274
     1275        if( passToDefWnd )
     1276        {
     1277            if( unicode )
     1278                result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1279            else
     1280                result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1281        }
     1282        break;
     1283    }
     1284
     1285    case WM_IME_COMPOSITIONFULL:
     1286        DPRINTF_EDIT_MSG32("WM_IME_COMPOSITIONFULL");
     1287        if( unicode )
     1288            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1289        else
     1290            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1291        break;
     1292
     1293    case WM_IME_CONTROL:
     1294        DPRINTF_EDIT_MSG32("WM_IME_CONTROL");
     1295        if( unicode )
     1296            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1297        else
     1298            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1299        break;
     1300
     1301    case WM_IME_ENDCOMPOSITION:
     1302        DPRINTF_EDIT_MSG32("WM_IME_ENDCOMPOSITION");
     1303
     1304        if( es->compStr )
     1305        {
     1306            INT i;
     1307
     1308            DestroyCaret();
     1309
     1310            EDIT_EM_SetSel(hwnd, es, (UINT)-1, 0, FALSE);
     1311            for( i = 0; i < es->compStrLen; i++ )
     1312                EDIT_MoveForward(hwnd, es, TRUE);
     1313            EDIT_WM_Clear(hwnd, es);
     1314
     1315            CreateCaret(hwnd, 0, 2, es->line_height);
     1316            EDIT_SetCaretPos(hwnd, es, es->selection_end, es->flags & EF_AFTER_WRAP);
     1317            ShowCaret(hwnd);
     1318
     1319            free( es->compStr );
     1320        }
     1321
     1322        es->compStr = NULL;
     1323        es->compStrLen = 0;
     1324
     1325        if( unicode )
     1326            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1327        else
     1328            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1329        break;
     1330
     1331    case WM_IME_NOTIFY:
     1332        DPRINTF_EDIT_MSG32("WM_IME_NOTIFY");
     1333
     1334        if( wParam == IMN_SETSENTENCEMODE )
     1335        {
     1336            HIMC  himc;
     1337            DWORD conversionMode;
     1338
     1339            himc = ImmGetContext( hwnd );
     1340
     1341            ImmGetConversionStatus( himc, &conversionMode, &es->sentenceMode );
     1342
     1343            ImmReleaseContext( hwnd, himc );
     1344        }
     1345
     1346        if( unicode )
     1347            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1348        else
     1349            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1350        break;
     1351
     1352    case WM_IME_REQUEST:
     1353        DPRINTF_EDIT_MSG32("WM_IME_REQUEST");
     1354        if( unicode )
     1355            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1356        else
     1357            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1358        break;
     1359
     1360    case WM_IME_SELECT:
     1361        DPRINTF_EDIT_MSG32("WM_IME_SELECT");
     1362        if( unicode )
     1363            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1364        else
     1365            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1366        break;
     1367
     1368    case WM_IME_SETCONTEXT:
     1369        DPRINTF_EDIT_MSG32("WM_IME_SETCONTEXT");
     1370
     1371        dprintf(("ImmGetProperty %08lx", ImmGetProperty( 0, IGP_CONVERSION )));
     1372
     1373        if( unicode )
     1374            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1375        else
     1376            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1377        break;
     1378
     1379    case WM_IME_STARTCOMPOSITION:
     1380        DPRINTF_EDIT_MSG32("WM_IME_STARTCOMPOSITION");
     1381
     1382        es->compStr = NULL;
     1383        es->compStrLen = 0;
     1384
     1385        if( unicode )
     1386            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1387        else
     1388            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1389        break;
     1390
     1391    case EM_GETIMESTATUS:
     1392        DPRINTF_EDIT_MSG32("EM_GETIMESTATUS");
     1393        if( unicode )
     1394            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1395        else
     1396            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1397        break;
     1398
     1399    case EM_SETIMESTATUS:
     1400        DPRINTF_EDIT_MSG32("EM_SETIMESTATUS");
     1401        if( unicode )
     1402            result = DefWindowProcW( hwnd, msg, wParam, lParam );
     1403        else
     1404            result = DefWindowProcA( hwnd, msg, wParam, lParam );
     1405        break;
    11251406#endif
    11261407
     
    24402721{
    24412722    LRESULT res = EDIT_EM_PosFromChar(hwnd, es, pos, after_wrap);
     2723
     2724#ifdef __WIN32OS2__
     2725    if( es->moveCaret )
     2726    {
     2727        HIMC            himc;
     2728        CANDIDATEFORM   candForm;
     2729
     2730        himc = ImmGetContext( hwnd );
     2731
     2732#endif
     2733
    24422734    SetCaretPos(SLOWORD(res), SHIWORD(res));
     2735
     2736#ifdef __WIN32OS2__
     2737        if( es->sentenceMode )
     2738        {
     2739            COMPOSITIONFORM cf;
     2740
     2741            cf.dwStyle = CFS_POINT;
     2742            cf.ptCurrentPos.x = SLOWORD( res );
     2743            cf.ptCurrentPos.y = SHIWORD( res );
     2744
     2745            ImmSetCompositionWindow( himc, &cf );
     2746        }
     2747
     2748        candForm.dwIndex = 0;
     2749        candForm.dwStyle = CFS_CANDIDATEPOS;
     2750        candForm.ptCurrentPos.x = SLOWORD( res );
     2751        candForm.ptCurrentPos.y = SHIWORD( res ) + es->line_height;
     2752
     2753        ImmSetCandidateWindow( himc, &candForm );
     2754
     2755        ImmReleaseContext( hwnd, himc );
     2756    }
     2757#endif
    24432758}
    24442759
     
    47735088    }
    47745089
     5090#ifdef __WIN32OS2__
     5091    es->compStr = NULL;
     5092    es->compStrLen = 0;
     5093    es->moveCaret = TRUE;
     5094    {
     5095        HIMC  himc;
     5096        DWORD conversionMode;
     5097
     5098        himc = ImmGetContext( hwnd );
     5099
     5100        ImmGetConversionStatus( himc, &conversionMode, &es->sentenceMode );
     5101
     5102        ImmReleaseContext( hwnd, himc );
     5103    }
     5104#endif
     5105
    47755106    return TRUE;
    47765107}
     
    49045235    es->font = font;
    49055236    dc = GetDC(hwnd);
     5237#ifdef __WIN32OS2__
     5238    // todo : set font of IME window
     5239#endif
    49065240    if (font)
    49075241        old_font = SelectObject(dc, font);
  • trunk/src/user32/listbox.c

    r21303 r21308  
    30283028            // always DBCS char
    30293029            CHAR charA[ 2 ];
    3030 
     3030            INT  lenA = 1;
     3031
     3032            if( IsDBCSLeadByte(( CHAR )( wParam >> 8 )))
     3033            {
    30313034                charA[ 0 ] = ( CHAR )( wParam >> 8 );
    30323035                charA[ 1 ] = ( CHAR )wParam;
    3033 
    3034             MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, 2, ( LPWSTR )&charW, 1);
     3036                lenA = 2;
     3037            }
     3038            else
     3039                charA[ 0 ] = ( CHAR )wParam;
     3040
     3041            MultiByteToWideChar( CP_ACP, 0, ( LPSTR )charA, lenA, ( LPWSTR )&charW, 1);
    30353042        }
    30363043        return LISTBOX_HandleChar( hwnd, descr, charW );
  • trunk/src/user32/oslibmsgtranslate.cpp

    r21303 r21308  
    1515 *
    1616 */
     17#define  INCL_NLS
     18#define  INCL_GPI
    1719#define  INCL_WIN
    1820#define  INCL_PM
     
    4244#include "user32api.h"
    4345
     46#include <os2im.h>
     47#include <im32.h>
    4448
    4549#define DBG_LOCALLOG    DBG_oslibmsgtranslate
     
    4852static BOOL fGenerateDoubleClick = FALSE;
    4953static MSG  doubleClickMsg = {0};
     54
     55extern UINT WINAPI GetACP(void); // from winnls.h
    5056
    5157//For wheel mouse translation
     
    753759        if( scanCode != 0 )
    754760        {
     761            switch( SHORT2FROMMP( os2Msg->mp2 ))
     762            {
     763                // for Korean
     764                case VK_DBE_HANJA :
     765                    bWinVKey = 0x19;
     766                    break;
     767
     768                case VK_DBE_HANGEUL :
     769                    bWinVKey = 0x15;
     770                    break;
     771
     772                case VK_DBE_JAMO :
     773                    bWinVKey = 0;
     774                    break;
     775
     776                // for Japan
     777                case VK_DBE_KATAKANA :
     778                    bWinVKey = 0;
     779                    break;
     780
     781                case VK_DBE_HIRAGANA :
     782                    bWinVKey = 0;
     783                    break;
     784
     785                case VK_DBE_SBCSCHAR :
     786                    bWinVKey = 0;
     787                    break;
     788
     789                case VK_DBE_DBCSCHAR :
     790                    bWinVKey = 0;
     791                    break;
     792
     793                case VK_DBE_SBCSDBCSCHAR :
     794                    bWinVKey = 0;
     795                    break;
     796
     797                case VK_DBE_ROMAN :
     798                    bWinVKey = 0;
     799                    break;
     800
     801                // for PRC-Chinese
     802                case VK_DBE_HANZI :
     803                    bWinVKey = 0;
     804                    break;
     805
     806                // for Taiwan
     807                case VK_DBE_TSANGJYE :
     808                    bWinVKey = 0;
     809                    break;
     810
     811                case VK_DBE_PHONETIC :
     812                    bWinVKey = 0;
     813                    break;
     814
     815                case VK_DBE_CONV :
     816                    bWinVKey = 0;
     817                    break;
     818
     819                case VK_DBE_NOCONV :
     820                    bWinVKey = 0;
     821                    break;
     822
     823                case VK_DBE_ALPHANUMERIC :
     824                    switch( GetACP())
     825                    {
     826                        case 949 :  // Korea
     827                        case 1361 :
     828                            bWinVKey = 0x15;
     829                            break;
     830
     831                        case 932 :  // Japan
     832                        case 942 :
     833                        case 943 :
     834
     835                        case 936 :  // PRC
     836                        case 1381 :
     837
     838                        case 950 :  // Taiwan
     839                        default :
     840                            bWinVKey = 0;
     841                    }
     842                    break;
     843
     844                default :
    755845                    KeyTranslatePMScanToWinVKey(usPMScanCode,
    756846                                                FALSE,
     
    758848                                                &wWinScan,
    759849                                                &fWinExtended);
     850            }
     851
    760852            winMsg->wParam = bWinVKey;
    761853        }
     
    10791171        break;
    10801172
     1173    case WM_IMENOTIFY:
     1174        dprintf(("WM_IMENOTIFY"));
     1175
     1176        winMsg->wParam = 0;
     1177        winMsg->lParam = 0;
     1178
     1179        switch(( ULONG )os2Msg->mp1 )
     1180        {
     1181            case IMN_STARTCONVERSION :
     1182                winMsg->message = WM_IME_STARTCOMPOSITION_W;
     1183                break;
     1184
     1185            case IMN_ENDCONVERSION :
     1186                winMsg->message = WM_IME_ENDCOMPOSITION_W;
     1187                break;
     1188
     1189            case IMN_CONVERSIONFULL :
     1190                winMsg->message = WM_IME_COMPOSITIONFULL_W;
     1191                break;
     1192
     1193            case IMN_IMECHANGED :
     1194                winMsg->message = WM_IME_SELECT_W;
     1195                // todo
     1196                // fall through
     1197
     1198            default :
     1199                goto dummymessage;
     1200
     1201        }
     1202        break;
     1203
     1204    case WM_IMEREQUEST:
     1205        winMsg->wParam = 0;
     1206        winMsg->lParam = 0;
     1207
     1208        switch(( ULONG )os2Msg->mp1 )
     1209        {
     1210            case IMR_INSTANCEACTIVATE :
     1211            {
     1212                USHORT usIMR_IA = LOUSHORT( os2Msg->mp2 );
     1213
     1214                winMsg->message = WM_IME_SETCONTEXT_W;
     1215                winMsg->wParam = HIUSHORT( os2Msg->mp2 );
     1216
     1217                if( usIMR_IA & IMR_IA_STATUS )
     1218                    winMsg->lParam |= ISC_SHOWUIGUIDELINE_W;
     1219
     1220                if( usIMR_IA & IMR_IA_CONVERSION )
     1221                    winMsg->lParam |= ISC_SHOWUICOMPOSITIONWINDOW_W;
     1222
     1223                if( usIMR_IA & IMR_IA_CANDIDATE )
     1224                    winMsg->lParam |= ISC_SHOWUIALLCANDIDATEWINDOW_W;
     1225
     1226                if( usIMR_IA & IMR_IA_INFOMSG )
     1227                    winMsg->lParam |= 0; // todo
     1228
     1229                if( usIMR_IA & IMR_IA_REGWORD )
     1230                    winMsg->lParam |= 0; // todo
     1231                break;
     1232            }
     1233
     1234            case IMR_STATUS :
     1235                winMsg->message = WM_IME_NOTIFY_W;
     1236
     1237                switch(( ULONG )os2Msg->mp2 )
     1238                {
     1239                    case IMR_STATUS_SHOW :
     1240                        winMsg->wParam = IMN_OPENSTATUSWINDOW_W;
     1241                        break;
     1242
     1243                    case IMR_STATUS_HIDE :
     1244                        winMsg->wParam = IMN_CLOSESTATUSWINDOW_W;
     1245                        break;
     1246
     1247                    case IMR_STATUS_INPUTMODE : // IMN_SETOPENSTATUS followed by IMN_SETCONVERSIONMODE
     1248                        winMsg->wParam = IMN_SETOPENSTATUS_W;
     1249                        break;
     1250
     1251                    case IMR_STATUS_CONVERSIONMODE :
     1252                        winMsg->wParam = IMN_SETSENTENCEMODE_W;
     1253                        break;
     1254
     1255                    case IMR_STATUS_STATUSPOS :
     1256                        winMsg->wParam = IMN_SETSTATUSWINDOWPOS_W;
     1257                        break;
     1258
     1259                    case IMR_STATUS_STRING :
     1260                    case IMR_STATUS_STRINGATTR :
     1261                    case IMR_STATUS_CURSORPOS :
     1262                    case IMR_STATUS_CURSORATTR :
     1263
     1264                    default :
     1265                        // todo
     1266                        goto dummymessage;
     1267
     1268                }
     1269                break;
     1270
     1271            case IMR_CONVRESULT :
     1272            {
     1273                ULONG ulIMR = ( ULONG )os2Msg->mp2;
     1274
     1275                winMsg->message = WM_IME_COMPOSITION_W;
     1276                winMsg->wParam = 0; // todo : current DBCS char
     1277
     1278                if( ulIMR & IMR_CONV_CONVERSIONSTRING )
     1279                    winMsg->lParam |= GCS_COMPSTR_W;
     1280
     1281                if( ulIMR & IMR_CONV_CONVERSIONATTR )
     1282                    winMsg->lParam |= GCS_COMPATTR_W;
     1283
     1284                if( ulIMR & IMR_CONV_CONVERSIONCLAUSE )
     1285                    winMsg->lParam |= GCS_COMPCLAUSE_W;
     1286
     1287                if( ulIMR & IMR_CONV_READINGSTRING )
     1288                    winMsg->lParam |= GCS_COMPREADSTR_W;
     1289
     1290                if( ulIMR & IMR_CONV_READINGATTR )
     1291                    winMsg->lParam |= GCS_COMPREADATTR_W;
     1292
     1293                if( ulIMR & IMR_CONV_READINGCLAUSE )
     1294                    winMsg->lParam |= GCS_COMPREADCLAUSE_W;
     1295
     1296                if( ulIMR & IMR_CONV_CURSORPOS )
     1297                    winMsg->lParam |= GCS_CURSORPOS_W;
     1298
     1299                if( ulIMR & IMR_CONV_CURSORATTR )
     1300                    winMsg->lParam |= 0; // todo
     1301
     1302                if( ulIMR & IMR_CONV_CHANGESTART )
     1303                    winMsg->lParam |= GCS_DELTASTART_W;
     1304
     1305                if( ulIMR & IMR_CONV_INSERTCHAR )
     1306                    winMsg->lParam |= CS_INSERTCHAR_W;
     1307
     1308                if( ulIMR & IMR_CONV_NOMOVECARET )
     1309                    winMsg->lParam |= CS_NOMOVECARET_W;
     1310
     1311                if( ulIMR & IMR_CONV_CONVERSIONFONT )
     1312                    winMsg->lParam |= 0; // todo
     1313
     1314                if( ulIMR & IMR_CONV_CONVERSIONPOS )
     1315                    winMsg->lParam |= 0; // todo
     1316
     1317                if( ulIMR & IMR_RESULT_RESULTSTRING )
     1318                    winMsg->lParam = GCS_RESULTSTR_W; // clear all composition info
     1319
     1320                if( ulIMR & IMR_RESULT_RESULTATTR )
     1321                    winMsg->lParam |= 0; // todo
     1322
     1323                if( ulIMR & IMR_RESULT_RESULTCLAUSE )
     1324                    winMsg->lParam |= GCS_RESULTCLAUSE_W;
     1325
     1326                if( ulIMR & IMR_RESULT_READINGSTRING )
     1327                    winMsg->lParam |= GCS_RESULTREADSTR_W;
     1328
     1329                if( ulIMR & IMR_RESULT_READINGATTR )
     1330                    winMsg->lParam |= 0; // todo
     1331
     1332                if( ulIMR & IMR_RESULT_READINGCLAUSE )
     1333                    winMsg->lParam |= GCS_RESULTREADCLAUSE_W;
     1334
     1335                if( ulIMR && ( winMsg->lParam == 0 ))
     1336                    goto dummymessage;
     1337                break;
     1338            }
     1339
     1340            case IMR_CANDIDATE :
     1341                winMsg->message = WM_IME_NOTIFY_W;
     1342                switch(( ULONG )os2Msg->mp2 )
     1343                {
     1344                    case IMR_CANDIDATE_SHOW :
     1345                    case IMR_CANDIDATE_HIDE :
     1346                    case IMR_CANDIDATE_SELECT :
     1347                    case IMR_CANDIDATE_CHANGE :
     1348                    case IMR_CANDIDATE_CANDIDATEPOS :
     1349                    default :
     1350                        // todo
     1351                        goto dummymessage;
     1352                }
     1353                break;
     1354
     1355            case IMR_INFOMSG :
     1356                winMsg->message = WM_IME_NOTIFY_W;
     1357                winMsg->wParam = IMN_GUIDELINE_W;
     1358                break;
     1359
     1360            case IMR_REGWORD :
     1361                goto dummymessage;
     1362
     1363            case IMR_IMECHANGE :
     1364                winMsg->message = WM_IME_SELECT_W;
     1365                // todo
     1366                goto dummymessage;
     1367
     1368            case IMR_CONFIG :
     1369                // todo
     1370                goto dummymessage;
     1371
     1372            case IMR_DICTIONARY :
     1373                // todo
     1374                goto dummymessage;
     1375
     1376            case IMR_OTHERINFO :
     1377                // todo
     1378                goto dummymessage;
     1379        }
     1380        break;
     1381
     1382#if 0 // application cannot receive this message
     1383    case WM_IMECONTROL:
     1384#endif
    10811385    case WM_INITMENU:
    10821386    case WM_MENUSELECT:
  • trunk/src/user32/pmwindow.cpp

    r21303 r21308  
    6161#include "user32api.h"
    6262#include <kbdhook.h>
     63#include <heapstring.h>
     64
     65#include <os2im.h>
     66#include <im32.h>
    6367
    6468#define DBG_LOCALLOG    DBG_pmwindow
     
    140144#endif
    141145
     146extern "C" ULONG OSLibImSetMsgQueueProperty( ULONG, ULONG );
     147
    142148//******************************************************************************
    143149// Initialize PM; create hab, message queue and register special Win32 window classes
     
    194200    BOOL rc = WinSetCp(hmq, GetDisplayCodepage());
    195201    dprintf(("InitPM: WinSetCP was %sOK", rc ? "" : "not "));
     202
     203    /* IM instace is created per message queue, that is, thread */
     204    if( IsDBCSEnv())
     205        OSLibImSetMsgQueueProperty( hmq, MQP_INSTANCE_PERMQ );
    196206
    197207    //CD polling window class
     
    10041014        dprintf(("OS2: %s %x %x %x", (msg == WM_HSCROLL) ? "WM_HSCROLL" : "WM_VSCROLL", win32wnd->getWindowHandle(), mp1, mp2));
    10051015        win32wnd->DispatchMsgA(pWinMsg);
     1016        break;
     1017
     1018    case WM_IMEREQUEST:
     1019    case WM_IMECONTROL:
     1020    case WM_IMENOTIFY:
     1021        if( pWinMsg->message )
     1022        {
     1023            win32wnd->DispatchMsgA( pWinMsg );
     1024
     1025            if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
     1026               ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
     1027            {
     1028                MSG m;
     1029
     1030                m.message = WM_IME_NOTIFY_W;
     1031                m.wParam = IMN_SETCONVERSIONMODE_W;
     1032                m.lParam = 0;
     1033
     1034                win32wnd->DispatchMsgA( &m );
     1035            }
     1036        }
     1037        else
     1038            goto RunDefWndProc;
    10061039        break;
    10071040
     
    22102243        break;
    22112244
     2245    case WM_IMEREQUEST:
     2246    case WM_IMECONTROL:
     2247    case WM_IMENOTIFY:
     2248        if( pWinMsg->message )
     2249        {
     2250            dprintf(("Frame window received IME message"));
     2251            win32wnd->DispatchMsgA( pWinMsg );
     2252
     2253            if(( pWinMsg->message = WM_IME_NOTIFY_W ) &&
     2254               ( pWinMsg->wParam == IMN_SETOPENSTATUS_W ))
     2255            {
     2256                MSG m;
     2257
     2258                m.message = WM_IME_NOTIFY_W;
     2259                m.wParam = IMN_SETCONVERSIONMODE_W;
     2260                m.lParam = 0;
     2261
     2262                win32wnd->DispatchMsgA( &m );
     2263            }
     2264        }
     2265        else
     2266            goto RunDefWndProc;
     2267        break;
     2268
    22122269#ifdef DEBUG
    22132270    case WM_DDE_INITIATE:
  • trunk/src/version/dbgwrap.cpp

    r10296 r21308  
    1515#include <heapstring.h>
    1616#include <version.h>
     17
     18#define DBG_LOCALLOG    DBG_trace
     19#include <dbglocal.h>
    1720
    1821#define DBGWRAP_MODULE "VERSION"
  • trunk/src/win16ldr/odin.c

    r5979 r21308  
    1 #ifndef MSC6
     1#ifdef WATCOMC
    22#include <windows.h>
    33#else
    44#include "msc60win.h"
    55#endif
     6//#include <ddeml.h>
    67#include <stdlib.h>
    78#include <string.h>
     
    1920HANDLE hModule = 0;
    2021
     22typedef void (FAR * PASCAL FUNC_SetPELdr)(LPCSTR);
     23
     24#ifdef DDE_COMM
     25HDDEDATA CALLBACK MyDdeCallback(UINT wType, UINT wFmt, HCONV hConv, HSZ hsz1, HSZ hsz2, HDDEDATA hData, DWORD dwData1, DWORD dwData2);
     26
     27DWORD idInst = 0;
     28HSZ   hszServer = 0, hszTopic = 0;
     29
     30#define MSG_DDE_WILDCONNECT     WM_USER+1
     31#define MSG_DDE_CONNECT         WM_USER+2
     32#endif
    2133
    2234//*****************************************************************************************
     
    2537{
    2638    MSG msg;
     39        FUNC_SetPELdr pfnSetPELdr;
     40        char  szPEPath[260];
     41        LPSTR tmp;
     42                                       
     43        hDll = LoadLibrary("odindll.dll");
     44        if(hDll == 0) {
     45                return 0;
     46        }
     47
     48        pfnSetPELdr = (FUNC_SetPELdr)GetProcAddress(hDll, "SETPELDR");
     49        if(pfnSetPELdr == NULL) {
     50                return 0;
     51        }                 
     52        //check if the caller specified the path of the PE loader; if so, pass
     53        //it on to odindll
     54    tmp = strstr(lpCmdLine, "/PELDR=[");
     55    if(tmp) {
     56        tmp += 8;       //skip /peldr=[
     57        strcpy(szPEPath, tmp);
     58        tmp = szPEPath;
     59       
     60        while(*tmp != ']' && *tmp != 0) tmp++;
     61       
     62        if(*tmp == ']') {
     63                *tmp = 0;
     64                pfnSetPELdr(szPEPath);
     65        }               
     66       
     67        //now skip this parameter               
     68        tmp = strstr(lpCmdLine, "/PELDR=[");
     69        while(*tmp != ']' && *tmp != 0) tmp++;     
     70        if(*tmp == ']') {
     71                tmp++;
     72        }
     73                lpCmdLine = tmp;       
     74    }
    2775
    2876    if (!hPrevInstance)
     
    3280    if (!InitInstance(hInstance, nCmdShow))
    3381        return (FALSE);
     82
     83#ifdef DDE_COMM
     84    if(DdeInitialize(&idInst, MyDdeCallback, APPCLASS_STANDARD, 0) != DMLERR_NO_ERROR) {
     85        return FALSE;
     86    }
     87    hszServer = DdeCreateStringHandle(idInst, "Win16OdinServer", CP_WINANSI);
     88    if(hszServer == 0) {
     89        return FALSE;
     90    }
     91    hszTopic = DdeCreateStringHandle(idInst, "Win16Broadcast", CP_WINANSI);
     92    if(hszTopic == 0) {
     93        return FALSE;
     94    }
     95    if(DdeNameService(idInst, hszServer, 0, DNS_REGISTER) == 0) {
     96        return FALSE;
     97    }
     98#endif
    3499
    35100    while(*lpCmdLine == ' ') lpCmdLine++;
     
    48113               
    49114                sprintf(errormsg, "WinExec %s failed with error %d", lpCmdLine, hModule);
    50                 MessageBox(hwnd, errormsg, "Ïnternal Error", MB_ICONHAND);
     115                MessageBox(hwnd, errormsg, "Internal Error", MB_ICONHAND);
    51116                DestroyWindow(hwnd);
    52117        }
    53118               
     119#ifdef DDE_COMM
     120    DdeNameService(idInst, hszServer, 0, DNS_UNREGISTER);               
     121    DdeFreeStringHandle(idInst, hszServer);
     122    DdeFreeStringHandle(idInst, hszTopic);
     123    DdeUninitialize(idInst);
     124#endif
    54125        FreeLibrary(hDll);
    55126    return (msg.wParam);
     
    60131{
    61132        WNDCLASS wc;
    62        
    63         hDll = LoadLibrary("odindll.dll");
    64         if(hDll == 0) {
    65                 return 0;
    66         }
    67133       
    68134    wc.style = NULL;
     
    88154        "Win16OdinClass",
    89155        "Odin Win16 Program Launcher",
     156#if 1
     157                WS_POPUP,
     158#else       
    90159        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
     160#endif       
    91161        CW_USEDEFAULT,
    92162        CW_USEDEFAULT,
     
    127197            break;
    128198
     199#ifdef DDE_COMM
     200        case MSG_DDE_WILDCONNECT:
     201            break;
     202        case MSG_DDE_CONNECT:
     203            MessageBox(0, "MyDdeCallback", "WILDCONNECT", MB_OK);
     204            break;
     205#endif
    129206        default:
    130207            return (DefWindowProc(hWnd, message, wParam, lParam));
     
    132209    return (NULL);
    133210}
    134 //*****************************************************************************************
    135 //*****************************************************************************************
     211#ifdef DDE_COMM
     212//*****************************************************************************************
     213//*****************************************************************************************
     214HDDEDATA CALLBACK MyDdeCallback(UINT wType, UINT wFmt, HCONV hConv,
     215                                HSZ hszTopic,  HSZ hszItem,
     216                                HDDEDATA hData, DWORD dwData1, DWORD dwData2)
     217{
     218//    WORD i, j;
     219//    WORD cItems, iFmt;
     220//    HDDEDATA hDataRet;
     221
     222    char msg[128];
     223
     224////     MessageBeep(500);
     225//    sprintf(msg, "type=%x format=%x %x %x %x %x %x %x", wType, wFmt, hConv, hszTopic, hszItem, hData, dwData1, dwData2);
     226//    MessageBox(0, "MyDdeCallback", "test", MB_OK);
     227
     228    if(wType == XTYP_EXECUTE && wFmt == CF_TEXT)
     229    {
     230        char szExec[64];
     231
     232        DdeGetData(hData, (LPBYTE)szExec, 64, 0);
     233        szExec[63] = 0;
     234        MessageBox(0, "MyDdeCallback", szExec, MB_OK);
     235        return (HDDEDATA)TRUE;
     236    }
     237    /*
     238     * Process wild initiates here
     239     */
     240    if (wType == XTYP_WILDCONNECT) {
     241        HSZ ahsz[(1 + 1) * 2];
     242        /*
     243         * He wants a hsz list of all our available app/topic pairs
     244         * that conform to hszTopic and hszItem(App).
     245         */
     246
     247//        MessageBox(0, "MyDdeCallback", "WILDCONNECT", MB_OK);
     248
     249//        if (!ValidateContext((PCONVCONTEXT)lData1)) {
     250//            return(FALSE);
     251//        }
     252
     253        if (hszItem != hszServer && hszItem != 0) {
     254            // we only support the hszAppName service
     255            return(0);
     256        }
     257
     258        ahsz[0] = hszServer;
     259        ahsz[1] = hszTopic;
     260        // cap off the list with 0s
     261        ahsz[2] = ahsz[3] = 0L;
     262
     263        // send it back
     264        return(DdeCreateDataHandle(idInst, (LPBYTE)&ahsz[0], sizeof(HSZ) * 4, 0L, 0, wFmt, 0));
     265    }
     266    return 0;
     267}
     268//*****************************************************************************************
     269//*****************************************************************************************
     270#endif
  • trunk/src/win16ldr/odindll.c

    r5979 r21308  
    1 #ifndef MSC6
    21#include <windows.h>
    3 #else
    4 #include "msc60win.h"
    5 #endif
    62#include <string.h>
     3#include <stdlib.h>
     4#include <stdio.h>
    75#include "peexe.h"
    86
     
    108UINT FAR _loadds PASCAL MyWinExec(LPCSTR lpszCmdLine, UINT fuShowCmd);
    119
     10BOOL    FAR _loadds PASCAL MyPostMessage(HWND, UINT, WPARAM, LPARAM);
     11LRESULT FAR _loadds PASCAL MySendMessage(HWND, UINT, WPARAM, LPARAM);
     12
    1213BOOL GetPEFileHeader (LPVOID lpFile, PIMAGE_FILE_HEADER pHeader);
    1314BOOL GetPEOptionalHeader (LPVOID lpFile, PIMAGE_OPTIONAL_HEADER pHeader);
    1415
    15 #if defined(__WATCOMC__)
    16 typedef DWORD (FAR * WINAPI * FUNC_GetVersion)(void);
    17 typedef UINT  (FAR * WINAPI * FUNC_WinExec)(LPCSTR, UINT);
    18 #else
    19 typedef DWORD (FAR * WINAPI FUNC_GetVersion)(void);
    20 typedef UINT  (FAR * WINAPI FUNC_WinExec)(LPCSTR, UINT);
    21 #endif
     16typedef DWORD (FAR * PASCAL FUNC_GetVersion)(void);
     17typedef UINT  (FAR * PASCAL FUNC_WinExec)(LPCSTR, UINT);
     18#ifdef PATCH_POSTSENDMSG
     19typedef BOOL    (FAR * PASCAL FUNC_PostMessage)(HWND, UINT, WPARAM, LPARAM);
     20typedef LRESULT (FAR * PASCAL FUNC_SendMessage)(HWND, UINT, WPARAM, LPARAM);
     21#endif
     22
     23BYTE  oldcodeEXEC;
     24DWORD olddataEXEC;
     25UINT  selEXEC;
     26BYTE FAR *jumpEXEC;
    2227
    2328BYTE  oldcodeVER;
    2429DWORD olddataVER;
    2530UINT  selVER;
    26 BYTE  oldcodeEXEC;
    27 DWORD olddataEXEC;
    28 UINT  selEXEC;
    2931BYTE FAR *jumpVER;
    30 BYTE FAR *jumpEXEC;
     32
     33#ifdef PATCH_POSTSENDMSG
     34BYTE  oldcodeSEND;
     35DWORD olddataSEND;
     36UINT  selSEND;
     37BYTE FAR *jumpSEND;
     38
     39BYTE  oldcodePOST;
     40DWORD olddataPOST;
     41UINT  selPOST;
     42BYTE FAR *jumpPOST;
     43#endif
    3144
    3245BOOL fUnloaded = FALSE;
     
    3548char szPEPath[256] = {0};
    3649
     50FUNC_GetVersion orggetver   = NULL;
     51FUNC_WinExec    orgwinexec  = NULL;
     52#ifdef PATCH_POSTSENDMSG
     53FUNC_SendMessage orgsendmsg = NULL;
     54FUNC_PostMessage orgpostmsg = NULL;
     55#endif
     56
    3757//*****************************************************************************************
    3858//*****************************************************************************************
    3959int FAR _loadds CALLBACK LibMain(HINSTANCE hinst, WORD wDataSeg, WORD cbHeap, LPSTR lpszCmdLine)
    4060{
    41         FUNC_GetVersion getver;
    42         FUNC_WinExec winexec;
    4361        DWORD FAR *addr;
    4462       
    45     if (fInit == FALSE) {
     63    if(fInit == FALSE)
     64    {
    4665        fInit = TRUE;
    4766
    48                 GetProfileString("Odin", "PEPath", "PE.EXE", szPEPath, sizeof(szPEPath));
    49                 getver      = (FUNC_GetVersion)&GetVersion;
     67                GetProfileString("PELDR", "LdrPath", "PE.EXE", szPEPath, sizeof(szPEPath));
     68               
     69                orggetver   = (FUNC_GetVersion)GetVersion;
    5070                selVER      = AllocSelector(0);
    51                 PrestoChangoSelector(SELECTOROF(getver), selVER);
    52 
    53                 jumpVER     = MAKELP(selVER, OFFSETOF(getver));
     71                PrestoChangoSelector(SELECTOROF(orggetver), selVER);
     72
     73                jumpVER     = MAKELP(selVER, OFFSETOF(orggetver));
    5474                addr        = (DWORD FAR *)(jumpVER+1);
    5575                oldcodeVER  = *jumpVER;
    5676                olddataVER  = *addr;
    5777                *jumpVER    = 0xEA;     //jmp
    58                 *addr       = (DWORD)&MyGetVersion;
    59 
    60                 winexec     = (FUNC_WinExec)&WinExec;   
     78                *addr       = (DWORD)MyGetVersion;
     79
     80                orgwinexec  = (FUNC_WinExec)WinExec;   
    6181                selEXEC     = AllocSelector(0);
    62                 PrestoChangoSelector(SELECTOROF(winexec), selEXEC);
    63 
    64                 jumpEXEC    = MAKELP(selEXEC, OFFSETOF(winexec));
     82                PrestoChangoSelector(SELECTOROF(orgwinexec), selEXEC);
     83
     84                jumpEXEC    = MAKELP(selEXEC, OFFSETOF(orgwinexec));
    6585                addr        = (DWORD FAR *)(jumpEXEC+1);
    6686                oldcodeEXEC = *jumpEXEC;
    6787                olddataEXEC = *addr;
    6888                *jumpEXEC   = 0xEA;     //jmp
    69                 *addr       = (DWORD)&MyWinExec;
     89                *addr       = (DWORD)MyWinExec;
     90
     91#ifdef PATCH_POSTSENDMSG
     92                orgsendmsg  = (FUNC_SendMessage)SendMessage;   
     93                selSEND     = AllocSelector(0);
     94                PrestoChangoSelector(SELECTOROF(orgsendmsg), selSEND);
     95
     96                jumpSEND    = MAKELP(selSEND, OFFSETOF(orgsendmsg));
     97                addr        = (DWORD FAR *)(jumpSEND+1);
     98                oldcodeSEND = *jumpSEND;
     99                olddataSEND = *addr;
     100                *jumpSEND   = 0xEA;     //jmp
     101                *addr       = (DWORD)MySendMessage;
     102
     103                orgpostmsg  = (FUNC_PostMessage)PostMessage;   
     104                selPOST     = AllocSelector(0);
     105                PrestoChangoSelector(SELECTOROF(orgpostmsg), selPOST);
     106
     107                jumpPOST    = MAKELP(selPOST, OFFSETOF(orgpostmsg));
     108                addr        = (DWORD FAR *)(jumpPOST+1);
     109                oldcodePOST = *jumpPOST;
     110                olddataPOST = *addr;
     111                *jumpPOST   = 0xEA;     //jmp
     112                *addr       = (DWORD)MyPostMessage;
     113#endif         
    70114    }
    71115    return 1;
     
    89133            *jumpEXEC = oldcodeEXEC;
    90134            *addr     = olddataEXEC;
     135
     136#ifdef PATCH_POSTSENDMSG
     137        addr        = (DWORD FAR *)(jumpSEND + 1);
     138        *jumpSEND   = oldcodeSEND;
     139        *addr       = olddataSEND;
     140                           
     141        addr        = (DWORD FAR *)(jumpPOST + 1);
     142        *jumpPOST   = oldcodePOST;
     143        *addr       = olddataPOST;
     144#endif       
    91145    }
    92146        return 1;
     
    97151{
    98152        return 0x00005F0C;
     153}
     154#ifdef PATCH_POSTSENDMSG
     155//*****************************************************************************************
     156//*****************************************************************************************
     157BOOL FAR _loadds PASCAL MyPostMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
     158{
     159    DWORD FAR *addr;
     160    BOOL       ret;
     161    char       buffer[64];
     162
     163    addr        = (DWORD FAR *)(jumpPOST + 1);
     164    *jumpPOST   = oldcodePOST;
     165    *addr       = olddataPOST;
     166
     167#ifdef DEBUG
     168    if(hwnd == HWND_BROADCAST) {
     169        sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
     170        MessageBox(0, "PostMessage", buffer, MB_OK);
     171    }
     172#endif
     173    ret = PostMessage(hwnd, Msg, wParam, lParam);
     174
     175    *jumpPOST   = 0xEA; //jmp
     176    *addr       = (DWORD)&MyPostMessage;
     177
     178    return ret;
     179}
     180//*****************************************************************************************
     181//*****************************************************************************************
     182LRESULT FAR _loadds PASCAL MySendMessage(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
     183{
     184    DWORD FAR *addr;
     185    BOOL       ret;
     186    char       buffer[64];
     187
     188    addr        = (DWORD FAR *)(jumpSEND + 1);
     189    *jumpSEND   = oldcodeSEND;
     190    *addr       = olddataSEND;
     191
     192#ifdef DEBUG
     193    if(hwnd == HWND_BROADCAST) {
     194        sprintf(buffer, "Broadcast %x %lx %lx", Msg, wParam, lParam);
     195        MessageBox(0, "SendMessage", buffer, MB_OK);
     196    }
     197#endif
     198    ret = SendMessage(hwnd, Msg, wParam, lParam);
     199
     200    *jumpSEND   = 0xEA; //jmp
     201    *addr       = (DWORD)&MySendMessage;
     202
     203    return ret;
     204}                       
     205#endif
     206//*****************************************************************************************
     207//*****************************************************************************************
     208void FAR _loadds PASCAL SetPELdr(LPCSTR lpszPELdr)
     209{                       
     210        strcpy(szPEPath, lpszPELdr);
    99211}
    100212//*****************************************************************************************
     
    116228        BOOL fFail = TRUE;
    117229
     230    if(szPEPath[0] == 0) goto calloldfunc;
     231   
    118232        of.cBytes = sizeof(OFSTRUCT);
    119233       
     
    124238        strcpy(cmdline, lpszCmdLine);
    125239       
     240        //isolate path of executable   
    126241        while(*cmdline == ' ') cmdline++;
    127242        tmp = cmdline;
    128243        while(*tmp != ' ' && *tmp != 0) tmp++;
    129         tmp++;
    130244        *tmp = 0;
    131245       
     246        //open it to check the executable type; we only care about PE (win32) executables
     247        //we'll let the original WinExec function handle everything else
    132248        hFile = OpenFile(cmdline, &of, OF_READ);
    133249        bytesRead = _lread(hFile, &doshdr, sizeof(doshdr));
     
    163279        }
    164280
     281    //Ok, it's a PE executable. Use the PE loader to launch it
    165282        tmp = cmdline;
    166283        hMem4 = hMem1;
     
    194311                _lclose(hFile);
    195312
     313    //restore original WinExec entrypoint
    196314    addr      = (DWORD FAR *)(jumpEXEC + 1);
    197315    *jumpEXEC = oldcodeEXEC;
    198316    *addr     = olddataEXEC;
    199317       
     318        //and call it   
    200319        if(fFail) {
     320                //non-PE executable
    201321                 ret = WinExec(lpszCmdLine, fuShowCmd);
    202322        }
    203323        else {
     324                //PE executable
    204325                ret = WinExec(cmdline, fuShowCmd);
    205326                if(ret >= 32) {
     
    216337        }
    217338       
     339        //put back our WinExec override                   
    218340        *jumpEXEC   = 0xEA;     //jmp
    219341        *addr       = (DWORD)&MyWinExec;
  • trunk/src/win16ldr/odindll.def

    r5954 r21308  
    1717        MYGETVERSION    @1
    1818        MYWINEXEC               @2
     19        SETPELDR        @3
  • trunk/src/ws2_32/ws2_32.def

    r9836 r21308  
    1616; WS2HELP.dll
    1717
    18   accept                                           = WSOCK32.1
    19   bind                                             = WSOCK32.2
    20   closesocket                                      = WSOCK32.3
    21   connect                                          = WSOCK32.4
    22   gethostbyaddr                                    = WSOCK32.51
    23   gethostbyname                                    = WSOCK32.52
    24   gethostname                                      = WSOCK32.57
    25   getpeername                                      = WSOCK32.5
    26   getprotobyname                                   = WSOCK32.53
    27   getprotobynumber                                 = WSOCK32.54
    28   getservbyname                                    = WSOCK32.55
    29   getservbyport                                    = WSOCK32.56
    30   getsockname                                      = WSOCK32.6
    31   htonl                                            = WSOCK32.8
    32   htons                                            = WSOCK32.9
    33   inet_addr                                        = WSOCK32.10
    34   inet_ntoa                                        = WSOCK32.11
    35   ioctlsocket                                      = WSOCK32.12
    36   listen                                           = WSOCK32.13
    37   ntohl                                            = WSOCK32.14
    38   ntohs                                            = WSOCK32.15
    39   recv                                             = WSOCK32.16
    40   recvfrom                                         = WSOCK32.17
    41   select                                           = WSOCK32.18
    42   send                                             = WSOCK32.19
    43   sendto                                           = WSOCK32.20
    44   shutdown                                         = WSOCK32.22
    45   socket                                           = WSOCK32.23
    46   WSAEventSelect                                   = WSOCK32.3001
    47   WSAEnumNetworkEvents                             = WSOCK32.3002
    4818         
    4919EXPORTS
    50   accept                                           @1
    51   bind                                             @2
    52   closesocket                                      @3
    53   connect                                          @4
    54   getpeername                                      @5
    55   getsockname                                      @6
     20   accept                      = _accept@12                            @1
     21   bind                        = _bind@12                              @2
     22   closesocket                 = _closesocket@4                        @3
     23   connect                     = _connect@12                           @4
     24   getpeername                 = _getpeername@12                       @5
     25   getsockname                 = _getsockname@12                       @6
    5626  getsockopt = _WS2getsockopt@20                   @7
    57   htonl                                            @8
    58   htons                                            @9
    59   ioctlsocket                                      @10
    60   inet_addr                                        @11
    61   inet_ntoa                                        @12
    62   listen                                           @13
    63   ntohl                                            @14
    64   ntohs                                            @15
    65   recv                                             @16
    66   recvfrom                                         @17
    67   select                                           @18
    68   send                                             @19
    69   sendto                                           @20
     27   htonl                       = _htonl@4                              @8
     28   htons                       = _htons@4                              @9
     29   ioctlsocket                 = _ioctlsocket@12                       @10
     30   inet_addr                   = _inet_addr@4                          @11
     31   inet_ntoa                   = _inet_ntoa@4                          @12
     32   listen                      = _listen@8                             @13
     33   ntohl                       = _ntohl@4                              @14
     34   ntohs                       = _ntohs@4                              @15
     35   recv                        = _recv@16                              @16
     36   recvfrom                    = _recvfrom@24                          @17
     37   select                      = _select@20                            @18
     38   send                        = _send@16                              @19
     39   sendto                      = _sendto@24                            @20
    7040  setsockopt = _WS2setsockopt@20                   @21
    71   shutdown                                         @22
    72   socket                                           @23
     41   shutdown                    = _shutdown@8                           @22
     42   socket                      = _socket@12                            @23
    7343
    7444; WSApSetPostRoutine                               @24
     
    8555; WSAEnumNameSpaceProvidersA                       @34
    8656; WSAEnumNameSpaceProvidersW                       @35
    87   WSAEnumNetworkEvents                             @36
     57  WSAEnumNetworkEvents = _WSAEnumNetworkEvents@12  @36
    8858  WSAEnumProtocolsA = _WSAEnumProtocolsA@12        @37
    8959  WSAEnumProtocolsW = _WSAEnumProtocolsW@12        @38
    90   WSAEventSelect                                   @39
     60  WSAEventSelect    = _WSAEventSelect@12           @39
     61
    9162; WSAGetOverlappedResult                           @40
    9263; WSAGetQOSByName                                  @41
     
    10172  WSAIoctl                    = _WSAIoctl@36       @50
    10273
    103   gethostbyaddr                                    @51
    104   gethostbyname                                    @52
    105   gethostname                                      @57
    106   getprotobyname                                   @53
    107   getprotobynumber                                 @54
    108   getservbyname                                    @55
    109   getservbyport                                    @56
     74  gethostbyaddr               = _gethostbyaddr@12                     @51
     75  gethostbyname               = _gethostbyname@4                      @52
     76  gethostname                 = _gethostname@8                        @57
     77  getprotobyname              = _getprotobyname@4                     @53
     78  getprotobynumber            = _getprotobynumber@4                   @54
     79  getservbyname               = _getservbyname@8                      @55
     80  getservbyport               = _getservbyport@8                      @56
    11081
    11182; WSAJoinLeaf                                      @58
  • trunk/src/wsock32/makefile

    r10222 r21308  
    4646$(ODIN32_LIB)/user32.lib \
    4747$(ODIN32_LIB)/libwrap.lib \
    48 $(ODIN32_LIB)/iphlpapi.lib \
    4948$(ODIN32_LIB)/$(ODINCRT).lib \
    5049so32dll.lib \
  • trunk/src/wsock32/wsock32.cpp

    r9887 r21308  
    5555#include <winuser32.h>
    5656#include <wprocess.h>
    57 #include <misc.h>
     57#include <dbglog.h>
     58
     59#include <sys/types.h>
     60#include <sys/socket.h>
     61#include <net/if.h>
    5862
    5963#include "wsock32.h"
     
    212216            strcpy(msg, "WSAEHOSTUNREACH");
    213217            break;
     218        case WSAETIMEDOUT:
     219            strcpy(msg, "WSAETIMEDOUT");
     220            break;
    214221        default:
    215222            strcpy(msg, "unknown");
     
    663670
    664671   if(ret == SOCKET_ERROR) {
    665         WSASetLastError(wsaErrno());
    666         return SOCKET_ERROR;
     672        if(wsaErrno() == WSAEWOULDBLOCK) {
     673            struct timeval tv;
     674            int optlen = sizeof(tv);
     675            ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen);
     676            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
     677                  dprintf(("WSAEWOULDBLOCK: recv timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
     678                  WSASetLastError(WSAETIMEDOUT);
     679            }
     680            else  WSASetLastError(WSAEWOULDBLOCK);
     681            ret = SOCKET_ERROR;
     682        }
     683        else WSASetLastError(wsaErrno());
    667684   }
    668685   else
     
    684701        else
    685702        if(state & SS_ISCONNECTED && flags != MSG_PEEK) {
    686                 dprintf(("recv returned 0, but socket is still connected -> return WSAWOULDBLOCK"));
     703                dprintf(("recv returned 0, but socket is still connected -> return WSAEWOULDBLOCK"));
    687704                WSASetLastError(WSAEWOULDBLOCK);
    688705                return SOCKET_ERROR;
     
    699716   }
    700717
    701    //Reset FD_READ event flagfor WSAAsyncSelect thread if one was created for this socket
     718   //Reset FD_READ event flag for WSAAsyncSelect thread if one was created for this socket
    702719   EnableAsyncEvent(s, FD_READ);
    703720   return ret;
     
    732749
    733750   if(ret == SOCKET_ERROR) {
    734         WSASetLastError(wsaErrno());
     751        if(wsaErrno() == WSAEWOULDBLOCK) {
     752            struct timeval tv;
     753            int optlen = sizeof(tv);
     754            ret = getsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, &optlen);
     755            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
     756                  dprintf(("WSAEWOULDBLOCK: recvfrom timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
     757                  WSASetLastError(WSAETIMEDOUT);
     758            }
     759            else  WSASetLastError(WSAEWOULDBLOCK);
     760            ret = SOCKET_ERROR;
     761        }
     762        else WSASetLastError(wsaErrno());
    735763   }
    736764   else {
     
    789817
    790818   if(ret == SOCKET_ERROR) {
    791         WSASetLastError(wsaErrno());
     819        if(wsaErrno() == WSAEWOULDBLOCK) {
     820            struct timeval tv;
     821            int optlen = sizeof(tv);
     822            ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen);
     823            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
     824                  dprintf(("WSAEWOULDBLOCK: send timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
     825                  WSASetLastError(WSAETIMEDOUT);
     826            }
     827            else  WSASetLastError(WSAEWOULDBLOCK);
     828            ret = SOCKET_ERROR;
     829        }
     830        else WSASetLastError(wsaErrno());
    792831   }
    793832   else WSASetLastError(NO_ERROR);
     
    844883
    845884   if(ret == SOCKET_ERROR) {
    846         WSASetLastError(wsaErrno());
     885        if(wsaErrno() == WSAEWOULDBLOCK) {
     886            struct timeval tv;
     887            int optlen = sizeof(tv);
     888            ret = getsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, &optlen);
     889            if(ret == 0 && (tv.tv_sec > 0 || tv.tv_usec > 0)) {
     890                  dprintf(("WSAEWOULDBLOCK: sendto timeout set to %ds%dus -> return WSAETIMEDOUT", tv.tv_sec, tv.tv_usec));
     891                  WSASetLastError(WSAETIMEDOUT);
     892            }
     893            else  WSASetLastError(WSAEWOULDBLOCK);
     894            ret = SOCKET_ERROR;
     895        }
     896        else WSASetLastError(wsaErrno());
    847897   }
    848898   else WSASetLastError(NO_ERROR);
     
    906956
    907957        sockets = (int *)malloc(sizeof(int) * (nrread+nrwrite+nrexcept));
    908         if(readfds) {
     958        if(readfds && nrread) {
    909959                memcpy(&sockets[0], readfds->fd_array, nrread * sizeof(SOCKET));
    910960        }
    911         if(writefds) {
     961        if(writefds && nrwrite) {
    912962                memcpy(&sockets[nrread], writefds->fd_array, nrwrite * sizeof(SOCKET));
    913963        }
    914         if(exceptfds) {
     964        if(exceptfds && nrexcept) {
    915965                memcpy(&sockets[nrread+nrwrite], exceptfds->fd_array, nrexcept * sizeof(SOCKET));
    916966        }
     
    940990                        for(i=0;i<nrread;i++) {
    941991                                if(socktmp[i] != -1) {
    942                                         readfds->fd_array[i] = socktmp[i];
     992                                        readfds->fd_array[j] = socktmp[i];
     993                                        dprintf(("Socket %d read pending", socktmp[i]));
    943994                                        j++;
    944995                                }
     
    9521003                        for(i=0;i<nrwrite;i++) {
    9531004                                if(socktmp[i] != -1) {
    954                                         writefds->fd_array[i] = socktmp[i];
     1005                                        writefds->fd_array[j] = socktmp[i];
     1006                                        dprintf(("Socket %d write pending", socktmp[i]));
    9551007                                        j++;
    9561008                                }
     
    9631015                        for(i=0;i<nrexcept;i++) {
    9641016                                if(socktmp[i] != -1) {
    965                                         exceptfds->fd_array[i] = socktmp[i];
     1017                                        exceptfds->fd_array[j] = socktmp[i];
    9661018                                        j++;
    9671019                                }
     
    9841036   return ret;
    9851037}
     1038#ifdef DEBUG_LOGGING
     1039//******************************************************************************
     1040//******************************************************************************
     1041char *debugsockopt(int optname)
     1042{
     1043    switch(optname) {
     1044    case SO_DONTLINGER:
     1045         return "SO_DONTLINGER";
     1046    case SO_LINGER:
     1047         return "SO_LINGER";
     1048    case SO_REUSEADDR:
     1049         return "SO_REUSEADDR";
     1050    case SO_SNDTIMEO:
     1051         return "SO_SNDTIMEO";
     1052    case SO_RCVTIMEO:
     1053         return "SO_RCVTIMEO";
     1054    case SO_SNDBUF:
     1055         return "SO_SNDBUF";
     1056    case SO_RCVBUF:
     1057         return "SO_RCVBUF";
     1058    case SO_BROADCAST:
     1059         return "SO_BROADCAST";
     1060    case SO_DEBUG:
     1061         return "SO_DEBUG";
     1062    case SO_KEEPALIVE:
     1063         return "SO_KEEPALIVE";
     1064    case SO_DONTROUTE:
     1065         return "SO_DONTROUTE";
     1066    case SO_OOBINLINE:
     1067         return "SO_OOBINLINE";
     1068    case SO_TYPE:
     1069         return "SO_TYPE";
     1070    case SO_ERROR:
     1071         return "SO_ERROR";
     1072    case SO_SNDLOWAT:
     1073         return "SO_SNDLOWAT";
     1074    case SO_RCVLOWAT:
     1075         return "SO_RCVLOWAT";
     1076    case SO_USELOOPBACK:
     1077         return "SO_USELOOPBACK";
     1078    case SO_ACCEPTCONN:
     1079         return "SO_ACCEPTCONN";
     1080    default:
     1081        return "unknown option";
     1082    }
     1083}
     1084#endif
    9861085//******************************************************************************
    9871086//******************************************************************************
     
    10641163        case SO_SNDTIMEO:
    10651164        case SO_RCVTIMEO:
     1165        {
     1166                if(optlen < (int)sizeof(int))
     1167                {
     1168                        dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small"));
     1169                        WSASetLastError(WSAEFAULT);
     1170                        return SOCKET_ERROR;
     1171                }
    10661172          // convert "int" to "struct timeval"
    10671173          struct timeval tv;
    1068           tv.tv_sec = *optval / 1000;
    1069           tv.tv_usec = (*optval % 1000) * 1000;
     1174                tv.tv_sec = (*(int *)optval) / 1000;
     1175                tv.tv_usec = ((*(int *)optval) % 1000) * 1000;
     1176                if(optname == SO_SNDTIMEO) {
     1177                     dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
     1178                }
     1179                else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
     1180
    10701181          ret = setsockopt(s, level, optname, (char *)&tv, sizeof(tv) );
    10711182          break;
     1183        }
     1184
     1185        case SO_REUSEADDR:
     1186                if(optlen < (int)sizeof(int)) {
     1187                        dprintf(("SO_REUSEADDR, optlen too small"));
     1188                        WSASetLastError(WSAEFAULT);
     1189                        return SOCKET_ERROR;
     1190                }
     1191                dprintf(("option SO_REUSEADDR value %d", *(int *)optval));
     1192                ret = setsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen);
     1193                if(ret) {
     1194                    dprintf(("setsockopt SO_REUSEADDR failed!!"));
     1195                }
     1196                ret = setsockopt(s, level, SO_REUSEPORT_OS2, (char *)optval, optlen);
     1197                if(ret) {
     1198                    dprintf(("setsockopt SO_REUSEPORT failed!!"));
     1199                }
     1200                break;
    10721201
    10731202        case SO_BROADCAST:
     
    10761205        case SO_DONTROUTE:
    10771206        case SO_OOBINLINE:
    1078         case SO_REUSEADDR:
     1207        case SO_ERROR:
     1208        case SO_SNDLOWAT:
     1209        case SO_RCVLOWAT:
     1210        case SO_ACCEPTCONN:
     1211        case SO_USELOOPBACK:
    10791212                if(optlen < (int)sizeof(int)) {
    1080                         dprintf(("SOL_SOCKET, SO_REUSEADDR, optlen too small"));
     1213                        dprintf(("%s optlen too small", debugsockopt(optname)));
    10811214                        WSASetLastError(WSAEFAULT);
    10821215                        return SOCKET_ERROR;
    10831216                }
     1217                dprintf(("option %s = %x", debugsockopt(optname), *(int *)optval));
    10841218                ret = setsockopt(s, level, optname, (char *)optval, optlen);
    10851219                break;
     
    11531287           {
    11541288               u_int flLoop;
    1155                if (optlen < sizeof(u_char))
     1289               if (optlen < sizeof(u_int))
    11561290               {
    11571291                   dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
     
    11611295               flLoop = (*optval == 0) ? 0 : 1;
    11621296               dprintf(("IP_MULTICAST_LOOP %d", *optval));
    1163                ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, optlen);
     1297               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)&flLoop, sizeof(u_char));
    11641298               break;
    11651299           }
     
    11671301           case IP_MULTICAST_TTL:
    11681302           case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
    1169                if (optlen < sizeof(u_char))
     1303               if (optlen < sizeof(u_int))
    11701304               {
    11711305                   dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
     
    11731307                   return SOCKET_ERROR;
    11741308               }
    1175                ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
     1309               dprintf(("IP_MULTICAST_TTL %d", *optval));
     1310               ret = setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, sizeof(u_char));
    11761311               break;
    11771312
     
    12101345               dprintf(("IPPROTO_IP, IP_HDRINCL 0x%x", val));
    12111346               ret = setsockopt(s, IPPROTO_IP, IP_HDRINCL_OS2, (char *)&val, optlen);
     1347               break;
     1348
     1349           case IP_DONTFRAGMENT:
     1350           case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2):
     1351               //MSDN says these options are silently ignored
     1352               dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored"));
     1353               ret = 0;
    12121354               break;
    12131355
     
    12691411                break;
    12701412
     1413        case SO_REUSEADDR:
     1414                if(optlen == NULL || *optlen < sizeof(int)) {
     1415                        WSASetLastError(WSAEFAULT);
     1416                        return SOCKET_ERROR;
     1417                }
     1418                ret = getsockopt(s, level, SO_REUSEADDR, (char *)optval, optlen);
     1419                dprintf(("getsockopt SO_REUSEADDR returned %d", *(int *)optval, optname));
     1420                break;
     1421                break;
     1422
     1423        case SO_SNDTIMEO:
     1424        case SO_RCVTIMEO:
     1425        {
     1426                if(optlen == NULL || *optlen < sizeof(int))
     1427                {
     1428                        dprintf(("SO_RCVTIMEO, SO_SNDTIMEO, optlen too small"));
     1429                        WSASetLastError(WSAEFAULT);
     1430                        return SOCKET_ERROR;
     1431                }
     1432                struct timeval tv;
     1433                int size = sizeof(tv);
     1434                ret = getsockopt(s, level, optname, (char *)&tv, &size );
     1435
     1436                // convert "struct timeval" to "int"
     1437                *(int *)optval = (tv.tv_sec * 1000) + tv.tv_usec/1000;
     1438                if(optname == SO_SNDTIMEO) {
     1439                     dprintf(("SO_SNDTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
     1440                }
     1441                else dprintf(("SO_RCVTIMEO: int val %x sec %d, usec %d", *(int *)optval, tv.tv_sec, tv.tv_usec));
     1442
     1443                break;
     1444        }
     1445
    12711446        case SO_SNDBUF:
    12721447        case SO_RCVBUF:
     
    12761451        case SO_DONTROUTE:
    12771452        case SO_OOBINLINE:
    1278         case SO_REUSEADDR:
    12791453        case SO_TYPE:
     1454        case SO_ERROR:
     1455        case SO_SNDLOWAT:
     1456        case SO_RCVLOWAT:
     1457        case SO_USELOOPBACK:
    12801458                if(optlen == NULL || *optlen < sizeof(int)) {
    12811459                        WSASetLastError(WSAEFAULT);
     
    12831461                }
    12841462                ret = getsockopt(s, level, optname, (char *)optval, optlen);
     1463                dprintf(("getsockopt %s returned %d", debugsockopt(optname), *(int *)optval));
    12851464                break;
     1465
    12861466        case SO_ACCEPTCONN:
    12871467                if(optlen == NULL || *optlen < sizeof(int)) {
     
    12941474                        *(BOOL *)optval = (options & SO_ACCEPTCONN) == SO_ACCEPTCONN;
    12951475                        *optlen = sizeof(BOOL);
     1476                        dprintf(("SO_ACCEPTCONN returned %d", *(BOOL *)optval));
    12961477                }
    12971478                break;
     
    13571538               break;
    13581539
     1540           case IP_MULTICAST_LOOP_WS2: //for buggy applications that intended to call ws_32.getsockopt
    13591541           case IP_MULTICAST_LOOP:
    13601542           case WS2_IPPROTO_OPT(IP_MULTICAST_LOOP_WS2):
    13611543           {
    1362                if (*optlen < sizeof(u_char))
     1544               if (*optlen < sizeof(u_int))
    13631545               {
    13641546                   dprintf(("IPPROTO_IP, IP_MULTICAST_LOOP/IP_MULTICAST_TTL, optlen too small"));
     
    13661548                   return SOCKET_ERROR;
    13671549               }
     1550               memset(optval, 0, *optlen);
    13681551               ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP_OS2, (char *)optval, optlen);
    13691552               break;
     
    13721555           case IP_MULTICAST_TTL:
    13731556           case WS2_IPPROTO_OPT(IP_MULTICAST_TTL_WS2):
    1374                if (*optlen < sizeof(u_char))
     1557               if (*optlen < sizeof(u_int))
    13751558               {
    13761559                   dprintf(("IPPROTO_IP, IP_MULTICAST_TTL, optlen too small"));
     
    13781561                   return SOCKET_ERROR;
    13791562               }
     1563               memset(optval, 0, *optlen);
    13801564               ret = getsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL_OS2, (char *)optval, optlen);
     1565               dprintf(("getsockopt IP_MULTICAST_TTL_OS2 returned %d, size %d", (int)*optval, *optlen));
    13811566               break;
    13821567
     
    13891574                   return SOCKET_ERROR;
    13901575               }
     1576               memset(optval, 0, *optlen);
    13911577               ret = getsockopt(s, IPPROTO_IP, IP_TTL_OS2, (char *)optval, optlen);
    13921578               break;
     
    14151601               }
    14161602               break;
     1603
     1604           case IP_DONTFRAGMENT:
     1605           case WS2_IPPROTO_OPT(IP_DONTFRAGMENT_WS2):
     1606               //MSDN says these options are silently ignored
     1607               if (*optlen < sizeof(u_int))
     1608               {
     1609                   dprintf(("IP_DONTFRAGMENT, IP_DONTFRAGMENT_WS2, optlen too small"));
     1610                   WSASetLastError(WSAEFAULT);
     1611                   return SOCKET_ERROR;
     1612               }
     1613               dprintf(("IPPROTO_IP: IP_DONTFRAGMENT ignored"));
     1614               *optlen = sizeof(u_int);
     1615               *(int *)optval = 0;
     1616               ret = 0;
     1617               break;
     1618
    14171619
    14181620           default:
     
    14811683//      I.e. start ISDNPM without dialing in. gethostbyname will query
    14821684//      each name server and retry several times (60+ seconds per name server)
     1685//
     1686static struct ws_hostent localhost;
     1687static DWORD  localhost_address;
     1688static DWORD  localhost_addrlist[2] = {(DWORD)&localhost_address, 0};
     1689static DWORD  localhost_aliaslist[1] = {0};
    14831690//******************************************************************************
    14841691ODINFUNCTION1(ws_hostent *,OS2gethostbyname,
     
    14931700
    14941701    dprintf(("gethostbyname %s", name));
    1495     if(gethostname(localhostname, sizeof(localhostname)) == NO_ERROR)
     1702    if (!gethostname(localhostname, sizeof(localhostname)))
    14961703    {
    1497         if(!strcmp(name, localhostname)) {
     1704        /*
     1705         * This is a fast non-blocking path for the hostname of this machine.
     1706         * It's probably not 100% correct though..
     1707         */
     1708        if (!strcmp(name, localhostname))
     1709        {
     1710            /*
     1711             * Lookup lan0 address, and move on to lo address if that fails.
     1712             */
     1713            sock_init();                /* ??? */
     1714            int s = socket(PF_INET, SOCK_STREAM, 0);
     1715            if (s >= 0)
     1716            {
     1717                struct ifreq  ifr = {0};
     1718                strcpy(ifr.ifr_name, "lan0");
     1719                int rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr));
     1720                if (rc == -1)
     1721                {
     1722                    strcpy(ifr.ifr_name, "lo");
     1723                    rc = ioctl(s, SIOCGIFADDR, (char*)&ifr, sizeof(ifr));
     1724                }
     1725                soclose(s);
     1726
     1727                if (rc != -1)
     1728                {
     1729                    /* ASSUMES: family is AF_INET */
     1730                    /* Doesn't work with aliases on lan0. */
     1731                    struct sockaddr_in *addr = (struct sockaddr_in *)&ifr.ifr_addr;
     1732
     1733                    localhost_address       = *(unsigned long *)&addr->sin_addr;
     1734                    localhost.h_name        = "localhost"; /* This is what the old workaround did. */
     1735                    localhost.h_addrtype    = AF_INET;
     1736                    localhost.h_length      = 4;
     1737                    localhost.h_addr_list   = (char **)&localhost_addrlist[0];
     1738                    localhost.h_aliases     = (char **)&localhost_aliaslist[0];
     1739                    WSASetLastError(NO_ERROR);
     1740                    return &localhost;
     1741                }
     1742            }
     1743
     1744            /*
     1745             * bail out..
     1746             */
    14981747            strcpy(localhostname, "localhost");
    14991748            name = localhostname;
  • trunk/src/wsock32/wsock32.def

    r6201 r21308  
    107107;  TransmitFile                = _OS2TransmitFile
    108108
     109;
     110; ENDOFEXPORTS
     111; Internal function marker
     112;
     113
    109114; -----------------------
    110115; ODIN internal functions
  • trunk/src/wsock32/wsock32.h

    r7977 r21308  
    2424#define IP_TTL              7
    2525#define IP_TOS              8
     26#define IP_DONTFRAGMENT     9
    2627#endif
    2728
Note: See TracChangeset for help on using the changeset viewer.