Sync to Wine-20050628:

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
This commit is contained in:
Gé van Geldorp 2005-08-03 22:46:31 +00:00
parent 7ba677508a
commit c089737240
14 changed files with 751 additions and 558 deletions

View 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,

View 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,

View 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[] =
static 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,
( 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[] =
static 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,
( 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,

View file

@ -126,7 +126,7 @@
126 stdcall VarBoolFromDisp(ptr long ptr)
127 stdcall VarFormatCurrency(ptr long long long long long ptr)
128 stub VarWeekdayName # stdcall (long long long long ptr)
129 stub VarMonthName # stdcall (long long long ptr)
129 stdcall VarMonthName(long long long ptr)
130 stdcall VarUI1FromI2(long ptr)
131 stdcall VarUI1FromI4(long ptr)
132 stdcall VarUI1FromR4(long ptr)

View 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,

View 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) {
headerisdata = FALSE;
xread = 0;
if (!memcmp(&(header[0]),"lt\0\0", 4) && (header[1] <= statstg.cbSize.QuadPart-8)) {
toread = header[1];
} else {
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,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);
} else {
xread = 0;
xbuf = This->data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,header[1]);
This->datalen = header[1];
while (xread < header[1]) {
ULONG nread;
hr = IStream_Read(pStm,xbuf+xread,header[1]-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,

View 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,

View 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]

View 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,

View 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 */

View 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,

View 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;
/* 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++) {
VariantInit(&arg[u]);
VariantCopy(&arg[u], &rgvarg[u]);
}
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;
hr = IDispatch_Invoke(This,
dispIdMember,
riid,
lcid,
dwFlags,
pDispParams,
pVarResult,
pExcepInfo,
pArgErr);
/* 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);
if (!arg) return E_OUTOFMEMORY;
/* 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]);
/* 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]);
for (u = 0; u < pDispParams->cArgs; u++) {
hr = VariantCopy(&arg[u], &rgvarg[u]);
if (FAILED(hr))
break;
}
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]);
}
}
/* 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);

View 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
{
fractionalDigits--;
wholeNumberDigits++;
}
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;
}
}
TRACE("cDig %d; nPwr10 %d, whole %d, frac %d ", np.cDig,
np.nPwr10, wholeNumberDigits, fractionalDigits);
TRACE("mult %d; div %d\n", multiplier10, divisor10);
/* 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)
{
/* 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("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;
TRACE("write %d fractional digits or skip\n", pToken[1]);
for (count = 0; count < fractionalDigits; count++)
pBuff[count] = '0' + rgbDig[wholeNumberDigits + count];
pBuff += fractionalDigits;
}
else
{
int count;
TRACE("write %d digits or skip\n", pToken[1]);
if (wholeNumberDigits > 1 || rgbDig[0] > 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 */
}
}
pToken++;
break;
case FMT_NUM_COPY_ZERO:
dwState |= NUM_WRITE_ON;
/* Fall through */
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");
if (dwState & NUM_WROTE_DEC)
{
int count;
int count, i;
TRACE("write %d fractional digits or 0's\n", pToken[1]);
for (count = 0; count < fractionalDigits; count++)
pBuff[count] = '0' + rgbDig[wholeNumberDigits + count];
pBuff += fractionalDigits;
if (pToken[1] > fractionalDigits)
if (!(numHeader->flags & FMT_FLAG_EXPONENT) && exponent < 0)
{
count = pToken[1] - fractionalDigits;
while (count--)
*pBuff++ = '0'; /* Write trailing zeros for missing digits */
/* 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';
}
else
count = min(have_frac, pToken[1]);
pad += pToken[1] - count;
have_frac -= count;
while (count--)
*pBuff++ = '0' + *prgbDig++;
if (*pToken == FMT_NUM_COPY_ZERO)
{
for (; pad > 0; pad--)
*pBuff++ = '0'; /* Write zeros for missing trailing digits */
}
}
else
{
int count;
int count, count_max;
TRACE("write %d digits or 0's\n", pToken[1]);
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;
}

View 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;
HRESULT hres;
VARTYPE lvt, rvt, resvt, tvt;
VARIANT lv, rv, tv;
double r8res;
/* 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 };
/* 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
};
TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
result);
if ((V_VT(left)&VT_TYPEMASK) == VT_EMPTY)
return VariantCopy(result,right);
VariantInit(&lv);
VariantInit(&rv);
VariantInit(&tv);
lvt = V_VT(left)&VT_TYPEMASK;
rvt = V_VT(right)&VT_TYPEMASK;
if ((V_VT(right)&VT_TYPEMASK) == VT_EMPTY)
return VariantCopy(result,left);
/* check if we add doubles */
if (((V_VT(left)&VT_TYPEMASK) == VT_R8) || ((V_VT(right)&VT_TYPEMASK) == VT_R8)) {
BOOL lOk = TRUE;
BOOL rOk = TRUE;
double lVal = -1;
double rVal = -1;
double res = -1;
lOk = TRUE;
switch (V_VT(left)&VT_TYPEMASK) {
case VT_I1 : lVal = V_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;
}
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;
}
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;
}
/* 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));
/* Determine the variant type to coerce to. */
if (coerce[lvt] > coerce[rvt]) {
resvt = prio2vt[coerce[lvt]];
tvt = prio2vt[coerce[rvt]];
} else {
/* Integers */
BOOL lOk = TRUE;
BOOL rOk = TRUE;
LONGLONG lVal = -1;
LONGLONG rVal = -1;
LONGLONG res = -1;
int resT = 0; /* Testing has shown I2 + I2 == I2, all else
becomes I4 */
lOk = TRUE;
switch (V_VT(left)&VT_TYPEMASK) {
case VT_I1 : lVal = V_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;
}
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;
}
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));
}
resvt = prio2vt[coerce[rvt]];
tvt = prio2vt[coerce[lvt]];
}
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;
/* 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;
/* 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;
}
/* 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;
/* 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);
end:
if (hres != S_OK) {
V_VT(result) = VT_EMPTY;
V_I4(result) = 0; /* No V_EMPTY */
}
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];