Sync to Wine-20050628:
authorGé van Geldorp <ge@gse.nl>
Wed, 3 Aug 2005 22:46:31 +0000 (22:46 +0000)
committerGé van Geldorp <ge@gse.nl>
Wed, 3 Aug 2005 22:46:31 +0000 (22:46 +0000)
Dmitry Timoshkov <dmitry@codeweavers.com>
- Make remaining OLE interface vtables const.
Robert Shearman <rob@codeweavers.com>
- DispInvoke is correct so there is no need to print a fixme.
- The typelib marshaler should only free the memory it actually allocated.
- Add special cases for two lesser used types that aren't
  sizeof(DWORD) sized.
- If we are accessing a method from a superclass then we need to use the
  superclass's ITypeInfo otherwise we could get errors when accessing
  hreftypes that aren't present in the subclass.
- Don't print out cryptic message if IDispatch or IUnknown object is
  just NULL.
- puArgErr is a ref pointer so we have to provide a dummy pointer if
  it is NULL.
- Fail gracefully and notify caller if we ran out of memoy or if
  variant copying failed.
- Clear out parameters to stop bad pointers lying around in memory if
  the function doesn't set them to anything.
- Fix the return values from QueryPathOfRegTypeLib.
- Open registry key with least access rights necessary.
- Documentation updates.
Michael Stefaniuc <mstefani@redhat.de>
- VarCmp: handle comparision of VT_EMPTY with an integer
- small comment fix
- Reimplement VarAdd, had missing functionality and wrong behaviour.
- Fix a typo in VarMul.
- more VarFormat fixes for number formats (exponent, mixed '#' and '0'
  in formats, rounding, etc). Simplify the code.
- previous VarFormat todo_wine tests pass now + add more tests
- Fix VarFormat for formats that mix '0' and '#' in the whole number
  part.
- Fix VarFormat for negative exponent formats.
- Add tests for the above + a couple of "todo_wine"'s.
- implement handling of exponents (e+,e-,E+,E-) when parsing number
  formats
- fix a small cut'n'paste error in the comments
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Marcus Meissner <marcus@jet.franken.de>
- Added VarMonthName() implementation.
- Corrected string length method in ITypeLib::IsName() and FindName()
  for LPOLESTR type.
- Fixed IType::Invoke in regards to handling propertyget variables
  longer than 4 bytes (like VT_DATE).
- Added testcases for OLE Picture handling.
- Implemented PICTYPE_NONE loading.
- Cleaned up stream loading, handle "lt" magic.
- Fixed some small problems exposed by tests against native.
Stefan Huehner <stefan@huehner.org>
- Fix some more -Wstrict-prototypes warnings.
Huw Davies <huw@codeweavers.com>
- Add comments describing the first DWORD in an import table entry.

svn path=/trunk/; revision=17037

14 files changed:
reactos/lib/oleaut32/connpt.c
reactos/lib/oleaut32/dispatch.c
reactos/lib/oleaut32/oaidl_p.c
reactos/lib/oleaut32/oleaut32.spec
reactos/lib/oleaut32/olefont.c
reactos/lib/oleaut32/olepicture.c
reactos/lib/oleaut32/recinfo.c
reactos/lib/oleaut32/tmarshal.c
reactos/lib/oleaut32/typelib.c
reactos/lib/oleaut32/typelib.h
reactos/lib/oleaut32/typelib2.c
reactos/lib/oleaut32/usrmarshal.c
reactos/lib/oleaut32/varformat.c
reactos/lib/oleaut32/variant.c

index b2afb6a..f13bd67 100644 (file)
@@ -48,7 +48,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
  */
 typedef struct ConnectionPointImpl {
 
-  IConnectionPointVtbl       *lpvtbl;
+  const IConnectionPointVtbl *lpvtbl;
 
   /* IUnknown of our main object*/
   IUnknown *Obj;
@@ -66,7 +66,7 @@ typedef struct ConnectionPointImpl {
   DWORD nSinks;
 } ConnectionPointImpl;
 
-static IConnectionPointVtbl ConnectionPointImpl_VTable;
+static const IConnectionPointVtbl ConnectionPointImpl_VTable;
 
 
 /************************************************************************
@@ -74,7 +74,7 @@ static IConnectionPointVtbl ConnectionPointImpl_VTable;
  */
 typedef struct EnumConnectionsImpl {
 
-  IEnumConnectionsVtbl       *lpvtbl;
+  const IEnumConnectionsVtbl *lpvtbl;
 
   DWORD ref;
 
@@ -351,7 +351,7 @@ static HRESULT WINAPI ConnectionPointImpl_EnumConnections(
   return hr;
 }
 
-static IConnectionPointVtbl ConnectionPointImpl_VTable =
+static const IConnectionPointVtbl ConnectionPointImpl_VTable =
 {
   ConnectionPointImpl_QueryInterface,
   ConnectionPointImpl_AddRef,
@@ -364,7 +364,7 @@ static IConnectionPointVtbl ConnectionPointImpl_VTable =
 };
 
 
-static IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
+static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable;
 static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface);
 
 /************************************************************************
@@ -587,7 +587,7 @@ static HRESULT WINAPI EnumConnectionsImpl_Clone(IEnumConnections* iface,
   return S_OK;
 }
 
-static IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
+static const IEnumConnectionsVtbl EnumConnectionsImpl_VTable =
 {
   EnumConnectionsImpl_QueryInterface,
   EnumConnectionsImpl_AddRef,
index 37514b3..fd9d7b2 100644 (file)
@@ -17,7 +17,6 @@
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
- * TODO: Type coercion is implemented in variant.c but not called yet.
  */
 
 #include "config.h"
@@ -78,11 +77,7 @@ HRESULT WINAPI DispInvoke(
        EXCEPINFO  *pexcepinfo,   /* [out] Destination for exception information */
        UINT       *puArgErr)     /* [out] Destination for bad argument */
 {
-    /**
-     * TODO:
-     * For each param, call DispGetParam to perform type coercion
-     */
-    FIXME("Coercion of arguments not implemented\n");
+    TRACE("\n");
 
     return ITypeInfo_Invoke(ptinfo, _this, dispidMember, wFlags,
                             pparams, pvarResult, pexcepinfo, puArgErr);
@@ -219,7 +214,7 @@ HRESULT WINAPI CreateStdDispatch(
 
 typedef struct
 {
-    IDispatchVtbl *lpVtbl;
+    const IDispatchVtbl *lpVtbl;
     void * pvThis;
     ITypeInfo * pTypeInfo;
     ULONG ref;
@@ -422,7 +417,7 @@ static HRESULT WINAPI StdDispatch_Invoke(LPDISPATCH iface, DISPID dispIdMember,
     return DispInvoke(This->pvThis, This->pTypeInfo, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
 }
 
-static IDispatchVtbl StdDispatch_VTable =
+static const IDispatchVtbl StdDispatch_VTable =
 {
   StdDispatch_QueryInterface,
   StdDispatch_AddRef,
index 18109da..1102e1c 100644 (file)
@@ -906,7 +906,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(7) _IDispatchProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(7) _IDispatchProxyVtbl = 
 {
     { &IID_IDispatch },
     {
@@ -929,7 +929,7 @@ static const PRPC_STUB_FUNCTION IDispatch_table[] =
     IDispatch_RemoteInvoke_Stub
 };
 
-const CInterfaceStubVtbl _IDispatchStubVtbl =
+static const CInterfaceStubVtbl _IDispatchStubVtbl =
 {
     {
         &IID_IDispatch,
@@ -1447,7 +1447,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(7) _IEnumVARIANTProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(7) _IEnumVARIANTProxyVtbl = 
 {
     { &IID_IEnumVARIANT },
     {
@@ -1470,7 +1470,7 @@ static const PRPC_STUB_FUNCTION IEnumVARIANT_table[] =
     IEnumVARIANT_Clone_Stub
 };
 
-const CInterfaceStubVtbl _IEnumVARIANTStubVtbl =
+static const CInterfaceStubVtbl _IEnumVARIANTStubVtbl =
 {
     {
         &IID_IEnumVARIANT,
@@ -2009,7 +2009,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(5) _ITypeCompProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(5) _ITypeCompProxyVtbl = 
 {
     { &IID_ITypeComp },
     {
@@ -2028,7 +2028,7 @@ static const PRPC_STUB_FUNCTION ITypeComp_table[] =
     ITypeComp_RemoteBindType_Stub
 };
 
-const CInterfaceStubVtbl _ITypeCompStubVtbl =
+static const CInterfaceStubVtbl _ITypeCompStubVtbl =
 {
     {
         &IID_ITypeComp,
@@ -4804,7 +4804,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(22) _ITypeInfoProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(22) _ITypeInfoProxyVtbl = 
 {
     { &IID_ITypeInfo },
     {
@@ -4857,7 +4857,7 @@ static const PRPC_STUB_FUNCTION ITypeInfo_table[] =
     ITypeInfo_LocalReleaseVarDesc_Stub
 };
 
-const CInterfaceStubVtbl _ITypeInfoStubVtbl =
+static const CInterfaceStubVtbl _ITypeInfoStubVtbl =
 {
     {
         &IID_ITypeInfo,
@@ -7141,7 +7141,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(37) _ITypeInfo2ProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(37) _ITypeInfo2ProxyVtbl = 
 {
     { &IID_ITypeInfo2 },
     {
@@ -7224,7 +7224,7 @@ static const PRPC_STUB_FUNCTION ITypeInfo2_table[] =
     ITypeInfo2_GetAllImplTypeCustData_Stub
 };
 
-const CInterfaceStubVtbl _ITypeInfo2StubVtbl =
+static const CInterfaceStubVtbl _ITypeInfo2StubVtbl =
 {
     {
         &IID_ITypeInfo2,
@@ -8924,7 +8924,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(13) _ITypeLibProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(13) _ITypeLibProxyVtbl = 
 {
     { &IID_ITypeLib },
     {
@@ -8959,7 +8959,7 @@ static const PRPC_STUB_FUNCTION ITypeLib_table[] =
     ITypeLib_LocalReleaseTLibAttr_Stub
 };
 
-const CInterfaceStubVtbl _ITypeLibStubVtbl =
+static const CInterfaceStubVtbl _ITypeLibStubVtbl =
 {
     {
         &IID_ITypeLib,
@@ -9631,7 +9631,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(17) _ITypeLib2ProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(17) _ITypeLib2ProxyVtbl = 
 {
     { &IID_ITypeLib2 },
     {
@@ -10330,7 +10330,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(8) _IErrorInfoProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(8) _IErrorInfoProxyVtbl = 
 {
     { &IID_IErrorInfo },
     {
@@ -10355,7 +10355,7 @@ static const PRPC_STUB_FUNCTION IErrorInfo_table[] =
     IErrorInfo_GetHelpContext_Stub
 };
 
-const CInterfaceStubVtbl _IErrorInfoStubVtbl =
+static const CInterfaceStubVtbl _IErrorInfoStubVtbl =
 {
     {
         &IID_IErrorInfo,
@@ -10926,7 +10926,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(8) _ICreateErrorInfoProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(8) _ICreateErrorInfoProxyVtbl = 
 {
     { &IID_ICreateErrorInfo },
     {
@@ -10951,7 +10951,7 @@ static const PRPC_STUB_FUNCTION ICreateErrorInfo_table[] =
     ICreateErrorInfo_SetHelpContext_Stub
 };
 
-const CInterfaceStubVtbl _ICreateErrorInfoStubVtbl =
+static const CInterfaceStubVtbl _ICreateErrorInfoStubVtbl =
 {
     {
         &IID_ICreateErrorInfo,
@@ -11080,7 +11080,7 @@ NdrStubInitialize(
     
 }
 
-const CINTERFACE_PROXY_VTABLE(4) _ISupportErrorInfoProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(4) _ISupportErrorInfoProxyVtbl = 
 {
     { &IID_ISupportErrorInfo },
     {
@@ -11097,7 +11097,7 @@ static const PRPC_STUB_FUNCTION ISupportErrorInfo_table[] =
     ISupportErrorInfo_InterfaceSupportsErrorInfo_Stub
 };
 
-const CInterfaceStubVtbl _ISupportErrorInfoStubVtbl =
+static const CInterfaceStubVtbl _ISupportErrorInfoStubVtbl =
 {
     {
         &IID_ISupportErrorInfo,
@@ -11347,7 +11347,7 @@ static const MIDL_STUB_DESC Object_StubDesc =
     0   /* Reserved5 */
     };
 
-const CINTERFACE_PROXY_VTABLE(4) _ITypeFactoryProxyVtbl = 
+static const CINTERFACE_PROXY_VTABLE(4) _ITypeFactoryProxyVtbl = 
 {
     { &IID_ITypeFactory },
     {
@@ -11364,7 +11364,7 @@ static const PRPC_STUB_FUNCTION ITypeFactory_table[] =
     ITypeFactory_CreateFromTypeInfo_Stub
 };
 
-const CInterfaceStubVtbl _ITypeFactoryStubVtbl =
+static const CInterfaceStubVtbl _ITypeFactoryStubVtbl =
 {
     {
         &IID_ITypeFactory,
@@ -13702,39 +13702,39 @@ static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =
         }
     };
 
-const CInterfaceProxyVtbl * _oaidl_ProxyVtblList[] = 
-{
-    ( CInterfaceProxyVtbl *) &_IDispatchProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeInfoProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeLibProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeCompProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_IEnumVARIANTProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeLib2ProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeInfo2ProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_IErrorInfoProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ITypeFactoryProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ICreateErrorInfoProxyVtbl,
-    ( CInterfaceProxyVtbl *) &_ISupportErrorInfoProxyVtbl,
+static const CInterfaceProxyVtbl * _oaidl_ProxyVtblList[] = 
+{
+    ( const CInterfaceProxyVtbl *) &_IDispatchProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeInfoProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeLibProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeCompProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_IEnumVARIANTProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeLib2ProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeInfo2ProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_IErrorInfoProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ITypeFactoryProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ICreateErrorInfoProxyVtbl,
+    ( const CInterfaceProxyVtbl *) &_ISupportErrorInfoProxyVtbl,
     0
 };
 
-const CInterfaceStubVtbl * _oaidl_StubVtblList[] = 
-{
-    ( CInterfaceStubVtbl *) &_IDispatchStubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeInfoStubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeLibStubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeCompStubVtbl,
-    ( CInterfaceStubVtbl *) &_IEnumVARIANTStubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeLib2StubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeInfo2StubVtbl,
-    ( CInterfaceStubVtbl *) &_IErrorInfoStubVtbl,
-    ( CInterfaceStubVtbl *) &_ITypeFactoryStubVtbl,
-    ( CInterfaceStubVtbl *) &_ICreateErrorInfoStubVtbl,
-    ( CInterfaceStubVtbl *) &_ISupportErrorInfoStubVtbl,
+static const CInterfaceStubVtbl * _oaidl_StubVtblList[] = 
+{
+    ( const CInterfaceStubVtbl *) &_IDispatchStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeInfoStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeLibStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeCompStubVtbl,
+    ( const CInterfaceStubVtbl *) &_IEnumVARIANTStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeLib2StubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeInfo2StubVtbl,
+    ( const CInterfaceStubVtbl *) &_IErrorInfoStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ITypeFactoryStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ICreateErrorInfoStubVtbl,
+    ( const CInterfaceStubVtbl *) &_ISupportErrorInfoStubVtbl,
     0
 };
 
-PCInterfaceName const _oaidl_InterfaceNamesList[] = 
+static const PCInterfaceName _oaidl_InterfaceNamesList[] = 
 {
     "IDispatch",
     "ITypeInfo",
@@ -13767,8 +13767,8 @@ int __stdcall _oaidl_IID_Lookup( const IID * pIID, int * pIndex )
 
 const ExtendedProxyFileInfo oaidl_ProxyFileInfo = 
 {
-    (PCInterfaceProxyVtblList *) & _oaidl_ProxyVtblList,
-    (PCInterfaceStubVtblList *) & _oaidl_StubVtblList,
+    (const PCInterfaceProxyVtblList *) & _oaidl_ProxyVtblList,
+    (const PCInterfaceStubVtblList *) & _oaidl_StubVtblList,
     (const PCInterfaceName * ) & _oaidl_InterfaceNamesList,
     0, /* no delegation */
     & _oaidl_IID_Lookup, 
index 0a8ac66..c49de81 100644 (file)
 126 stdcall VarBoolFromDisp(ptr long ptr)\r
 127 stdcall VarFormatCurrency(ptr long long long long long ptr)\r
 128 stub VarWeekdayName # stdcall (long long long long ptr)\r
-129 stub VarMonthName # stdcall (long long long ptr)\r
+129 stdcall VarMonthName(long long long ptr)\r
 130 stdcall VarUI1FromI2(long ptr)\r
 131 stdcall VarUI1FromI4(long ptr)\r
 132 stdcall VarUI1FromR4(long ptr)\r
index eaceefe..2e6395a 100644 (file)
@@ -63,12 +63,12 @@ struct OLEFontImpl
    * The first two are supported by the first vtable, the next two are
    * supported by the second table and the last two have their own.
    */
-  IFontVtbl*                           lpvtbl1;
-  IDispatchVtbl*                       lpvtbl2;
-  IPersistStreamVtbl*                  lpvtbl3;
-  IConnectionPointContainerVtbl*       lpvtbl4;
-  IPersistPropertyBagVtbl*             lpvtbl5;
-  IPersistStreamInitVtbl*              lpvtbl6;
+  const IFontVtbl*                     lpvtbl1;
+  const IDispatchVtbl*                 lpvtbl2;
+  const IPersistStreamVtbl*            lpvtbl3;
+  const IConnectionPointContainerVtbl* lpvtbl4;
+  const IPersistPropertyBagVtbl*       lpvtbl5;
+  const IPersistStreamInitVtbl*        lpvtbl6;
   /*
    * Reference count for that instance of the class.
    */
@@ -219,7 +219,7 @@ static HRESULT WINAPI OLEFontImpl_FindConnectionPoint(
 /*
  * Virtual function tables for the OLEFontImpl class.
  */
-static IFontVtbl OLEFontImpl_VTable =
+static const IFontVtbl OLEFontImpl_VTable =
 {
   OLEFontImpl_QueryInterface,
   OLEFontImpl_AddRef,
@@ -250,7 +250,7 @@ static IFontVtbl OLEFontImpl_VTable =
   OLEFontImpl_SetHdc
 };
 
-static IDispatchVtbl OLEFontImpl_IDispatch_VTable =
+static const IDispatchVtbl OLEFontImpl_IDispatch_VTable =
 {
   OLEFontImpl_IDispatch_QueryInterface,
   OLEFontImpl_IDispatch_AddRef,
@@ -261,7 +261,7 @@ static IDispatchVtbl OLEFontImpl_IDispatch_VTable =
   OLEFontImpl_Invoke
 };
 
-static IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
+static const IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
 {
   OLEFontImpl_IPersistStream_QueryInterface,
   OLEFontImpl_IPersistStream_AddRef,
@@ -273,7 +273,7 @@ static IPersistStreamVtbl OLEFontImpl_IPersistStream_VTable =
   OLEFontImpl_GetSizeMax
 };
 
-static IConnectionPointContainerVtbl
+static const IConnectionPointContainerVtbl
      OLEFontImpl_IConnectionPointContainer_VTable =
 {
   OLEFontImpl_IConnectionPointContainer_QueryInterface,
@@ -283,8 +283,9 @@ static IConnectionPointContainerVtbl
   OLEFontImpl_FindConnectionPoint
 };
 
-static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable;
-static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable;
+static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable;
+static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable;
+
 /******************************************************************************
  *             OleCreateFontIndirect   [OLEAUT32.420]
  */
@@ -2002,7 +2003,7 @@ static HRESULT WINAPI OLEFontImpl_IPersistPropertyBag_Save(
   return E_FAIL;
 }
 
-static IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
+static const IPersistPropertyBagVtbl OLEFontImpl_IPersistPropertyBag_VTable = 
 {
   OLEFontImpl_IPersistPropertyBag_QueryInterface,
   OLEFontImpl_IPersistPropertyBag_AddRef,
@@ -2080,7 +2081,7 @@ static HRESULT WINAPI OLEFontImpl_IPersistStreamInit_InitNew(
   return S_OK;
 }
 
-static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
+static const IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable = 
 {
   OLEFontImpl_IPersistStreamInit_QueryInterface,
   OLEFontImpl_IPersistStreamInit_AddRef,
@@ -2100,7 +2101,7 @@ static IPersistStreamInitVtbl OLEFontImpl_IPersistStreamInit_VTable =
 typedef struct
 {
     /* IUnknown fields */
-    IClassFactoryVtbl          *lpVtbl;
+    const IClassFactoryVtbl    *lpVtbl;
     DWORD                       ref;
 } IClassFactoryImpl;
 
@@ -2137,7 +2138,7 @@ static HRESULT WINAPI SFCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
        return S_OK;
 }
 
-static IClassFactoryVtbl SFCF_Vtbl = {
+static const IClassFactoryVtbl SFCF_Vtbl = {
        SFCF_QueryInterface,
        SFCF_AddRef,
        SFCF_Release,
index b0d3532..6d40403 100644 (file)
@@ -103,10 +103,10 @@ typedef struct OLEPictureImpl {
    * IPicture handles IUnknown
    */
 
-    IPictureVtbl       *lpvtbl1;
-    IDispatchVtbl      *lpvtbl2;
-    IPersistStreamVtbl *lpvtbl3;
-    IConnectionPointContainerVtbl *lpvtbl4;
+    const IPictureVtbl       *lpvtbl1;
+    const IDispatchVtbl      *lpvtbl2;
+    const IPersistStreamVtbl *lpvtbl3;
+    const IConnectionPointContainerVtbl *lpvtbl4;
 
   /* Object reference count */
     DWORD ref;
@@ -156,10 +156,10 @@ typedef struct OLEPictureImpl {
 /*
  * Predeclare VTables.  They get initialized at the end.
  */
-static IPictureVtbl OLEPictureImpl_VTable;
-static IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
-static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
-static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
+static const IPictureVtbl OLEPictureImpl_VTable;
+static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable;
+static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable;
+static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable;
 
 /***********************************************************************
  * Implementation of the OLEPictureImpl class.
@@ -334,6 +334,9 @@ static void OLEPictureImpl_Destroy(OLEPictureImpl* Obj)
     case PICTYPE_ENHMETAFILE:
       DeleteEnhMetaFile(Obj->desc.u.emf.hemf);
       break;
+    case PICTYPE_NONE:
+      /* Nothing to do */
+      break;
     default:
       FIXME("Unsupported type %d - unable to delete\n", Obj->desc.picType);
       break;
@@ -485,6 +488,9 @@ static HRESULT WINAPI OLEPictureImpl_get_Handle(IPicture *iface,
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
   TRACE("(%p)->(%p)\n", This, phandle);
   switch(This->desc.picType) {
+  case PICTYPE_NONE:
+    *phandle = 0;
+    break;
   case PICTYPE_BITMAP:
     *phandle = (OLE_HANDLE)This->desc.u.bmp.hbitmap;
     break;
@@ -512,8 +518,10 @@ static HRESULT WINAPI OLEPictureImpl_get_hPal(IPicture *iface,
                                              OLE_HANDLE *phandle)
 {
   OLEPictureImpl *This = (OLEPictureImpl *)iface;
-  FIXME("(%p)->(%p): stub\n", This, phandle);
-  return E_NOTIMPL;
+  FIXME("(%p)->(%p): stub, return 0 palette.\n", This, phandle);
+
+  *phandle = 0;
+  return S_OK;
 }
 
 /************************************************************************
@@ -992,7 +1000,8 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) {
  */
 static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
   HRESULT      hr = E_FAIL;
-  ULONG                xread;
+  BOOL         headerisdata = FALSE;
+  ULONG                xread, toread;
   BYTE                 *xbuf;
   DWORD                header[2];
   WORD         magic;
@@ -1013,43 +1022,54 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
    */
   hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME);
   if (hr)
-    FIXME("Stat failed with hres %lx\n",hr);
+      FIXME("Stat failed with hres %lx\n",hr);
   hr=IStream_Read(pStm,header,8,&xread);
   if (hr || xread!=8) {
       FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread);
       return hr;
   }
-  if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
-      !memcmp(&(header[0]), "BM",       2) ||   /* BMP header */
-      !memcmp(&(header[0]), "\xff\xd8", 2) ||   /* JPEG header */
-      header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */
-    xread = 8;
-    xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,statstg.cbSize.QuadPart);
-    memcpy(xbuf,&header,8);
-    This->datalen = statstg.cbSize.QuadPart;
-    while (xread < This->datalen) {
-      ULONG nread;
-      hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
-      xread+=nread;
-      if (hr || !nread)
-       break;
-    }
-    if (xread != This->datalen)
-      FIXME("Could only read %ld of %d bytes in no-header case?\n",xread,This->datalen);
+
+  headerisdata = FALSE;
+  xread = 0;
+  if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
+      toread = header[1];
   } else {
-    xread = 0;
-    xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
-    This->datalen = header[1];
-    while (xread < header[1]) {
+      if (!memcmp(&(header[0]), "GIF8",     4) ||   /* GIF header */
+         !memcmp(&(header[0]), "BM",       2)  ||   /* BMP header */
+         !memcmp(&(header[0]), "\xff\xd8", 2)  ||   /* JPEG header */
+         (header[1] > statstg.cbSize.QuadPart) ||   /* invalid size */
+         (header[1]==0)
+      ) {/* Incorrect header, assume none. */
+          headerisdata = TRUE;
+          toread = statstg.cbSize.QuadPart-8;
+         xread = 8;
+      } else {
+         FIXME("Unknown stream header magic: %08lx\n", header[0]);
+          toread = header[1];
+      }
+  }
+
+  This->datalen = toread+(headerisdata?8:0);
+  xbuf = This->data = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, This->datalen);
+
+  if (headerisdata)
+      memcpy (xbuf, &header, 8);
+
+  while (xread < This->datalen) {
       ULONG nread;
-      hr = IStream_Read(pStm,xbuf+xread,header[1]-xread,&nread);
+      hr = IStream_Read(pStm,xbuf+xread,This->datalen-xread,&nread);
       xread+=nread;
       if (hr || !nread)
        break;
-    }
-    if (xread != header[1])
-      FIXME("Could only read %ld of %ld bytes?\n",xread,header[1]);
   }
+  if (xread != This->datalen)
+      FIXME("Could only read %ld of %d bytes out of stream?\n",xread,This->datalen);
+
+  if (This->datalen == 0) {    /* Marks the "NONE" picture */
+      This->desc.picType = PICTYPE_NONE;
+      return S_OK;
+  }
+
   magic = xbuf[0] + (xbuf[1]<<8);
   switch (magic) {
   case 0x4947: { /* GIF */
@@ -1917,7 +1937,7 @@ static HRESULT WINAPI OLEPictureImpl_Invoke(
 }
 
 
-static IPictureVtbl OLEPictureImpl_VTable =
+static const IPictureVtbl OLEPictureImpl_VTable =
 {
   OLEPictureImpl_QueryInterface,
   OLEPictureImpl_AddRef,
@@ -1938,7 +1958,7 @@ static IPictureVtbl OLEPictureImpl_VTable =
   OLEPictureImpl_get_Attributes
 };
 
-static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
+static const IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
 {
   OLEPictureImpl_IDispatch_QueryInterface,
   OLEPictureImpl_IDispatch_AddRef,
@@ -1949,7 +1969,7 @@ static IDispatchVtbl OLEPictureImpl_IDispatch_VTable =
   OLEPictureImpl_Invoke
 };
 
-static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
+static const IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
 {
   OLEPictureImpl_IPersistStream_QueryInterface,
   OLEPictureImpl_IPersistStream_AddRef,
@@ -1961,7 +1981,7 @@ static IPersistStreamVtbl OLEPictureImpl_IPersistStream_VTable =
   OLEPictureImpl_GetSizeMax
 };
 
-static IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
+static const IConnectionPointContainerVtbl OLEPictureImpl_IConnectionPointContainer_VTable =
 {
   OLEPictureImpl_IConnectionPointContainer_QueryInterface,
   OLEPictureImpl_IConnectionPointContainer_AddRef,
@@ -2189,7 +2209,7 @@ HRESULT WINAPI OleLoadPicturePath( LPOLESTR szURLorPath, LPUNKNOWN punkCaller,
 typedef struct
 {
     /* IUnknown fields */
-    IClassFactoryVtbl          *lpVtbl;
+    const IClassFactoryVtbl    *lpVtbl;
     DWORD                       ref;
 } IClassFactoryImpl;
 
@@ -2227,7 +2247,7 @@ static HRESULT WINAPI SPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
        return S_OK;
 }
 
-static IClassFactoryVtbl SPCF_Vtbl = {
+static const IClassFactoryVtbl SPCF_Vtbl = {
        SPCF_QueryInterface,
        SPCF_AddRef,
        SPCF_Release,
index d7851c1..2ed6667 100644 (file)
@@ -41,7 +41,7 @@ typedef struct {
 } fieldstr;
 
 typedef struct {
-    IRecordInfoVtbl *lpVtbl;
+    const IRecordInfoVtbl *lpVtbl;
     ULONG ref;
 
     GUID guid;
@@ -476,7 +476,7 @@ static HRESULT WINAPI IRecordInfoImpl_RecordDestroy(IRecordInfo *iface, PVOID pv
     return S_OK;
 }
 
-static IRecordInfoVtbl IRecordInfoImplVtbl = {
+static const IRecordInfoVtbl IRecordInfoImplVtbl = {
     IRecordInfoImpl_QueryInterface,
     IRecordInfoImpl_AddRef,
     IRecordInfoImpl_Release,
index 5f78bd4..7960ee6 100644 (file)
@@ -355,8 +355,8 @@ typedef struct _TMAsmProxy {
 #endif
 
 typedef struct _TMProxyImpl {
-    LPVOID                             *lpvtbl;
-    IRpcProxyBufferVtbl        *lpvtbl2;
+    LPVOID                             *lpvtbl;
+    const IRpcProxyBufferVtbl          *lpvtbl2;
     ULONG                              ref;
 
     TMAsmProxy                         *asmstubs;
@@ -443,7 +443,7 @@ TMProxyImpl_Disconnect(LPRPCPROXYBUFFER iface)
 }
 
 
-static IRpcProxyBufferVtbl tmproxyvtable = {
+static const IRpcProxyBufferVtbl tmproxyvtable = {
     TMProxyImpl_QueryInterface,
     TMProxyImpl_AddRef,
     TMProxyImpl_Release,
@@ -455,6 +455,10 @@ static IRpcProxyBufferVtbl tmproxyvtable = {
 int
 _argsize(DWORD vt) {
     switch (vt) {
+    case VT_R8:
+        return sizeof(double)/sizeof(DWORD);
+    case VT_CY:
+        return sizeof(CY)/sizeof(DWORD);
     case VT_DATE:
        return sizeof(DATE)/sizeof(DWORD);
     case VT_VARIANT:
@@ -607,6 +611,9 @@ serialize_param(
     }
     case VT_PTR: {
        DWORD cookie;
+       BOOL        derefhere;
+
+       derefhere = (tdesc->u.lptdesc->vt != VT_USERDEFINED);
 
        if (debugout) TRACE_(olerelay)("*");
        /* Write always, so the other side knows when it gets a NULL pointer.
@@ -620,7 +627,7 @@ serialize_param(
            return S_OK;
        }
        hres = serialize_param(tinfo,writeit,debugout,dealloc,tdesc->u.lptdesc,(DWORD*)*arg,buf);
-       if (dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)arg);
+       if (derefhere && dealloc) HeapFree(GetProcessHeap(),0,(LPVOID)*arg);
        return hres;
     }
     case VT_UNKNOWN:
@@ -686,6 +693,7 @@ serialize_param(
                    (DWORD*)(((LPBYTE)arg)+vdesc->u.oInst),
                    buf
                );
+                ITypeInfo_ReleaseVarDesc(tinfo2, vdesc);
                if (hres!=S_OK)
                    return hres;
                if (debugout && (i<(tattr->cVars-1)))
@@ -1432,7 +1440,7 @@ deserialize_DISPPARAM_ptr(
 /* Searches function, also in inherited interfaces */
 static HRESULT
 _get_funcdesc(
-    ITypeInfo *tinfo, int iMethod, FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
+    ITypeInfo *tinfo, int iMethod, ITypeInfo **tactual, FUNCDESC **fdesc, BSTR *iname, BSTR *fname)
 {
     int i = 0, j = 0;
     HRESULT hres;
@@ -1440,6 +1448,9 @@ _get_funcdesc(
     if (fname) *fname = NULL;
     if (iname) *iname = NULL;
 
+    *tactual = tinfo;
+    ITypeInfo_AddRef(*tactual);
+
     while (1) {
        hres = ITypeInfo_GetFuncDesc(tinfo, i, fdesc);
        if (hres) {
@@ -1464,7 +1475,7 @@ _get_funcdesc(
                    ERR("Did not find a typeinfo for reftype %ld?\n",href);
                    continue;
                }
-               hres = _get_funcdesc(tinfo2,iMethod,fdesc,iname,fname);
+               hres = _get_funcdesc(tinfo2,iMethod,tactual,fdesc,iname,fname);
                ITypeInfo_Release(tinfo2);
                if (!hres) return S_OK;
            }
@@ -1496,12 +1507,14 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     int                        nrofnames;
     int                        is_idispatch_getidsofnames = 0;
     DWORD              remoteresult = 0;
+    ITypeInfo          *tinfo;
 
     EnterCriticalSection(&tpinfo->crit);
 
-    hres = _get_funcdesc(tpinfo->tinfo,method,&fdesc,&iname,&fname);
+    hres = _get_funcdesc(tpinfo->tinfo,method,&tinfo,&fdesc,&iname,&fname);
     if (hres) {
        ERR("Did not find typeinfo/funcdesc entry for method %d!\n",method);
+        ITypeInfo_Release(tinfo);
         LeaveCriticalSection(&tpinfo->crit);
        return E_FAIL;
     }
@@ -1509,6 +1522,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
     if (!tpinfo->chanbuf)
     {
         WARN("Tried to use disconnected proxy\n");
+        ITypeInfo_Release(tinfo);
         LeaveCriticalSection(&tpinfo->crit);
         return RPC_E_DISCONNECTED;
     }
@@ -1537,6 +1551,8 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
        hres = serialize_IDispatch_GetIDsOfNames(TRUE,relaydeb,args,&buf);
        if (hres != S_OK) {
            FIXME("serialize of IDispatch::GetIDsOfNames failed!\n");
+            ITypeInfo_Release(tinfo);
+            LeaveCriticalSection(&tpinfo->crit);
            return hres;
        }
        goto afterserialize;
@@ -1553,7 +1569,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
 
     /* Need them for hack below */
     memset(names,0,sizeof(names));
-    if (ITypeInfo_GetNames(tpinfo->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
+    if (ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames))
        nrofnames = 0;
     if (nrofnames > sizeof(names)/sizeof(names[0]))
        ERR("Need more names!\n");
@@ -1582,7 +1598,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
            /* DISPPARAMS* needs special serializer */
            if (!lstrcmpW(names[i+1],pdispparamsW)) {
                hres = serialize_DISPPARAM_ptr(
-                   tpinfo->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                    relaydeb,
                    FALSE,
@@ -1594,7 +1610,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
            }
            if (!lstrcmpW(names[i+1],ppvObjectW)) {
                hres = serialize_LPVOID_ptr(
-                   tpinfo->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                    relaydeb,
                    FALSE,
@@ -1608,7 +1624,7 @@ xCall(LPVOID retptr, int method, TMProxyImpl *tpinfo /*, args */)
        }
        if (!isserialized)
            hres = serialize_param(
-               tpinfo->tinfo,
+               tinfo,
                elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                relaydeb,
                FALSE,
@@ -1695,7 +1711,7 @@ afterserialize:
            /* deserialize DISPPARAM */
            if (!lstrcmpW(names[i+1],pdispparamsW)) {
                hres = deserialize_DISPPARAM_ptr(
-                   tpinfo->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
                    relaydeb,
                    FALSE,
@@ -1711,7 +1727,7 @@ afterserialize:
            }
            if (!lstrcmpW(names[i+1],ppvObjectW)) {
                hres = deserialize_LPVOID_ptr(
-                   tpinfo->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
                    relaydeb,
                    FALSE,
@@ -1725,7 +1741,7 @@ afterserialize:
        }
        if (!isdeserialized)
            hres = deserialize_param(
-               tpinfo->tinfo,
+               tinfo,
                elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
                relaydeb,
                FALSE,
@@ -1750,6 +1766,7 @@ after_deserialize:
        return status;
 
     HeapFree(GetProcessHeap(),0,buf.base);
+    ITypeInfo_Release(tinfo);
     LeaveCriticalSection(&tpinfo->crit);
     return remoteresult;
 }
@@ -1842,7 +1859,9 @@ PSFacBuf_CreateProxy(
                int j;
                /* nrofargs without This */
                int nrofargs;
-               hres = _get_funcdesc(tinfo,i,&fdesc,NULL,NULL);
+                ITypeInfo *tinfo2;
+               hres = _get_funcdesc(tinfo,i,&tinfo2,&fdesc,NULL,NULL);
+                ITypeInfo_Release(tinfo2);
                if (hres) {
                    ERR("GetFuncDesc %lx should not fail here.\n",hres);
                    return hres;
@@ -1891,7 +1910,7 @@ PSFacBuf_CreateProxy(
 }
 
 typedef struct _TMStubImpl {
-    IRpcStubBufferVtbl *lpvtbl;
+    const IRpcStubBufferVtbl   *lpvtbl;
     ULONG                      ref;
 
     LPUNKNOWN                  pUnk;
@@ -1976,6 +1995,7 @@ TMStubImpl_Invoke(
     BSTR       names[10];
     BSTR       fname = NULL,iname = NULL;
     BOOL       is_idispatch_getidsofnames = 0;
+    ITypeInfo  *tinfo;
 
     memset(&buf,0,sizeof(buf));
     buf.size   = xmsg->cbBuffer;
@@ -1996,7 +2016,7 @@ TMStubImpl_Invoke(
        xmsg->cbBuffer  = buf.size;
        return hres;
     }
-    hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&fdesc,&iname,&fname);
+    hres = _get_funcdesc(This->tinfo,xmsg->iMethod,&tinfo,&fdesc,&iname,&fname);
     if (hres) {
        ERR("GetFuncDesc on method %ld failed with %lx\n",xmsg->iMethod,hres);
        return hres;
@@ -2010,7 +2030,7 @@ TMStubImpl_Invoke(
 
     /* Need them for hack below */
     memset(names,0,sizeof(names));
-    ITypeInfo_GetNames(This->tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
+    ITypeInfo_GetNames(tinfo,fdesc->memid,names,sizeof(names)/sizeof(names[0]),&nrofnames);
     if (nrofnames > sizeof(names)/sizeof(names[0])) {
        ERR("Need more names!\n");
     }
@@ -2047,7 +2067,7 @@ TMStubImpl_Invoke(
            /* deserialize DISPPARAM */
            if (!lstrcmpW(names[i+1],pdispparamsW)) {
                hres = deserialize_DISPPARAM_ptr(
-                   This->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                    FALSE,
                    TRUE,
@@ -2063,7 +2083,7 @@ TMStubImpl_Invoke(
            }
            if (!lstrcmpW(names[i+1],ppvObjectW)) {
                hres = deserialize_LPVOID_ptr(
-                   This->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                    FALSE,
                    TRUE,
@@ -2077,7 +2097,7 @@ TMStubImpl_Invoke(
        }
        if (!isdeserialized)
            hres = deserialize_param(
-               This->tinfo,
+               tinfo,
                elem->u.paramdesc.wParamFlags & PARAMFLAG_FIN,
                FALSE,
                TRUE,
@@ -2129,7 +2149,7 @@ afterdeserialize:
            /* DISPPARAMS* needs special serializer */
            if (!lstrcmpW(names[i+1],pdispparamsW)) {
                hres = serialize_DISPPARAM_ptr(
-                   This->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
                    FALSE,
                    TRUE,
@@ -2141,7 +2161,7 @@ afterdeserialize:
            }
            if (!lstrcmpW(names[i+1],ppvObjectW)) {
                hres = serialize_LPVOID_ptr(
-                   This->tinfo,
+                   tinfo,
                    elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
                    FALSE,
                    TRUE,
@@ -2155,7 +2175,7 @@ afterdeserialize:
        }
        if (!isserialized)
            hres = serialize_param(
-              This->tinfo,
+              tinfo,
               elem->u.paramdesc.wParamFlags & PARAMFLAG_FOUT,
               FALSE,
               TRUE,
@@ -2173,7 +2193,8 @@ afterserialize:
     hres = xbuf_add (&buf, (LPBYTE)&res, sizeof(DWORD));
     if (hres != S_OK)
        return hres;
-   
+
+    ITypeInfo_Release(tinfo);
     xmsg->cbBuffer     = buf.curoff;
     I_RpcGetBuffer((RPC_MESSAGE *)xmsg);
     memcpy(xmsg->Buffer, buf.base, buf.curoff);
@@ -2204,7 +2225,7 @@ TMStubImpl_DebugServerRelease(LPRPCSTUBBUFFER iface, LPVOID ppv) {
     return;
 }
 
-IRpcStubBufferVtbl tmstubvtbl = {
+static const IRpcStubBufferVtbl tmstubvtbl = {
     TMStubImpl_QueryInterface,
     TMStubImpl_AddRef,
     TMStubImpl_Release,
@@ -2247,7 +2268,7 @@ PSFacBuf_CreateStub(
     return hres;
 }
 
-static IPSFactoryBufferVtbl psfacbufvtbl = {
+static const IPSFactoryBufferVtbl psfacbufvtbl = {
     PSFacBuf_QueryInterface,
     PSFacBuf_AddRef,
     PSFacBuf_Release,
@@ -2256,7 +2277,7 @@ static IPSFactoryBufferVtbl psfacbufvtbl = {
 };
 
 /* This is the whole PSFactoryBuffer object, just the vtableptr */
-static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
+static const IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl;
 
 /***********************************************************************
  *           DllGetClassObject [OLE32.63]
index 5cba2bb..869f90b 100644 (file)
@@ -192,38 +192,55 @@ static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
     return buffer;
 }
 
+int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
+
 
 /****************************************************************************
  *             QueryPathOfRegTypeLib   [OLEAUT32.164]
+ *
+ * Gets the path to a registered type library.
+ *
+ * PARAMS
+ *  guid [I] referenced guid
+ *  wMaj [I] major version
+ *  wMin [I] minor version
+ *  lcid [I] locale id
+ *  path [O] path of typelib
+ *
  * RETURNS
- *     path of typelib
+ *  Success: S_OK.
+ *  Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
+ *  or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
+ *  opened.
  */
-HRESULT WINAPI
-QueryPathOfRegTypeLib(
-       REFGUID guid,   /* [in] referenced guid */
-       WORD wMaj,      /* [in] major version */
-       WORD wMin,      /* [in] minor version */
-       LCID lcid,      /* [in] locale id */
-       LPBSTR path )   /* [out] path of typelib */
+HRESULT WINAPI QueryPathOfRegTypeLib(
+       REFGUID guid,
+       WORD wMaj,
+       WORD wMin,
+       LCID lcid,
+       LPBSTR path )
 {
-    HRESULT hr = E_FAIL;
+    HRESULT hr = TYPE_E_LIBNOTREGISTERED;
     LCID myLCID = lcid;
     HKEY hkey;
     WCHAR buffer[60];
     WCHAR Path[MAX_PATH];
+    LONG res;
 
-    if ( !HIWORD(guid) )
-    {
-        FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path);
-        return E_FAIL;
-    }
+    TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
 
     get_typelib_key( guid, wMaj, wMin, buffer );
 
-    if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS)
+    res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
+    if (res == ERROR_FILE_NOT_FOUND)
     {
         TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
-        return E_FAIL;
+        return TYPE_E_LIBNOTREGISTERED;
+    }
+    else if (res != ERROR_SUCCESS)
+    {
+        TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
+        return TYPE_E_REGISTRYACCESS;
     }
 
     while (hr != S_OK)
@@ -258,6 +275,7 @@ QueryPathOfRegTypeLib(
         }
     }
     RegCloseKey( hkey );
+    TRACE_(typelib)("-- 0x%08lx\n", hr);
     return hr;
 }
 
@@ -274,22 +292,24 @@ HRESULT WINAPI CreateTypeLib(
     FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
     return E_FAIL;
 }
+
 /******************************************************************************
  *             LoadTypeLib     [OLEAUT32.161]
- * Loads and registers a type library
- * NOTES
- *    Docs: OLECHAR FAR* szFile
- *    Docs: iTypeLib FAR* FAR* pptLib
+ *
+ * Loads a type library
+ *
+ * PARAMS
+ *  szFile [I] Name of file to load from.
+ *  pptLib [O] Pointer that receives ITypeLib object on success.
  *
  * RETURNS
  *    Success: S_OK
  *    Failure: Status
+ *
+ * SEE
+ *  LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
  */
-int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
-
-HRESULT WINAPI LoadTypeLib(
-    const OLECHAR *szFile,/* [in] Name of file to load from */
-    ITypeLib * *pptLib)   /* [out] Pointer to pointer to loaded type library */
+HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
 {
     TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
     return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
@@ -297,6 +317,7 @@ HRESULT WINAPI LoadTypeLib(
 
 /******************************************************************************
  *             LoadTypeLibEx   [OLEAUT32.183]
+ *
  * Loads and optionally registers a type library
  *
  * RETURNS
@@ -368,13 +389,27 @@ HRESULT WINAPI LoadTypeLibEx(
 
 /******************************************************************************
  *             LoadRegTypeLib  [OLEAUT32.162]
+ *
+ * Loads a registered type library.
+ *
+ * PARAMS
+ *  rguid     [I] GUID of the registered type library.
+ *  wVerMajor [I] major version.
+ *  wVerMinor [I] minor version.
+ *  lcid      [I] locale ID.
+ *  ppTLib    [O] pointer that receives an ITypeLib object on success.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
+ *  LoadTypeLib.
  */
 HRESULT WINAPI LoadRegTypeLib(
-       REFGUID rguid,          /* [in] referenced guid */
-       WORD wVerMajor,         /* [in] major version */
-       WORD wVerMinor,         /* [in] minor version */
-       LCID lcid,              /* [in] locale id */
-       ITypeLib **ppTLib)      /* [out] path of typelib */
+       REFGUID rguid,
+       WORD wVerMajor,
+       WORD wVerMinor,
+       LCID lcid,
+       ITypeLib **ppTLib)
 {
     BSTR bstr=NULL;
     HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
@@ -826,8 +861,8 @@ typedef struct tagTLBImpLib
 /* internal ITypeLib data */
 typedef struct tagITypeLibImpl
 {
-    ITypeLib2Vtbl *lpVtbl;
-    ITypeCompVtbl *lpVtblTypeComp;
+    const ITypeLib2Vtbl *lpVtbl;
+    const ITypeCompVtbl *lpVtblTypeComp;
     ULONG ref;
     TLIBATTR LibAttr;            /* guid,lcid,syskind,version,flags */
 
@@ -854,8 +889,8 @@ typedef struct tagITypeLibImpl
     INT index;
 } ITypeLibImpl;
 
-static struct ITypeLib2Vtbl tlbvt;
-static struct ITypeCompVtbl tlbtcvt;
+static const ITypeLib2Vtbl tlbvt;
+static const ITypeCompVtbl tlbtcvt;
 
 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
@@ -938,8 +973,8 @@ typedef struct tagTLBImplType
 /* internal TypeInfo data */
 typedef struct tagITypeInfoImpl
 {
-    ITypeInfo2Vtbl *lpVtbl;
-    ITypeCompVtbl  *lpVtblTypeComp;
+    const ITypeInfo2Vtbl *lpVtbl;
+    const ITypeCompVtbl  *lpVtblTypeComp;
     ULONG ref;
     TYPEATTR TypeAttr ;         /* _lots_ of type information. */
     ITypeLibImpl * pTypeLib;        /* back pointer to typelib */
@@ -967,8 +1002,8 @@ typedef struct tagITypeInfoImpl
     struct tagITypeInfoImpl * next;
 } ITypeInfoImpl;
 
-static struct ITypeInfo2Vtbl tinfvt;
-static struct ITypeCompVtbl  tcompvt;
+static const ITypeInfo2Vtbl tinfvt;
+static const ITypeCompVtbl  tcompvt;
 
 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
 
@@ -1293,7 +1328,7 @@ static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
     {{0},30},{{0},31}
 };
 
-static void TLB_abort()
+static void TLB_abort(void)
 {
     DebugBreak();
 }
@@ -3743,7 +3778,7 @@ static HRESULT WINAPI ITypeLib2_fnIsName(
     TLBFuncDesc *pFInfo;
     TLBVarDesc *pVInfo;
     int i;
-    UINT nNameBufLen = SysStringLen(szNameBuf);
+    UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
 
     TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
          pfName);
@@ -3789,16 +3824,16 @@ static HRESULT WINAPI ITypeLib2_fnFindName(
     TLBFuncDesc *pFInfo;
     TLBVarDesc *pVInfo;
     int i,j = 0;
-
-    UINT nNameBufLen = SysStringLen(szNameBuf);
+    UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
 
     for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
         if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
         for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
             if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
-            for(i=0;i<pFInfo->funcdesc.cParams;i++)
+            for(i=0;i<pFInfo->funcdesc.cParams;i++) {
                 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
                     goto ITypeLib2_fnFindName_exit;
+           }
         }
         for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
             if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
@@ -3973,7 +4008,7 @@ static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
     return S_OK;
 }
 
-static ITypeLib2Vtbl tlbvt = {
+static const ITypeLib2Vtbl tlbvt = {
     ITypeLib2_fnQueryInterface,
     ITypeLib2_fnAddRef,
     ITypeLib2_fnRelease,
@@ -4040,7 +4075,7 @@ static HRESULT WINAPI ITypeLibComp_fnBindType(
     return E_NOTIMPL;
 }
 
-static ITypeCompVtbl tlbtcvt =
+static const ITypeCompVtbl tlbtcvt =
 {
 
     ITypeLibComp_fnQueryInterface,
@@ -4748,27 +4783,36 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
             memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
 
            hres = S_OK;
-           numargs = 1; numargs2 = 0;
+           numargs = 1; /* sizeof(thisptr) */
+           numargs2 = 0;
            for (i = 0; i < func_desc->cParams; i++) {
-               if (i<pDispParams->cArgs)
-                   numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
-               else {
-                   numargs     += 1; /* sizeof(lpvoid) */
-                   numargs2    += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
+                TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
+
+               numargs += _argsize(tdesc->vt);
+               if (i>=pDispParams->cArgs) { /* arguments to return */
+                   if (tdesc->vt == VT_PTR) {
+                       numargs2        += _argsize(tdesc->u.lptdesc->vt);
+                   } else {
+                       FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
+                       numargs2        += _argsize(tdesc->vt);
+                   }
                }
            }
 
            args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
-           args2 = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
+           args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
 
            args[0] = (DWORD)pIUnk;
            argspos = 1; args2pos = 0;
            for (i = 0; i < func_desc->cParams; i++) {
-               int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
+               ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
+               TYPEDESC *tdesc = &(elemdesc->tdesc);
+               USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
+               int arglen = _argsize(tdesc->vt);
+
                if (i<pDispParams->cArgs) {
                     VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
-                    TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
-                    USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
+
                     if (paramFlags & PARAMFLAG_FOPT) {
                         if(i < func_desc->cParams - func_desc->cParamsOpt)
                             ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
@@ -4787,13 +4831,14 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
                     if (FAILED(hres)) goto func_fail;
                     argspos += arglen;
-                } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
+                } else if (paramFlags & PARAMFLAG_FOPT) {
                     VARIANT *arg = &rgvarg[i];
-                    TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
-                    if(i < func_desc->cParams - func_desc->cParamsOpt)
+
+                    if (i < func_desc->cParams - func_desc->cParamsOpt)
                         ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
-                    if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
+                    if (paramFlags & PARAMFLAG_FHASDEFAULT)
                         FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
+
                     V_VT(arg) = VT_ERROR;
                     V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
                     arglen = _argsize(VT_ERROR);
@@ -4801,10 +4846,12 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
                     if (FAILED(hres)) goto func_fail;
                     argspos += arglen;
                } else {
-                   TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
-                   if (tdesc->vt != VT_PTR)
+                   if (tdesc->vt == VT_PTR)
+                       arglen = _argsize(tdesc->u.lptdesc->vt);
+                   else
                        FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
-                   /*FIXME: give pointers for the rest, so propertyget works*/
+
+                   /* Supply pointers for the rest, so propertyget works*/
                    args[argspos] = (DWORD)&args2[args2pos];
 
                    /* If pointer to variant, pass reference it. */
@@ -4829,20 +4876,24 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
            if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
                args2pos = 0;
                for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
-                   int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
-                   TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
-                    TYPEDESC i4_tdesc;
-                    i4_tdesc.vt = VT_I4;
+                   ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i+pDispParams->cArgs]);
+                   TYPEDESC *tdesc = &(elemdesc->tdesc);
+                   int arglen = _argsize(tdesc->vt);
+                   TYPEDESC i4_tdesc;
+                   i4_tdesc.vt = VT_I4;
 
                    /* If we are a pointer to a variant, we are done already */
                    if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
                        continue;
 
+                   if (tdesc->vt == VT_PTR) {
+                       tdesc = tdesc->u.lptdesc;
+                       arglen = _argsize(tdesc->vt);
+                   }
+
                    VariantInit(pVarResult);
                    memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));
 
-                   if (tdesc->vt == VT_PTR)
-                       tdesc = tdesc->u.lptdesc;
                    if (tdesc->vt == VT_USERDEFINED) {
                        ITypeInfo       *tinfo2;
                        TYPEATTR        *tattr;
@@ -5062,7 +5113,6 @@ static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
     ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
     HRESULT result = E_FAIL;
 
-
     if (hRefType == -1 &&
        (((ITypeInfoImpl*) This)->TypeAttr.typekind   == TKIND_DISPATCH) &&
        (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags &  TYPEFLAG_FDUAL))
@@ -5733,7 +5783,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
     return TYPE_E_ELEMENTNOTFOUND;
 }
 
-static ITypeInfo2Vtbl tinfvt =
+static const ITypeInfo2Vtbl tinfvt =
 {
 
     ITypeInfo_fnQueryInterface,
@@ -5956,7 +6006,7 @@ static HRESULT WINAPI ITypeComp_fnBindType(
     return S_OK;
 }
 
-static ITypeCompVtbl tcompvt =
+static const ITypeCompVtbl tcompvt =
 {
 
     ITypeComp_fnQueryInterface,
index e519aa7..6f7b8cd 100644 (file)
@@ -161,9 +161,12 @@ typedef struct tagMSFT_TypeInfoBase {
 
 /* layout of an entry with information on imported types */
 typedef struct tagMSFT_ImpInfo {
-    INT     res0;           /* unknown */
-    INT     oImpFile;       /* offset inthe Import File table */
-    INT     oGuid;          /* offset in Guid table */
+    INT     res0;           /* bits 0 - 15:  count */
+                            /* bit  16:      if set oGuid is an offset to Guid */
+                            /*               if clear oGuid is a typeinfo index in the specified typelib */
+                            /* bits 24 - 31: TKIND of reference */
+    INT     oImpFile;       /* offset in the Import File table */
+    INT     oGuid;          /* offset in Guid table or typeinfo index (see bit 16 of res0) */
     } MSFT_ImpInfo;
 
 /* function description data */
index cf34267..14d9112 100644 (file)
@@ -145,8 +145,8 @@ typedef struct tagMSFT_ImpFile {
 
 typedef struct tagICreateTypeLib2Impl
 {
-    ICreateTypeLib2Vtbl *lpVtbl;
-    ITypeLib2Vtbl       *lpVtblTypeLib2;
+    const ICreateTypeLib2Vtbl *lpVtbl;
+    const ITypeLib2Vtbl       *lpVtblTypeLib2;
 
     ULONG ref;
 
@@ -171,8 +171,8 @@ typedef struct tagICreateTypeLib2Impl
 
 typedef struct tagICreateTypeInfo2Impl
 {
-    ICreateTypeInfo2Vtbl *lpVtbl;
-    ITypeInfo2Vtbl       *lpVtblTypeInfo2;
+    const ICreateTypeInfo2Vtbl *lpVtbl;
+    const ITypeInfo2Vtbl       *lpVtblTypeInfo2;
 
     ULONG ref;
 
@@ -2803,7 +2803,7 @@ static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
 
 /*================== ICreateTypeInfo2 & ITypeInfo2 VTABLEs And Creation ===================================*/
 
-static ICreateTypeInfo2Vtbl ctypeinfo2vt =
+static const ICreateTypeInfo2Vtbl ctypeinfo2vt =
 {
 
     ICreateTypeInfo2_fnQueryInterface,
@@ -2851,7 +2851,7 @@ static ICreateTypeInfo2Vtbl ctypeinfo2vt =
     ICreateTypeInfo2_fnSetName
 };
 
-static ITypeInfo2Vtbl typeinfo2vt =
+static const ITypeInfo2Vtbl typeinfo2vt =
 {
 
     ITypeInfo2_fnQueryInterface,
@@ -3761,7 +3761,7 @@ static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
 
 /*================== ICreateTypeLib2 & ITypeLib2 VTABLEs And Creation ===================================*/
 
-static ICreateTypeLib2Vtbl ctypelib2vt =
+static const ICreateTypeLib2Vtbl ctypelib2vt =
 {
 
     ICreateTypeLib2_fnQueryInterface,
@@ -3785,7 +3785,7 @@ static ICreateTypeLib2Vtbl ctypelib2vt =
     ICreateTypeLib2_fnSetHelpStringDll
 };
 
-static ITypeLib2Vtbl typelib2vt =
+static const ITypeLib2Vtbl typelib2vt =
 {
 
     ITypeLib2_fnQueryInterface,
index eaddecc..8c5f1a8 100644 (file)
@@ -210,7 +210,10 @@ static unsigned wire_extra(unsigned long *pFlags, VARIANT *pvar)
     /* find the buffer size of the marshalled dispatch interface */
     hr = CoGetMarshalSizeMax(&size, &IID_IDispatch, (IUnknown*)V_DISPATCH(pvar), LOWORD(*pFlags), NULL, MSHLFLAGS_NORMAL);
     if (FAILED(hr)) {
-      ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%lx\n", hr);
+      if (!V_DISPATCH(pvar))
+        WARN("NULL dispatch pointer\n");
+      else
+        ERR("Dispatch variant buffer size calculation failed, HRESULT=0x%lx\n", hr);
       return 0;
     }
     size += sizeof(ULONG); /* we have to store the buffersize in the stream */
@@ -515,6 +518,7 @@ HRESULT CALLBACK IDispatch_Invoke_Proxy(
   UINT* rgVarRefIdx = NULL;
   VARIANTARG* rgVarRef = NULL;
   UINT u, cVarRef;
+  UINT uArgErr;
 
   TRACE("(%p)->(%ld,%s,%lx,%x,%p,%p,%p,%p)\n", This,
         dispIdMember, debugstr_guid(riid),
@@ -523,6 +527,7 @@ HRESULT CALLBACK IDispatch_Invoke_Proxy(
 
   /* [out] args can't be null, use dummy vars if needed */
   if (!pVarResult) pVarResult = &VarResult;
+  if (!puArgErr) puArgErr = &uArgErr;
 
   /* count by-ref args */
   for (cVarRef=0,u=0; u<pDispParams->cArgs; u++) {
@@ -590,49 +595,61 @@ HRESULT __RPC_STUB IDispatch_Invoke_Stub(
     UINT* rgVarRefIdx,
     VARIANTARG* rgVarRef)
 {
-  HRESULT hr;
+  HRESULT hr = S_OK;
   VARIANTARG *rgvarg, *arg;
   UINT u;
 
+  /* initialize out parameters, so that they can be marshalled
+   * in case the real Invoke doesn't initialize them */
+  VariantInit(pVarResult);
+  memset(pExcepInfo, 0, sizeof(*pExcepInfo));
+  *pArgErr = 0;
+
   /* let the real Invoke operate on a copy of the in parameters,
    * so we don't risk losing pointers to allocated memory */
   rgvarg = pDispParams->rgvarg;
   arg = CoTaskMemAlloc(sizeof(VARIANTARG)*pDispParams->cArgs);
-  for (u=0; u<pDispParams->cArgs; u++) {
+  if (!arg) return E_OUTOFMEMORY;
+
+  /* init all args so we can call VariantClear on all the args if the copy
+   * below fails */
+  for (u = 0; u < pDispParams->cArgs; u++)
     VariantInit(&arg[u]);
-    VariantCopy(&arg[u], &rgvarg[u]);
+
+  for (u = 0; u < pDispParams->cArgs; u++) {
+    hr = VariantCopy(&arg[u], &rgvarg[u]);
+    if (FAILED(hr))
+        break;
   }
-  pDispParams->rgvarg = arg;
 
-  /* initialize out parameters, so that they can be marshalled
-   * in case the real Invoke doesn't initialize them */
-  VariantInit(pVarResult);
-  memset(pExcepInfo, 0, sizeof(*pExcepInfo));
-  *pArgErr = 0;
+  if (SUCCEEDED(hr)) {
+    pDispParams->rgvarg = arg;
 
-  hr = IDispatch_Invoke(This,
-                       dispIdMember,
-                       riid,
-                       lcid,
-                       dwFlags,
-                       pDispParams,
-                       pVarResult,
-                       pExcepInfo,
-                       pArgErr);
-
-  /* copy ref args to out list */
-  for (u=0; u<cVarRef; u++) {
-    unsigned i = rgVarRefIdx[u];
-    VariantInit(&rgVarRef[u]);
-    VariantCopy(&rgVarRef[u], &arg[i]);
-    /* clear original if equal, to avoid double-free */
-    if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
-      VariantClear(&rgvarg[i]);
+    hr = IDispatch_Invoke(This,
+                         dispIdMember,
+                         riid,
+                         lcid,
+                         dwFlags,
+                         pDispParams,
+                         pVarResult,
+                         pExcepInfo,
+                         pArgErr);
+
+    /* copy ref args to out list */
+    for (u=0; u<cVarRef; u++) {
+      unsigned i = rgVarRefIdx[u];
+      VariantInit(&rgVarRef[u]);
+      VariantCopy(&rgVarRef[u], &arg[i]);
+      /* clear original if equal, to avoid double-free */
+      if (V_BYREF(&rgVarRef[u]) == V_BYREF(&rgvarg[i]))
+        VariantClear(&rgvarg[i]);
+    }
   }
+
   /* clear the duplicate argument list */
-  for (u=0; u<pDispParams->cArgs; u++) {
+  for (u=0; u<pDispParams->cArgs; u++)
     VariantClear(&arg[u]);
-  }
+
   pDispParams->rgvarg = rgvarg;
   CoTaskMemFree(arg);
 
index 32770f8..9e4db05 100644 (file)
@@ -275,8 +275,8 @@ typedef struct tagFMT_DATE_HEADER
 #define FMT_NUM_COPY_SKIP   0x35 /* Copy 1 digit or skip if no digit */
 #define FMT_NUM_DECIMAL     0x36 /* Decimal separator */
 #define FMT_NUM_EXP_POS_U   0x37 /* Scientific notation, uppercase, + sign */
-#define FMT_NUM_EXP_NEG_U   0x38 /* Scientific notation, lowercase, - sign */
-#define FMT_NUM_EXP_POS_L   0x39 /* Scientific notation, uppercase, + sign */
+#define FMT_NUM_EXP_NEG_U   0x38 /* Scientific notation, uppercase, - sign */
+#define FMT_NUM_EXP_POS_L   0x39 /* Scientific notation, lowercase, + sign */
 #define FMT_NUM_EXP_NEG_L   0x3A /* Scientific notation, lowercase, - sign */
 #define FMT_NUM_CURRENCY    0x3B /* Currency symbol */
 #define FMT_NUM_TRUE_FALSE  0x3D /* Convert to "True" or "False" */
@@ -708,7 +708,35 @@ HRESULT WINAPI VarTokenizeFormatString(LPOLESTR lpszFormat, LPBYTE rgbTok,
       pFormat++;
       TRACE("decimal sep\n");
     }
-    /* FIXME: E+ E- e+ e- => Exponent */
+    else if ((*pFormat == 'e' || *pFormat == 'E') && (pFormat[1] == '-' ||
+              pFormat[1] == '+') && header->type == FMT_TYPE_NUMBER)
+    {
+      /* Number formats: Exponent specifier
+       * Other formats: Literal
+       */
+      num_header->flags |= FMT_FLAG_EXPONENT;
+      NEED_SPACE(2 * sizeof(BYTE));
+      if (*pFormat == 'e') {
+        if (pFormat[1] == '+')
+          *pOut = FMT_NUM_EXP_POS_L;
+        else
+          *pOut = FMT_NUM_EXP_NEG_L;
+      } else {
+        if (pFormat[1] == '+')
+          *pOut = FMT_NUM_EXP_POS_U;
+        else
+          *pOut = FMT_NUM_EXP_NEG_U;
+      }
+      pFormat += 2;
+      *++pOut = 0x0;
+      while (*pFormat == '0')
+      {
+        *pOut = *pOut + 1;
+        pFormat++;
+      }
+      pOut++;
+      TRACE("exponent\n");
+    }
     /* FIXME: %% => Divide by 1000 */
     else if (*pFormat == ',' && header->type == FMT_TYPE_NUMBER)
     {
@@ -1155,15 +1183,16 @@ HRESULT WINAPI VarTokenizeFormatString(LPOLESTR lpszFormat, LPBYTE rgbTok,
 
 /* Number formatting state flags */
 #define NUM_WROTE_DEC  0x01 /* Written the decimal separator */
+#define NUM_WRITE_ON   0x02 /* Started to write the number */
 
 /* Format a variant using a number format */
 static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
                                     LPBYTE rgbTok, ULONG dwFlags,
                                     BSTR *pbstrOut, LCID lcid)
 {
-  BYTE rgbDig[256];
+  BYTE rgbDig[256], *prgbDig;
   NUMPARSE np;
-  int wholeNumberDigits, fractionalDigits, divisor10 = 0, multiplier10 = 0;
+  int have_int, need_int = 0, have_frac, need_frac, exponent = 0, pad = 0;
   WCHAR buff[256], *pBuff = buff;
   VARIANT vString, vBool;
   DWORD dwState = 0;
@@ -1181,7 +1210,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
 
   if (V_TYPE(pVarIn) == VT_EMPTY || V_TYPE(pVarIn) == VT_NULL)
   {
-    wholeNumberDigits = fractionalDigits = 0;
+    have_int = have_frac = 0;
     numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNull(header));
     V_BOOL(&vBool) = VARIANT_FALSE;
   }
@@ -1198,36 +1227,9 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
     if (FAILED(hRes))
       return hRes;
 
-    if (np.nPwr10 < 0)
-    {
-      if (-np.nPwr10 >= np.cDig)
-      {
-        /* A real number < +/- 1.0 e.g. 0.1024 or 0.01024 */
-        wholeNumberDigits = 0;
-        fractionalDigits = np.cDig;
-        divisor10 = -np.nPwr10;
-      }
-      else
-      {
-        /* An exactly represented real number e.g. 1.024 */
-        wholeNumberDigits = np.cDig + np.nPwr10;
-        fractionalDigits = np.cDig - wholeNumberDigits;
-        divisor10 = np.cDig - wholeNumberDigits;
-      }
-    }
-    else if (np.nPwr10 == 0)
-    {
-      /* An exactly represented whole number e.g. 1024 */
-      wholeNumberDigits = np.cDig;
-      fractionalDigits = 0;
-    }
-    else /* np.nPwr10 > 0 */
-    {
-      /* A whole number followed by nPwr10 0's e.g. 102400 */
-      wholeNumberDigits = np.cDig;
-      fractionalDigits = 0;
-      multiplier10 = np.nPwr10;
-    }
+    have_int = np.cDig;
+    have_frac = 0;
+    exponent = np.nPwr10;
 
     /* Figure out which format to use */
     if (np.dwOutFlags & NUMPRS_NEG)
@@ -1235,8 +1237,7 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
       numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetNegative(header));
       V_BOOL(&vBool) = VARIANT_TRUE;
     }
-    else if (wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 &&
-              !divisor10 && rgbDig[0] == 0)
+    else if (have_int == 1 && !exponent && rgbDig[0] == 0)
     {
       numHeader = (FMT_NUMBER_HEADER*)(rgbTok + FmtGetZero(header));
       V_BOOL(&vBool) = VARIANT_FALSE;
@@ -1251,33 +1252,72 @@ static HRESULT VARIANT_FormatNumber(LPVARIANT pVarIn, LPOLESTR lpszFormat,
           numHeader->flags, numHeader->multiplier, numHeader->divisor,
           numHeader->whole, numHeader->fractional);
 
+    need_int = numHeader->whole;
+    need_frac = numHeader->fractional;
+
     if (numHeader->flags & FMT_FLAG_PERCENT &&
-        !(wholeNumberDigits == 1 && !fractionalDigits && !multiplier10 &&
-        !divisor10 && rgbDig[0] == 0))
+        !(have_int == 1 && !exponent && rgbDig[0] == 0))
+      exponent += 2;
+
+    if (numHeader->flags & FMT_FLAG_EXPONENT)
     {
-       /* *100 for %'s. Try to 'steal' fractional digits if we can */
-      TRACE("Fraction - multiply by 100\n");
-      if (!fractionalDigits)
-         multiplier10 += 2;
+      /* Exponent format: length of the integral number part is fixed and
+         specified by the format. */
+      pad = need_int - have_int;
+      if (pad >= 0)
+        exponent -= pad;
       else
       {
-        fractionalDigits--;
-        wholeNumberDigits++;
-        if (!fractionalDigits)
-          multiplier10++;
-        else
+        have_int = need_int;
+        have_frac -= pad;
+        exponent -= pad;
+        pad = 0;
+      }
+    }
+    else
+    {
+      /* Convert the exponent */
+      pad = max(exponent, -have_int);
+      exponent -= pad;
+      if (pad < 0)
+      {
+        have_int += pad;
+        have_frac = -pad;
+        pad = 0;
+      }
+    }
+
+    /* Rounding the number */
+    if (have_frac > need_frac)
+    {
+      prgbDig = &rgbDig[have_int + need_frac];
+      have_frac = need_frac;
+      if (*prgbDig >= 5)
+      {
+        while (prgbDig-- > rgbDig && *prgbDig == 9)
+          *prgbDig = 0;
+        if (prgbDig < rgbDig)
         {
-          fractionalDigits--;
-          wholeNumberDigits++;
+          /* We reached the first digit and that was also a 9 */
+          rgbDig[0] = 1;
+          if (numHeader->flags & FMT_FLAG_EXPONENT)
+            exponent++;
+          else
+          {
+            rgbDig[have_int + need_frac] = 0;
+            have_int++;
+          }
         }
+        else
+          (*prgbDig)++;
       }
     }
-    TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", np.cDig,
-          np.nPwr10, wholeNumberDigits, fractionalDigits);
-    TRACE("mult %d; div %d\n", multiplier10, divisor10);
-
+    TRACE("have_int=%d,need_int=%d,have_frac=%d,need_frac=%d,pad=%d,exp=%d\n",
+          have_int, need_int, have_frac, need_frac, pad, exponent);
   }
+
   pToken = (const BYTE*)numHeader + sizeof(FMT_NUMBER_HEADER);
+  prgbDig = rgbDig;
 
   while (SUCCEEDED(hRes) && *pToken != FMT_GEN_END)
   {
@@ -1360,88 +1400,88 @@ VARIANT_FormatNumber_Bool:
         *pBuff++ = 'e';
       else
         *pBuff++ = 'E';
-      if (divisor10)
+      if (exponent < 0)
       {
         *pBuff++ = '-';
-        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], divisor10);
+        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], -exponent);
       }
       else
       {
         if (*pToken == FMT_NUM_EXP_POS_L || *pToken == FMT_NUM_EXP_POS_U)
           *pBuff++ = '+';
-        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], multiplier10);
+        sprintfW(pBuff, szPercentZeroStar_d, pToken[1], exponent);
       }
       while (*pBuff)
         pBuff++;
       pToken++;
       break;
 
-    case FMT_NUM_COPY_SKIP:
-      if (dwState & NUM_WROTE_DEC)
-      {
-        int count;
+    case FMT_NUM_COPY_ZERO:
+      dwState |= NUM_WRITE_ON;
+      /* Fall through */
 
-        TRACE("write %d fractional digits or skip\n", pToken[1]);
+    case FMT_NUM_COPY_SKIP:
+      TRACE("write %d %sdigits or %s\n", pToken[1],
+            dwState & NUM_WROTE_DEC ? "fractional " : "",
+            *pToken == FMT_NUM_COPY_ZERO ? "0" : "skip");
 
-        for (count = 0; count < fractionalDigits; count++)
-          pBuff[count] = '0' + rgbDig[wholeNumberDigits + count];
-        pBuff += fractionalDigits;
-      }
-      else
+      if (dwState & NUM_WROTE_DEC)
       {
-        int count;
-
-        TRACE("write %d digits or skip\n", pToken[1]);
+        int count, i;
 
-        if (wholeNumberDigits > 1 || rgbDig[0] > 0)
+        if (!(numHeader->flags & FMT_FLAG_EXPONENT) && exponent < 0)
         {
-          TRACE("write %d whole number digits\n", wholeNumberDigits);
-          for (count = 0; count < wholeNumberDigits; count++)
-            *pBuff++ = '0' + rgbDig[count];
-          TRACE("write %d whole trailing 0's\n", multiplier10);
-          for (count = 0; count < multiplier10; count++)
-            *pBuff++ = '0'; /* Write trailing zeros for multiplied values */
+          /* Pad with 0 before writing the fractional digits */
+          pad = max(exponent, -pToken[1]);
+          exponent -= pad;
+          count = min(have_frac, pToken[1] + pad);
+          for (i = 0; i > pad; i--)
+            *pBuff++ = '0';
         }
-      }
-      pToken++;
-      break;
-
-    case FMT_NUM_COPY_ZERO:
-      if (dwState & NUM_WROTE_DEC)
-      {
-        int count;
-
-        TRACE("write %d fractional digits or 0's\n", pToken[1]);
+        else
+          count = min(have_frac, pToken[1]);
 
-        for (count = 0; count < fractionalDigits; count++)
-          pBuff[count] = '0' + rgbDig[wholeNumberDigits + count];
-        pBuff += fractionalDigits;
-        if (pToken[1] > fractionalDigits)
+        pad += pToken[1] - count;
+        have_frac -= count;
+        while (count--)
+          *pBuff++ = '0' + *prgbDig++;
+        if (*pToken == FMT_NUM_COPY_ZERO)
         {
-          count = pToken[1] - fractionalDigits;
-          while (count--)
-            *pBuff++ = '0'; /* Write trailing zeros for missing digits */
+          for (; pad > 0; pad--)
+            *pBuff++ = '0'; /* Write zeros for missing trailing digits */
         }
       }
       else
       {
-        int count;
-
-        TRACE("write %d digits or 0's\n", pToken[1]);
+        int count, count_max;
 
-        if (pToken[1] > (wholeNumberDigits + multiplier10))
+        need_int -= pToken[1];
+        count_max = have_int + pad - need_int;
+        if (count_max < 0)
+            count_max = 0;
+        if (dwState & NUM_WRITE_ON)
         {
-          count = pToken[1] - (wholeNumberDigits + multiplier10);
+          count = pToken[1] - count_max;
           TRACE("write %d leading zeros\n", count);
-          while(count--)
-            *pBuff++ = '0'; /* Write leading zeros for missing digits */
+          while (count-- > 0)
+            *pBuff++ = '0';
         }
-        TRACE("write %d whole number digits\n", wholeNumberDigits);
-        for (count = 0; count < wholeNumberDigits; count++)
-          *pBuff++ = '0' + rgbDig[count];
-        TRACE("write %d whole trailing 0's\n", multiplier10);
-        for (count = 0; count < multiplier10; count++)
-          *pBuff++ = '0'; /* Write trailing zeros for multiplied values */
+        if (*pToken == FMT_NUM_COPY_ZERO || have_int > 1 || *prgbDig > 0)
+        {
+          dwState |= NUM_WRITE_ON;
+          count = min(count_max, have_int);
+          count_max -= count;
+          have_int -= count;
+          TRACE("write %d whole number digits\n", count);
+          while (count--)
+            *pBuff++ = '0' + *prgbDig++;
+        }
+        count = min(count_max, pad);
+        count_max -= count;
+        pad -= count;
+        TRACE("write %d whole trailing 0's\n", count);
+        while (count--)
+          *pBuff++ = '0';
       }
       pToken++;
       break;
@@ -2405,3 +2445,57 @@ HRESULT WINAPI VarFormatCurrency(LPVARIANT pVarIn, INT nDigits, INT nLeading,
   }
   return hRet;
 }
+
+/**********************************************************************
+ *              VarMonthName [OLEAUT32.129]
+ *
+ * Print the specified month as localized name.
+ *
+ * PARAMS
+ *  iMonth    [I] month number 1..12
+ *  fAbbrev   [I] 0 - full name, !0 - abbreviated name
+ *  dwFlags   [I] flag stuff. only VAR_CALENDAR_HIJRI possible.
+ *  pbstrOut  [O] Destination for month name
+ *
+ * RETURNS
+ *  Success: S_OK. pbstrOut contains the name.
+ *  Failure: E_INVALIDARG, if any parameter is invalid.
+ *           E_OUTOFMEMORY, if enough memory cannot be allocated.
+ */
+HRESULT WINAPI VarMonthName(INT iMonth, INT fAbbrev, ULONG dwFlags, BSTR *pbstrOut)
+{
+  DWORD localeValue;
+  INT size;
+  WCHAR *str;
+
+  if ((iMonth < 1)  || (iMonth > 12))
+    return E_INVALIDARG;
+
+  if (dwFlags)
+    FIXME("Does not support dwFlags 0x%lx, ignoring.\n", dwFlags);
+
+  if (fAbbrev)
+       localeValue = LOCALE_SABBREVMONTHNAME1 + iMonth - 1;
+  else
+       localeValue = LOCALE_SMONTHNAME1 + iMonth - 1;
+
+  size = GetLocaleInfoW(LOCALE_USER_DEFAULT,localeValue, NULL, 0);
+  if (!size) {
+    FIXME("GetLocaleInfo 0x%lx failed.\n", localeValue);
+    return E_INVALIDARG;
+  }
+  str = HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*size);
+  if (!str)
+    return E_OUTOFMEMORY;
+  size = GetLocaleInfoW(LOCALE_USER_DEFAULT,localeValue, str, size);
+  if (!size) {
+    FIXME("GetLocaleInfo of 0x%lx failed in 2nd stage?!\n", localeValue);
+    HeapFree(GetProcessHeap(),0,str);
+    return E_INVALIDARG;
+  }
+  *pbstrOut = SysAllocString(str);
+  HeapFree(GetProcessHeap(),0,str);
+  if (!*pbstrOut)
+    return E_OUTOFMEMORY;
+  return S_OK;
+}
index f57f0df..4a9985a 100644 (file)
@@ -2569,6 +2569,7 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
     case VT_UI4  :
     case VT_UINT : lVal = V_UI4(left); break;
     case VT_BOOL : lVal = V_BOOL(left); break;
+    case VT_EMPTY : lVal = 0; break;
     default: lOk = FALSE;
     }
 
@@ -2583,6 +2584,7 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
     case VT_UI4  :
     case VT_UINT : rVal = V_UI4(right); break;
     case VT_BOOL : rVal = V_BOOL(right); break;
+    case VT_EMPTY : rVal = 0; break;
     default: rOk = FALSE;
     }
 
@@ -2596,7 +2598,7 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
         }
     }
 
-    /* Strings - use VarBstrCmp */
+    /* Dates */
     if ((V_VT(left)&VT_TYPEMASK) == VT_DATE &&
         (V_VT(right)&VT_TYPEMASK) == VT_DATE) {
 
@@ -2717,198 +2719,188 @@ HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
 
 /**********************************************************************
  *              VarAdd [OLEAUT32.141]
- * FIXME: From MSDN: If ... Then
- * Both expressions are of the string type Concatenated.
- * One expression is a string type and the other a character Addition.
- * One expression is numeric and the other is a string Addition.
- * Both expressions are numeric Addition.
- * Either expression is NULL NULL is returned.
- * Both expressions are empty  Integer subtype is returned.
  *
+ * Add two variants.
+ *
+ * PARAMS
+ *  left    [I] First variant
+ *  right   [I] Second variant
+ *  result  [O] Result variant
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code indicating the error.
+ *
+ * NOTES
+ *  Native VarAdd up to and including WinXP dosn't like as input variants
+ *  I1, UI2, UI4, UI8, INT and UINT.
+ *
+ *  Native VarAdd dosn't check for NULL in/out pointers and crashes. We do the
+ *  same here.
+ *
+ * FIXME
+ *  Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
+ *  case.
  */
 HRESULT WINAPI VarAdd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
 {
-    HRESULT rc = E_FAIL;
-
-    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
-
-    if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
-       return VariantCopy(result,right);
+    HRESULT hres;
+    VARTYPE lvt, rvt, resvt, tvt;
+    VARIANT lv, rv, tv;
+    double r8res;
 
-    if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
-       return VariantCopy(result,left);
+    /* Variant priority for coercion. Sorted from lowest to highest.
+       VT_ERROR shows an invalid input variant type. */
+    enum coerceprio { vt_EMPTY, vt_UI1, vt_I2, vt_I4, vt_I8, vt_BSTR,vt_R4,
+                      vt_R8, vt_CY, vt_DATE, vt_DECIMAL, vt_DISPATCH, vt_NULL,
+                      vt_ERROR };
+    /* Mapping from priority to variant type. Keep in sync with coerceprio! */
+    VARTYPE prio2vt[] = { VT_EMPTY, VT_UI1, VT_I2, VT_I4, VT_I8, VT_BSTR, VT_R4,
+                          VT_R8, VT_CY, VT_DATE, VT_DECIMAL, VT_DISPATCH,
+                          VT_NULL, VT_ERROR };
 
-    /* check if we add doubles */
-    if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        double       lVal = -1;
-        double       rVal = -1;
-        double       res  = -1;
+    /* Mapping for coercion from input variant to priority of result variant. */
+    static VARTYPE coerce[] = {
+        /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
+        vt_EMPTY, vt_NULL, vt_I2, vt_I4, vt_R4,
+        /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
+        vt_R8, vt_CY, vt_DATE, vt_BSTR, vt_DISPATCH,
+        /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
+        vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
+        /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
+        vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
+    };
 
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_I1(left);   break;
-        case VT_I2   : lVal = V_I2(left);   break;
-        case VT_I4   :
-        case VT_INT  : lVal = V_I4(left);   break;
-        case VT_UI1  : lVal = V_UI1(left);   break;
-        case VT_UI2  : lVal = V_UI2(left);  break;
-        case VT_UI4  :
-        case VT_UINT : lVal = V_UI4(left);  break;
-        case VT_R4   : lVal = V_R4(left);  break;
-        case VT_R8   : lVal = V_R8(left);  break;
-       case VT_NULL : lVal = 0.0;  break;
-        default: lOk = FALSE;
-        }
+    TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
+          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
+          result);
 
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_I1(right);  break;
-        case VT_I2   : rVal = V_I2(right);  break;
-        case VT_I4   :
-        case VT_INT  : rVal = V_I4(right);  break;
-        case VT_UI1  : rVal = V_UI1(right);  break;
-        case VT_UI2  : rVal = V_UI2(right); break;
-        case VT_UI4  :
-        case VT_UINT : rVal = V_UI4(right); break;
-        case VT_R4   : rVal = V_R4(right);break;
-        case VT_R8   : rVal = V_R8(right);break;
-       case VT_NULL : rVal = 0.0; break;
-        default: rOk = FALSE;
-        }
+    VariantInit(&lv);
+    VariantInit(&rv);
+    VariantInit(&tv);
+    lvt = V_VT(left)&VT_TYPEMASK;
+    rvt = V_VT(right)&VT_TYPEMASK;
 
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = VT_R8;
-            V_R8(result)  = res;
-            rc = S_OK;
-        } else {
-           FIXME("Unhandled type pair %d / %d in double addition.\n",
-               (V_VT(left)&VT_TYPEMASK),
-               (V_VT(right)&VT_TYPEMASK)
-           );
-       }
-       return rc;
+    /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
+       Same for any input variant type > VT_I8 */
+    if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
+        lvt > VT_I8 || rvt > VT_I8) {
+        hres = DISP_E_BADVARTYPE;
+        goto end;
     }
 
-    /* now check if we add floats. VT_R8 can no longer happen here! */
-    if (((V_VT(left)&VT_TYPEMASK) == VT_R4) || ((V_VT(right)&VT_TYPEMASK) == VT_R4)) {
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        float        lVal = -1;
-        float        rVal = -1;
-        float        res  = -1;
-
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_I1(left);   break;
-        case VT_I2   : lVal = V_I2(left);   break;
-        case VT_I4   :
-        case VT_INT  : lVal = V_I4(left);   break;
-        case VT_UI1  : lVal = V_UI1(left);   break;
-        case VT_UI2  : lVal = V_UI2(left);  break;
-        case VT_UI4  :
-        case VT_UINT : lVal = V_UI4(left);  break;
-        case VT_R4   : lVal = V_R4(left);  break;
-       case VT_NULL : lVal = 0.0;  break;
-        default: lOk = FALSE;
-        }
-
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_I1(right);  break;
-        case VT_I2   : rVal = V_I2(right);  break;
-        case VT_I4   :
-        case VT_INT  : rVal = V_I4(right);  break;
-        case VT_UI1  : rVal = V_UI1(right);  break;
-        case VT_UI2  : rVal = V_UI2(right); break;
-        case VT_UI4  :
-        case VT_UINT : rVal = V_UI4(right); break;
-        case VT_R4   : rVal = V_R4(right);break;
-       case VT_NULL : rVal = 0.0; break;
-        default: rOk = FALSE;
-        }
-
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = VT_R4;
-            V_R4(result)  = res;
-            rc = S_OK;
-        } else {
-           FIXME("Unhandled type pair %d / %d in float addition.\n",
-               (V_VT(left)&VT_TYPEMASK),
-               (V_VT(right)&VT_TYPEMASK)
-           );
-       }
-       return rc;
+    /* Determine the variant type to coerce to. */
+    if (coerce[lvt] > coerce[rvt]) {
+        resvt = prio2vt[coerce[lvt]];
+        tvt = prio2vt[coerce[rvt]];
+    } else {
+        resvt = prio2vt[coerce[rvt]];
+        tvt = prio2vt[coerce[lvt]];
     }
 
-    /* Handle strings as concat */
-    if ((V_VT(left)&VT_TYPEMASK) == VT_BSTR &&
-        (V_VT(right)&VT_TYPEMASK) == VT_BSTR) {
-        V_VT(result) = VT_BSTR;
-        return VarBstrCat(V_BSTR(left), V_BSTR(right), &V_BSTR(result));
-    } else {
+    /* Special cases where the result variant type is defined by both
+       input variants and not only that with the highest priority */
+    if (resvt == VT_BSTR) {
+        if (tvt == VT_EMPTY || tvt == VT_BSTR)
+            resvt = VT_BSTR;
+        else
+            resvt = VT_R8;
+    }
+    if (resvt == VT_R4 && (tvt == VT_BSTR || tvt == VT_I8 || tvt == VT_I4))
+        resvt = VT_R8;
 
-        /* Integers */
-        BOOL         lOk        = TRUE;
-        BOOL         rOk        = TRUE;
-        LONGLONG     lVal = -1;
-        LONGLONG     rVal = -1;
-        LONGLONG     res  = -1;
-        int          resT = 0; /* Testing has shown I2 + I2 == I2, all else
-                                  becomes I4                                */
+    /* For overflow detection use the biggest compatible type for the
+       addition */
+    switch (resvt) {
+        case VT_ERROR:
+            hres = DISP_E_BADVARTYPE;
+            goto end;
+        case VT_NULL:
+            hres = S_OK;
+            V_VT(result) = VT_NULL;
+            goto end;
+        case VT_DISPATCH:
+            FIXME("cannot handle variant type VT_DISPATCH\n");
+            hres = DISP_E_TYPEMISMATCH;
+            goto end;
+        case VT_EMPTY:
+            resvt = VT_I2;
+            /* Fall through */
+        case VT_UI1:
+        case VT_I2:
+        case VT_I4:
+        case VT_I8:
+            tvt = VT_I8;
+            break;
+        case VT_DATE:
+        case VT_R4:
+            tvt = VT_R8;
+            break;
+        default:
+            tvt = resvt;
+    }
 
-        lOk = TRUE;
-        switch (V_VT(left)&VT_TYPEMASK) {
-        case VT_I1   : lVal = V_I1(left);  resT=VT_I4; break;
-        case VT_I2   : lVal = V_I2(left);  resT=VT_I2; break;
-        case VT_I4   :
-        case VT_INT  : lVal = V_I4(left);  resT=VT_I4; break;
-        case VT_UI1  : lVal = V_UI1(left);  resT=VT_I4; break;
-        case VT_UI2  : lVal = V_UI2(left); resT=VT_I4; break;
-        case VT_UI4  :
-        case VT_UINT : lVal = V_UI4(left); resT=VT_I4; break;
-       case VT_NULL : lVal = 0; resT = VT_I4; break;
-        default: lOk = FALSE;
-        }
+    /* Now coerce the variants */
+    hres = VariantChangeType(&lv, left, 0, tvt);
+    if (FAILED(hres))
+        goto end;
+    hres = VariantChangeType(&rv, right, 0, tvt);
+    if (FAILED(hres))
+        goto end;
 
-        rOk = TRUE;
-        switch (V_VT(right)&VT_TYPEMASK) {
-        case VT_I1   : rVal = V_I1(right);  resT=VT_I4; break;
-        case VT_I2   : rVal = V_I2(right);  resT=max(VT_I2, resT); break;
-        case VT_I4   :
-        case VT_INT  : rVal = V_I4(right);  resT=VT_I4; break;
-        case VT_UI1  : rVal = V_UI1(right);  resT=VT_I4; break;
-        case VT_UI2  : rVal = V_UI2(right); resT=VT_I4; break;
-        case VT_UI4  :
-        case VT_UINT : rVal = V_UI4(right); resT=VT_I4; break;
-       case VT_NULL : rVal = 0; resT=VT_I4; break;
-        default: rOk = FALSE;
+    /* Do the math */
+    hres = S_OK;
+    V_VT(&tv) = tvt;
+    V_VT(result) = resvt;
+    switch (tvt) {
+        case VT_DECIMAL:
+            hres = VarDecAdd(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
+                             &V_DECIMAL(result));
+            goto end;
+        case VT_CY:
+            hres = VarCyAdd(V_CY(&lv), V_CY(&rv), &V_CY(result));
+            goto end;
+        case VT_BSTR:
+            /* We do not add those, we concatenate them. */
+            hres = VarBstrCat(V_BSTR(&lv), V_BSTR(&rv), &V_BSTR(result));
+            goto end;
+        case VT_I8:
+            /* Overflow detection */
+            r8res = (double)V_I8(&lv) + (double)V_I8(&rv);
+            if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
+                V_VT(result) = VT_R8;
+                V_R8(result) = r8res;
+                goto end;
+            } else
+                V_I8(&tv) = V_I8(&lv) + V_I8(&rv);
+            break;
+        case VT_R8:
+            /* FIXME: overflow detection */
+            V_R8(&tv) = V_R8(&lv) + V_R8(&rv);
+            break;
+        default:
+            ERR("We shouldn't get here! tvt = %d!\n", tvt);
+            break;
+    }
+    if (resvt != tvt) {
+        if ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
+            /* Overflow! Change to the vartype with the next higher priority */
+            resvt = prio2vt[coerce[resvt] + 1];
+            hres = VariantChangeType(result, &tv, 0, resvt);
         }
+    } else
+        hres = VariantCopy(result, &tv);
 
-        if (lOk && rOk) {
-            res = (lVal + rVal);
-            V_VT(result) = resT;
-            switch (resT) {
-            case VT_I2   : V_I2(result)  = res; break;
-            case VT_I4   : V_I4(result)  = res; break;
-            default:
-                FIXME("Unexpected result variant type %x\n", resT);
-                V_I4(result)  = res;
-            }
-            rc = S_OK;
-
-        } else {
-            FIXME("unimplemented part (0x%x + 0x%x)\n",V_VT(left), V_VT(right));
-        }
+end:
+    if (hres != S_OK) {
+        V_VT(result) = VT_EMPTY;
+        V_I4(result) = 0;       /* No V_EMPTY */
     }
-
-    TRACE("returning 0x%8lx (%s%s),%ld\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_I4 ? V_I4(result) : V_I2(result));
-    return rc;
+    VariantClear(&lv);
+    VariantClear(&rv);
+    VariantClear(&tv);
+    TRACE("returning 0x%8lx (variant type %s)\n", hres, debugstr_VT(result));
+    return hres;
 }
 
 /**********************************************************************
@@ -3058,7 +3050,7 @@ HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
             ERR("We shouldn't get here! tvt = %d!\n", tvt);
             break;
     }
-    if (rvt != tvt) {
+    if (resvt != tvt) {
         while ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
             /* Overflow! Change to the vartype with the next higher priority */
             resvt = prio2vt[coerce[resvt] + 1];