Sync to Wine-20050725:

Huw Davies <huw@codeweavers.com> for Mandriva
- Cope with the index in a import table entry being a typeinfo index
  rather than a guid offset.
Robert Shearman <rob@codeweavers.com>
- Document active object and variant functions.
- Rename OLEAUT32_Dll* Functions to Dll*.
- IRpcStubBuffer_Disconnect can be called multiple times.
- Release TypeLib when freeing stub buffer.
- Fix confusion between number of characters and number of bytes in
  unmarshaling BSTRs. Convert it all to characters for consistency with
  the BSTR_User* routines.
- Marshal and unmarshal TKIND_ENUM and TKIND_ALIAS.
- Fix VT_BYREF|VT_UNKNOWN return values by comparing the correct value
  with VT_UNKNOWN and VT_DISPATCH.
- Better tracing.
- Return DISP_E_EXCEPTION from ITypeInfo_Invoke on an error in the
  called function.
- Remove RegisterTypeLib hack.
- Support VT_BYREF|VT_I4 in _copy_arg.
- Activate ITypeLib, ITypeInfo and IEnumVARIANT Marshalers.
Alex Villacis Lasso <a_villacis@palosanto.com>
- Fix GIF palette allocation, by relying on ColorCount instead of
  SColorResolution.
- Ensure that underflowing negative float is represented as a positive
  0, just as native oleaut32.
Alexandre Julliard <julliard@winehq.org>
- Get rid of cursoricon.h.
Mike McCormack <mike@codeweavers.com>
- gcc 4.0 -Wpointer-sign fixes (Reg* functions).
- Interlocked LONG* gcc warning fixes.
Stefan Huehner <stefan@huehner.org>
- Fix some more -Wmissing-declarations warnings.
Robert Shearman <rob@codeweavers.com> for Mandriva
- Add a generic TYPEDESC VT to VARIANT VT mapper so we can use the
  standard Variant* routines. Use this new function to properly copy &
  de-reference the return value.
- Conversions between variants types of the same size should ignore
  overflows.
- Tests for this behaviour.

svn path=/trunk/; revision=17333
This commit is contained in:
Gé van Geldorp 2005-08-12 17:30:09 +00:00
parent 7835b350bb
commit a48a2273ec
16 changed files with 395 additions and 197 deletions

View file

@ -20,6 +20,7 @@
#define strcmpiW(s1,s2) _wcsicmp((const wchar_t *)(s1),(const wchar_t *)(s2))
#define strncmpiW(s1,s2,n) _wcsnicmp((const wchar_t *)(s1),(const wchar_t *)(s2),(n))
#define strtoulW(s1,s2,b) wcstoul((const wchar_t *)(s1),(wchar_t **)(s2),(b))
#define strspnW(str, accept) wcsspn((const wchar_t *)(str), (const wchar_t *)(accept))
#define tolowerW(n) towlower((n))
#define toupperW(n) towupper((n))
#define islowerW(n) iswlower((n))

View file

@ -54,7 +54,7 @@ typedef struct ConnectionPointImpl {
IUnknown *Obj;
/* Reference count */
DWORD ref;
LONG ref;
/* IID of sink interface */
IID iid;
@ -76,7 +76,7 @@ typedef struct EnumConnectionsImpl {
const IEnumConnectionsVtbl *lpvtbl;
DWORD ref;
LONG ref;
/* IUnknown of ConnectionPoint, used for ref counting */
IUnknown *pUnk;

View file

@ -217,7 +217,7 @@ typedef struct
const IDispatchVtbl *lpVtbl;
void * pvThis;
ITypeInfo * pTypeInfo;
ULONG ref;
LONG ref;
} StdDispatch;
/******************************************************************************

View file

@ -42,8 +42,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
/* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
extern const GUID CLSID_PSOAInterface;
/* IDispatch marshaler */
extern const GUID CLSID_PSDispatch;
extern const GUID CLSID_PSEnumVariant;
extern const GUID CLSID_PSTypeInfo;
extern const GUID CLSID_PSTypeLib;
extern const GUID CLSID_PSTypeComp;
static BOOL BSTR_bCache = TRUE; /* Cache allocations to minimise alloc calls? */
@ -449,6 +452,18 @@ static WCHAR *pdelimiter = &_delimiter[0];
/***********************************************************************
* RegisterActiveObject (OLEAUT32.33)
*
* Registers an object in the global item table.
*
* PARAMS
* punk [I] Object to register.
* rcid [I] CLSID of the object.
* dwFlags [I] Flags.
* pdwRegister [O] Address to store cookie of object registration in.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*/
HRESULT WINAPI RegisterActiveObject(
LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister
@ -475,6 +490,16 @@ HRESULT WINAPI RegisterActiveObject(
/***********************************************************************
* RevokeActiveObject (OLEAUT32.34)
*
* Revokes an object from the global item table.
*
* PARAMS
* xregister [I] Registration cookie.
* reserved [I] Reserved. Set to NULL.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*/
HRESULT WINAPI RevokeActiveObject(DWORD xregister,LPVOID reserved)
{
@ -491,6 +516,17 @@ HRESULT WINAPI RevokeActiveObject(DWORD xregister,LPVOID reserved)
/***********************************************************************
* GetActiveObject (OLEAUT32.35)
*
* Gets an object from the global item table.
*
* PARAMS
* rcid [I] CLSID of the object.
* preserved [I] Reserved. Set to NULL.
* ppunk [O] Address to store object into.
*
* RETURNS
* Success: S_OK.
* Failure: HRESULT code.
*/
HRESULT WINAPI GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk)
{
@ -667,7 +703,7 @@ extern void _get_STDPIC_CF(LPVOID);
/***********************************************************************
* DllGetClassObject (OLEAUT32.1)
*/
HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
{
*ppv = NULL;
if (IsEqualGUID(rclsid,&CLSID_StdFont)) {
@ -684,8 +720,11 @@ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *p
return S_OK;
}
}
if (IsEqualGUID(rclsid,&CLSID_PSDispatch)) {
return OLEAUTPS_DllGetClassObject(rclsid,iid,ppv);
if (IsEqualCLSID(rclsid, &CLSID_PSDispatch) ||
IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) ||
IsEqualCLSID(rclsid, &CLSID_PSTypeLib) ||
IsEqualCLSID(rclsid, &CLSID_PSEnumVariant)) {
return OLEAUTPS_DllGetClassObject(&CLSID_PSDispatch, iid, ppv);
}
if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) {
if (S_OK==TypeLibFac_DllGetClassObject(rclsid,iid,ppv))
@ -707,7 +746,7 @@ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *p
* RETURNS
* Always returns S_FALSE. This dll cannot be unloaded.
*/
HRESULT WINAPI OLEAUT32_DllCanUnloadNow(void)
HRESULT WINAPI DllCanUnloadNow(void)
{
return S_FALSE;
}

View file

@ -1,4 +1,4 @@
1 stdcall -private DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject
1 stdcall -private DllGetClassObject(ptr ptr ptr)
2 stdcall SysAllocString(wstr)
3 stdcall SysReAllocString(ptr wstr)
4 stdcall SysAllocStringLen(wstr long)
@ -312,8 +312,8 @@
317 stdcall VarR8Round(double long ptr)
318 stdcall VarCat(ptr ptr ptr)
319 stdcall VarDateFromUdateEx(ptr long long ptr)
320 stdcall -private DllRegisterServer() OLEAUT32_DllRegisterServer
321 stdcall -private DllUnregisterServer() OLEAUT32_DllUnregisterServer
320 stdcall -private DllRegisterServer()
321 stdcall -private DllUnregisterServer()
322 stdcall GetRecordInfoFromGuids(ptr long long long ptr ptr)
323 stdcall GetRecordInfoFromTypeInfo(ptr ptr)
325 stub SetVarConversionLocaleSetting
@ -382,7 +382,7 @@
399 stub UserMSG_free_local
401 stdcall OleLoadPictureEx(ptr long long long long long long ptr)
402 stub OleLoadPictureFileEx
410 stdcall -private DllCanUnloadNow() OLEAUT32_DllCanUnloadNow
410 stdcall -private DllCanUnloadNow()
411 stdcall SafeArrayCreateVector(long long long)
412 stdcall SafeArrayCopyData(ptr ptr)
413 stdcall VectorFromBstr(ptr ptr)

View file

@ -72,7 +72,7 @@ struct OLEFontImpl
/*
* Reference count for that instance of the class.
*/
ULONG ref;
LONG ref;
/*
* This structure contains the description of the class.
@ -2102,7 +2102,7 @@ typedef struct
{
/* IUnknown fields */
const IClassFactoryVtbl *lpVtbl;
DWORD ref;
LONG ref;
} IClassFactoryImpl;
static HRESULT WINAPI

View file

@ -76,7 +76,6 @@
#include "wine/unicode.h"
#include "wine/wingdi16.h"
#include "cursoricon.h"
#ifdef HAVE_JPEGLIB_H
/* This is a hack, so jpeglib.h does not redefine INT32 and the like*/
@ -93,6 +92,29 @@
WINE_DEFAULT_DEBUG_CHANNEL(ole);
#include "pshpack1.h"
typedef struct {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD xHotspot;
WORD yHotspot;
DWORD dwDIBSize;
DWORD dwDIBOffset;
} CURSORICONFILEDIRENTRY;
typedef struct
{
WORD idReserved;
WORD idType;
WORD idCount;
CURSORICONFILEDIRENTRY idEntries[1];
} CURSORICONFILEDIR;
#include "poppack.h"
/*************************************************************************
* Declaration of implementation class
*/
@ -109,7 +131,7 @@ typedef struct OLEPictureImpl {
const IConnectionPointContainerVtbl *lpvtbl4;
/* Object reference count */
DWORD ref;
LONG ref;
/* We own the object and must destroy it ourselves */
BOOL fOwn;
@ -1117,12 +1139,12 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
);
/* */
padding = (gif->SWidth+3) & ~3;
bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<<gif->SColorResolution)*sizeof(RGBQUAD));
bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
si = gif->SavedImages+0;
gid = &(si->ImageDesc);
cm = gid->ColorMap;
if (!cm) cm = gif->SColorMap;
bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(cm->ColorCount)*sizeof(RGBQUAD));
bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight);
/* look for the transparent color extension */
for (i = 0; i < si->ExtensionBlockCount; ++i) {
@ -1134,7 +1156,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
}
}
for (i=0;i<(1<<gif->SColorResolution);i++) {
for (i = 0; i < cm->ColorCount; i++) {
bmi->bmiColors[i].rgbRed = cm->Colors[i].Red;
bmi->bmiColors[i].rgbGreen = cm->Colors[i].Green;
bmi->bmiColors[i].rgbBlue = cm->Colors[i].Blue;
@ -1181,7 +1203,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) {
bmi->bmiHeader.biSizeImage = padding*gif->SHeight;
bmi->bmiHeader.biXPelsPerMeter = 0;
bmi->bmiHeader.biYPelsPerMeter = 0;
bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution;
bmi->bmiHeader.biClrUsed = cm->ColorCount;
bmi->bmiHeader.biClrImportant = 0;
hdcref = GetDC(0);
@ -2210,7 +2232,7 @@ typedef struct
{
/* IUnknown fields */
const IClassFactoryVtbl *lpVtbl;
DWORD ref;
LONG ref;
} IClassFactoryImpl;
static HRESULT WINAPI

View file

@ -42,7 +42,7 @@ typedef struct {
typedef struct {
const IRecordInfoVtbl *lpVtbl;
ULONG ref;
LONG ref;
GUID guid;
UINT lib_index;

View file

@ -445,20 +445,20 @@ static GUID const CLSID_RecordInfo = {
extern GUID const CLSID_PSDispatch;
static GUID const CLSID_PSEnumVariant = {
GUID const CLSID_PSEnumVariant = {
0x00020421, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
static GUID const CLSID_PSTypeInfo = {
GUID const CLSID_PSTypeInfo = {
0x00020422, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
static GUID const CLSID_PSTypeLib = {
GUID const CLSID_PSTypeLib = {
0x00020423, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
extern GUID const CLSID_PSOAInterface;
static GUID const CLSID_PSTypeComp = {
GUID const CLSID_PSTypeComp = {
0x00020425, 0x0000, 0x0000, {0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46} };
extern GUID const CLSID_PSOAInterface;
static GUID const CLSID_OldFont = {
0x46763EE0, 0xCAB2, 0x11CE, {0x8C,0x20,0x00,0xAA,0x00,0x51,0xE5,0xD4} };
@ -903,7 +903,7 @@ static struct regsvr_interface const interface_list[] = {
/***********************************************************************
* DllRegisterServer (OLEAUT32.320)
*/
HRESULT WINAPI OLEAUT32_DllRegisterServer()
HRESULT WINAPI DllRegisterServer(void)
{
HRESULT hr;
@ -918,7 +918,7 @@ HRESULT WINAPI OLEAUT32_DllRegisterServer()
/***********************************************************************
* DllUnregisterServer (OLEAUT32.321)
*/
HRESULT WINAPI OLEAUT32_DllUnregisterServer()
HRESULT WINAPI DllUnregisterServer(void)
{
HRESULT hr;

View file

@ -262,7 +262,8 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
char tlguid[200],typelibkey[300],interfacekey[300],ver[100];
char tlfn[260];
OLECHAR tlfnW[260];
DWORD tlguidlen, verlen, type, tlfnlen;
DWORD tlguidlen, verlen, type;
LONG tlfnlen;
ITypeLib *tl;
sprintf( interfacekey, "Interface\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\Typelib",
@ -277,14 +278,14 @@ _get_typeinfo_for_iid(REFIID riid, ITypeInfo**ti) {
}
type = (1<<REG_SZ);
tlguidlen = sizeof(tlguid);
if (RegQueryValueExA(ikey,NULL,NULL,&type,tlguid,&tlguidlen)) {
if (RegQueryValueExA(ikey,NULL,NULL,&type,(LPBYTE)tlguid,&tlguidlen)) {
ERR("Getting typelib guid failed.\n");
RegCloseKey(ikey);
return E_FAIL;
}
type = (1<<REG_SZ);
verlen = sizeof(ver);
if (RegQueryValueExA(ikey,"Version",NULL,&type,ver,&verlen)) {
if (RegQueryValueExA(ikey,"Version",NULL,&type,(LPBYTE)ver,&verlen)) {
ERR("Could not get version value?\n");
RegCloseKey(ikey);
return E_FAIL;
@ -357,7 +358,7 @@ typedef struct _TMAsmProxy {
typedef struct _TMProxyImpl {
LPVOID *lpvtbl;
const IRpcProxyBufferVtbl *lpvtbl2;
ULONG ref;
LONG ref;
TMAsmProxy *asmstubs;
ITypeInfo* tinfo;
@ -564,15 +565,18 @@ serialize_param(
if (writeit) {
/* ptr to ptr to magic widestring, basically */
BSTR *bstr = (BSTR *) *arg;
DWORD len;
if (!*bstr) {
/* -1 means "null string" which is equivalent to empty string */
DWORD fakelen = -1;
xbuf_add(buf, (LPBYTE)&fakelen,4);
len = -1;
hres = xbuf_add(buf, (LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
} else {
/* BSTRs store the length behind the first character */
DWORD *len = ((DWORD *)(*bstr))-1;
hres = xbuf_add(buf, (LPBYTE) len, *len + 4);
if (hres) return hres;
len = *((DWORD*)*bstr-1)/sizeof(WCHAR);
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
hres = xbuf_add(buf,(LPBYTE)*bstr,len * sizeof(WCHAR));
if (hres) return hres;
}
}
@ -591,17 +595,18 @@ serialize_param(
TRACE_(olerelay)("<bstr NULL>");
}
if (writeit) {
if (!*arg) {
DWORD fakelen = -1;
hres = xbuf_add(buf,(LPBYTE)&fakelen,4);
if (hres)
return hres;
BSTR bstr = (BSTR)*arg;
DWORD len;
if (!bstr) {
len = -1;
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
} else {
DWORD *bstr = ((DWORD*)(*arg))-1;
hres = xbuf_add(buf,(LPBYTE)bstr,bstr[0]+4);
if (hres)
return hres;
len = *((DWORD*)bstr-1)/sizeof(WCHAR);
hres = xbuf_add(buf,(LPBYTE)&len,sizeof(DWORD));
if (hres) return hres;
hres = xbuf_add(buf,(LPBYTE)bstr,len * sizeof(WCHAR));
if (hres) return hres;
}
}
@ -704,6 +709,14 @@ serialize_param(
if (debugout) TRACE_(olerelay)("}");
break;
}
case TKIND_ALIAS:
return serialize_param(tinfo2,writeit,debugout,dealloc,&tattr->tdescAlias,arg,buf);
case TKIND_ENUM:
hres = S_OK;
if (debugout) TRACE_(olerelay)("%lx",*arg);
if (writeit)
hres = xbuf_add(buf,(LPBYTE)arg,sizeof(DWORD));
return hres;
default:
FIXME("Unhandled typekind %d\n",tattr->typekind);
hres = E_FAIL;
@ -1130,8 +1143,8 @@ deserialize_param(
**bstr = NULL;
if (debugout) TRACE_(olerelay)("<bstr NULL>");
} else {
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len);
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
if (hres) {
ERR("Failed to read BSTR.\n");
return hres;
@ -1160,8 +1173,8 @@ deserialize_param(
*arg = 0;
if (debugout) TRACE_(olerelay)("<bstr NULL>");
} else {
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,len+sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len);
str = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(len+1)*sizeof(WCHAR));
hres = xbuf_get(buf,(LPBYTE)str,len*sizeof(WCHAR));
if (hres) {
ERR("Failed to read BSTR.\n");
return hres;
@ -1275,6 +1288,15 @@ deserialize_param(
if (debugout) TRACE_(olerelay)("}");
break;
}
case TKIND_ALIAS:
return deserialize_param(tinfo2,readit,debugout,alloc,&tattr->tdescAlias,arg,buf);
case TKIND_ENUM:
if (readit) {
hres = xbuf_get(buf,(LPBYTE)arg,sizeof(DWORD));
if (hres) ERR("Failed to read enum (4 byte)\n");
}
if (debugout) TRACE_(olerelay)("%lx",*arg);
return hres;
default:
ERR("Unhandled typekind %d\n",tattr->typekind);
hres = E_FAIL;
@ -1911,7 +1933,7 @@ PSFacBuf_CreateProxy(
typedef struct _TMStubImpl {
const IRpcStubBufferVtbl *lpvtbl;
ULONG ref;
LONG ref;
LPUNKNOWN pUnk;
ITypeInfo *tinfo;
@ -1952,6 +1974,7 @@ TMStubImpl_Release(LPRPCSTUBBUFFER iface)
if (!refCount)
{
IRpcStubBuffer_Disconnect(iface);
ITypeInfo_Release(This->tinfo);
CoTaskMemFree(This);
}
return refCount;
@ -1976,9 +1999,11 @@ TMStubImpl_Disconnect(LPRPCSTUBBUFFER iface)
TRACE("(%p)->()\n", This);
IUnknown_Release(This->pUnk);
This->pUnk = NULL;
return;
if (This->pUnk)
{
IUnknown_Release(This->pUnk);
This->pUnk = NULL;
}
}
static HRESULT WINAPI

View file

@ -84,6 +84,8 @@ WINE_DECLARE_DEBUG_CHANNEL(typelib);
/* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
/****************************************************************************
* FromLExxx
*
@ -617,17 +619,8 @@ HRESULT WINAPI RegisterTypeLib(
MESSAGE("\n");
}
/*
* FIXME: The 1 is just here until we implement rpcrt4
* stub/proxy handling. Until then it helps IShield
* v6 to work.
*/
if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
{
if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
FIXME("Registering non-oleautomation interface!\n");
}
/* register interface<->typelib coupling */
get_interface_key( &tattr->guid, keyName );
if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
@ -863,7 +856,7 @@ typedef struct tagITypeLibImpl
{
const ITypeLib2Vtbl *lpVtbl;
const ITypeCompVtbl *lpVtblTypeComp;
ULONG ref;
LONG ref;
TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
/* strings can be stored in tlb as multibyte strings BUT they are *always*
@ -975,7 +968,7 @@ typedef struct tagITypeInfoImpl
{
const ITypeInfo2Vtbl *lpVtbl;
const ITypeCompVtbl *lpVtblTypeComp;
ULONG ref;
LONG ref;
TYPEATTR TypeAttr ; /* _lots_ of type information. */
ITypeLibImpl * pTypeLib; /* back pointer to typelib */
int index; /* index in this typelib; */
@ -1070,14 +1063,14 @@ static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
}
}
void dump_ELEMDESC(ELEMDESC *edesc) {
static void dump_ELEMDESC(ELEMDESC *edesc) {
char buf[200];
dump_TypeDesc(&edesc->tdesc,buf);
MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
}
void dump_FUNCDESC(FUNCDESC *funcdesc) {
static void dump_FUNCDESC(FUNCDESC *funcdesc) {
int i;
MESSAGE("memid is %08lx\n",funcdesc->memid);
for (i=0;i<funcdesc->cParams;i++) {
@ -1116,10 +1109,6 @@ void dump_FUNCDESC(FUNCDESC *funcdesc) {
dump_ELEMDESC(&funcdesc->elemdescFunc);
}
void dump_IDLDESC(IDLDESC *idl) {
MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
}
static const char * typekind_desc[] =
{
"TKIND_ENUM",
@ -1133,27 +1122,6 @@ static const char * typekind_desc[] =
"TKIND_MAX"
};
void dump_TYPEATTR(TYPEATTR *tattr) {
char buf[200];
MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
MESSAGE("\tlcid: %ld\n",tattr->lcid);
MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
MESSAGE("\tcVars: %d\n", tattr->cVars);
MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
dump_TypeDesc(&tattr->tdescAlias,buf);
MESSAGE("\ttypedesc: %s\n", buf);
dump_IDLDESC(&tattr->idldescType);
}
static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
{
int i;
@ -1305,7 +1273,7 @@ static void dump_TypeInfo(ITypeInfoImpl * pty)
dump_TLBImplType(pty->impltypelist);
}
void dump_VARDESC(VARDESC *v)
static void dump_VARDESC(VARDESC *v)
{
MESSAGE("memid %ld\n",v->memid);
MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
@ -1397,7 +1365,7 @@ static void free_deep_typedesc(TYPEDESC *tdesc)
* Functions for reading MSFT typelibs (those created by CreateTypeLib2)
*/
/* read function */
DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
{
TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
pcx->pos, count, pcx->oStart, pcx->length, where);
@ -1454,7 +1422,7 @@ static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
}
BSTR MSFT_ReadName( TLBContext *pcx, int offset)
static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
{
char * name;
MSFT_NameIntro niName;
@ -1489,7 +1457,7 @@ BSTR MSFT_ReadName( TLBContext *pcx, int offset)
return bstrName;
}
BSTR MSFT_ReadString( TLBContext *pcx, int offset)
static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
{
char * string;
INT16 length;
@ -1997,8 +1965,11 @@ static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
if(pImpLib){
(*ppRefType)->reference=offset;
(*ppRefType)->pImpTLInfo = pImpLib;
MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
(*ppRefType)->index = TLB_REF_USE_GUID;
if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
(*ppRefType)->index = TLB_REF_USE_GUID;
} else
(*ppRefType)->index = impinfo.oGuid;
}else{
ERR("Cannot find a reference\n");
(*ppRefType)->reference=-1;
@ -2038,7 +2009,7 @@ static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
/*
* process a typeinfo record
*/
ITypeInfoImpl * MSFT_DoTypeInfo(
static ITypeInfoImpl * MSFT_DoTypeInfo(
TLBContext *pcx,
int count,
ITypeLibImpl * pLibInfo)
@ -4617,6 +4588,10 @@ _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
memcpy(argpos, &V_I4(arg), 4);
hres = S_OK;
break;
case VT_BYREF|VT_I4:
memcpy(argpos, V_I4REF(arg), 4);
hres = S_OK;
break;
default:
FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
hres = E_FAIL;
@ -4697,6 +4672,123 @@ _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
return E_FAIL;
}
static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
{
HRESULT hr = S_OK;
ITypeInfo *tinfo2 = NULL;
TYPEATTR *tattr = NULL;
hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
if (hr)
{
ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
"hr = 0x%08lx\n",
tdesc->u.hreftype, hr);
return hr;
}
hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
if (hr)
{
ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
ITypeInfo_Release(tinfo2);
return hr;
}
switch (tattr->typekind)
{
case TKIND_ENUM:
*vt |= VT_INT;
break;
case TKIND_ALIAS:
tdesc = &tattr->tdescAlias;
hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
break;
case TKIND_INTERFACE:
if (IsEqualIID(&IID_IDispatch, &tattr->guid))
*vt |= VT_DISPATCH;
else
*vt |= VT_UNKNOWN;
break;
case TKIND_DISPATCH:
*vt |= VT_DISPATCH;
break;
case TKIND_RECORD:
FIXME("TKIND_RECORD unhandled.\n");
hr = E_NOTIMPL;
break;
case TKIND_UNION:
FIXME("TKIND_RECORD unhandled.\n");
hr = E_NOTIMPL;
break;
default:
FIXME("TKIND %d unhandled.\n",tattr->typekind);
hr = E_NOTIMPL;
break;
}
ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
ITypeInfo_Release(tinfo2);
return hr;
}
static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
{
HRESULT hr = S_OK;
/* enforce only one level of pointer indirection */
if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
{
tdesc = tdesc->u.lptdesc;
/* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
* VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
* VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
if ((tdesc->vt == VT_USERDEFINED) ||
((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
{
VARTYPE vt_userdefined = 0;
TYPEDESC *tdesc_userdefined = tdesc;
if (tdesc->vt == VT_PTR)
{
vt_userdefined = VT_BYREF;
tdesc_userdefined = tdesc->u.lptdesc;
}
hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
if ((hr == S_OK) &&
(((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
{
*vt |= vt_userdefined;
return S_OK;
}
}
*vt = VT_BYREF;
}
switch (tdesc->vt)
{
case VT_HRESULT:
*vt |= VT_ERROR;
break;
case VT_USERDEFINED:
hr = userdefined_to_variantvt(tinfo, tdesc, vt);
break;
case VT_PTR:
ERR("cannot convert VT_PTR into variant VT\n");
hr = E_FAIL;
break;
default:
*vt |= tdesc->vt;
break;
}
return hr;
}
/***********************************************************************
* DispCallFunc (OLEAUT32.@)
*/
@ -4772,6 +4864,11 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
if(FAILED(hres)) return hres;
if (TRACE_ON(ole))
{
TRACE("invoking:\n");
dump_FUNCDESC(func_desc);
}
switch (func_desc->funckind) {
case FUNC_PUREVIRTUAL:
@ -4873,76 +4970,36 @@ static HRESULT WINAPI ITypeInfo_fnInvoke(
args
);
if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
args2pos = 0;
for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
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_USERDEFINED) {
ITypeInfo *tinfo2;
TYPEATTR *tattr;
hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
if (FAILED(hres)) {
FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
goto func_fail;
}
ITypeInfo_GetTypeAttr(tinfo2,&tattr);
switch (tattr->typekind) {
case TKIND_ENUM:
/* force the return type to be VT_I4 */
tdesc = &i4_tdesc;
if (pVarResult) {
for (i = 0; i < func_desc->cParams; i++) {
USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
if (wParamFlags & PARAMFLAG_FRETVAL) {
ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
TYPEDESC *tdesc = &elemdesc->tdesc;
VARIANTARG varresult;
V_VT(&varresult) = 0;
hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
if (hres)
break;
case TKIND_ALIAS:
TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
tdesc = &(tattr->tdescAlias);
break;
case TKIND_INTERFACE:
FIXME("TKIND_INTERFACE unhandled.\n");
break;
case TKIND_DISPATCH:
FIXME("TKIND_DISPATCH unhandled.\n");
break;
case TKIND_RECORD:
FIXME("TKIND_RECORD unhandled.\n");
break;
default:
FIXME("TKIND %d unhandled.\n",tattr->typekind);
break;
}
ITypeInfo_Release(tinfo2);
/* FIXME: this is really messy - we should keep the
* args in VARIANTARGs rather than a DWORD array */
memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
if (TRACE_ON(ole))
{
TRACE("varresult: ");
dump_Variant(&varresult);
}
hres = VariantCopyInd(pVarResult, &varresult);
break;
}
V_VT(pVarResult) = tdesc->vt;
/* HACK: VB5 likes this.
* I do not know why. There is 1 example in MSDN which uses
* this which appears broken (mixes int vals and
* IDispatch*.).
*/
if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
V_VT(pVarResult) = VT_DISPATCH;
TRACE("storing into variant:\n");
dump_Variant(pVarResult);
args2pos += arglen;
}
}
if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
WARN("invoked function failed with error 0x%08lx\n", res);
hres = DISP_E_EXCEPTION;
if (pExcepInfo) pExcepInfo->scode = res;
}
func_fail:
HeapFree(GetProcessHeap(), 0, rgvarg);
HeapFree(GetProcessHeap(),0,args2);

View file

@ -157,17 +157,19 @@ typedef struct tagMSFT_TypeInfoBase {
/* else it is zero? */
INT res18; /* always? 0 */
/*060*/ INT res19; /* always? -1 */
} MSFT_TypeInfoBase;
} MSFT_TypeInfoBase;
/* layout of an entry with information on imported types */
typedef struct tagMSFT_ImpInfo {
INT res0; /* bits 0 - 15: count */
INT flags; /* 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;
} MSFT_ImpInfo;
#define MSFT_IMPINFO_OFFSET_IS_GUID 0x00010000
/* function description data */
typedef struct {

View file

@ -80,7 +80,7 @@ QueryPathOfRegTypeLib16(
{
char xguid[80];
char typelibkey[100],pathname[260];
DWORD plen;
LONG plen;
TRACE("\n");

View file

@ -148,7 +148,7 @@ typedef struct tagICreateTypeLib2Impl
const ICreateTypeLib2Vtbl *lpVtbl;
const ITypeLib2Vtbl *lpVtblTypeLib2;
ULONG ref;
LONG ref;
WCHAR *filename;
@ -174,7 +174,7 @@ typedef struct tagICreateTypeInfo2Impl
const ICreateTypeInfo2Vtbl *lpVtbl;
const ITypeInfo2Vtbl *lpVtblTypeInfo2;
ULONG ref;
LONG ref;
ICreateTypeLib2Impl *typelib;
MSFT_TypeInfoBase *typeinfo;
@ -1242,7 +1242,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface, U
guidoffset = ctl2_alloc_guid(This->typelib, &foo);
if (guidoffset == -1) return E_OUTOFMEMORY;
impinfo.res0 = 0x03010000;
impinfo.flags = TKIND_INTERFACE << 24 | MSFT_IMPINFO_OFFSET_IS_GUID;
impinfo.oImpFile = fileoffset;
impinfo.oGuid = guidoffset;
ctl2_alloc_importinfo(This->typelib, &impinfo);

View file

@ -82,7 +82,6 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
{
HRESULT res = DISP_E_TYPEMISMATCH;
VARTYPE vtFrom = V_TYPE(ps);
BOOL bIgnoreOverflow = FALSE;
DWORD dwFlags = 0;
TRACE("(%p->(%s%s),0x%08lx,0x%04x,%p->(%s%s),%s%s)\n", pd, debugstr_VT(pd),
@ -117,11 +116,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
if (vtFrom == VT_INT)
vtFrom = VT_I4;
else if (vtFrom == VT_UINT)
{
vtFrom = VT_UI4;
if (vt == VT_I4)
bIgnoreOverflow = TRUE;
}
if (vt == vtFrom)
return VariantCopy(pd, ps);
@ -155,7 +150,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_EMPTY: V_I1(pd) = 0; return S_OK;
case VT_I2: return VarI1FromI2(V_I2(ps), &V_I1(pd));
case VT_I4: return VarI1FromI4(V_I4(ps), &V_I1(pd));
case VT_UI1: return VarI1FromUI1(V_UI1(ps), &V_I1(pd));
case VT_UI1: V_I1(pd) = V_UI1(ps); return S_OK;
case VT_UI2: return VarI1FromUI2(V_UI2(ps), &V_I1(pd));
case VT_UI4: return VarI1FromUI4(V_UI4(ps), &V_I1(pd));
case VT_I8: return VarI1FromI8(V_I8(ps), &V_I1(pd));
@ -178,7 +173,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_I1: return VarI2FromI1(V_I1(ps), &V_I2(pd));
case VT_I4: return VarI2FromI4(V_I4(ps), &V_I2(pd));
case VT_UI1: return VarI2FromUI1(V_UI1(ps), &V_I2(pd));
case VT_UI2: return VarI2FromUI2(V_UI2(ps), &V_I2(pd));
case VT_UI2: V_I2(pd) = V_UI2(ps); return S_OK;
case VT_UI4: return VarI2FromUI4(V_UI4(ps), &V_I2(pd));
case VT_I8: return VarI2FromI8(V_I8(ps), &V_I2(pd));
case VT_UI8: return VarI2FromUI8(V_UI8(ps), &V_I2(pd));
@ -201,14 +196,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_I2: return VarI4FromI2(V_I2(ps), &V_I4(pd));
case VT_UI1: return VarI4FromUI1(V_UI1(ps), &V_I4(pd));
case VT_UI2: return VarI4FromUI2(V_UI2(ps), &V_I4(pd));
case VT_UI4:
if (bIgnoreOverflow)
{
V_VT(pd) = VT_I4;
V_I4(pd) = V_I4(ps);
return S_OK;
}
return VarI4FromUI4(V_UI4(ps), &V_I4(pd));
case VT_UI4: V_I4(pd) = V_UI4(ps); return S_OK;
case VT_I8: return VarI4FromI8(V_I8(ps), &V_I4(pd));
case VT_UI8: return VarI4FromUI8(V_UI8(ps), &V_I4(pd));
case VT_R4: return VarI4FromR4(V_R4(ps), &V_I4(pd));
@ -226,7 +214,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
switch (vtFrom)
{
case VT_EMPTY: V_UI1(pd) = 0; return S_OK;
case VT_I1: return VarUI1FromI1(V_I1(ps), &V_UI1(pd));
case VT_I1: V_UI1(pd) = V_I1(ps); return S_OK;
case VT_I2: return VarUI1FromI2(V_I2(ps), &V_UI1(pd));
case VT_I4: return VarUI1FromI4(V_I4(ps), &V_UI1(pd));
case VT_UI2: return VarUI1FromUI2(V_UI2(ps), &V_UI1(pd));
@ -249,7 +237,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
{
case VT_EMPTY: V_UI2(pd) = 0; return S_OK;
case VT_I1: return VarUI2FromI1(V_I1(ps), &V_UI2(pd));
case VT_I2: return VarUI2FromI2(V_I2(ps), &V_UI2(pd));
case VT_I2: V_UI2(pd) = V_I2(ps); return S_OK;
case VT_I4: return VarUI2FromI4(V_I4(ps), &V_UI2(pd));
case VT_UI1: return VarUI2FromUI1(V_UI1(ps), &V_UI2(pd));
case VT_UI4: return VarUI2FromUI4(V_UI4(ps), &V_UI2(pd));
@ -272,7 +260,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_EMPTY: V_UI4(pd) = 0; return S_OK;
case VT_I1: return VarUI4FromI1(V_I1(ps), &V_UI4(pd));
case VT_I2: return VarUI4FromI2(V_I2(ps), &V_UI4(pd));
case VT_I4: return VarUI4FromI4(V_I4(ps), &V_UI4(pd));
case VT_I4: V_UI4(pd) = V_I4(ps); return S_OK;
case VT_UI1: return VarUI4FromUI1(V_UI1(ps), &V_UI4(pd));
case VT_UI2: return VarUI4FromUI2(V_UI2(ps), &V_UI4(pd));
case VT_I8: return VarUI4FromI8(V_I8(ps), &V_UI4(pd));
@ -298,7 +286,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_UI1: return VarUI8FromUI1(V_UI1(ps), &V_UI8(pd));
case VT_UI2: return VarUI8FromUI2(V_UI2(ps), &V_UI8(pd));
case VT_UI4: return VarUI8FromUI4(V_UI4(ps), &V_UI8(pd));
case VT_I8: return VarUI8FromI8(V_I8(ps), &V_UI8(pd));
case VT_I8: V_UI8(pd) = V_I8(ps); return S_OK;
case VT_R4: return VarUI8FromR4(V_R4(ps), &V_UI8(pd));
case VT_R8: return VarUI8FromR8(V_R8(ps), &V_UI8(pd));
case VT_DATE: return VarUI8FromDate(V_DATE(ps), &V_UI8(pd));
@ -320,7 +308,7 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags,
case VT_UI1: return VarI8FromUI1(V_UI1(ps), &V_I8(pd));
case VT_UI2: return VarI8FromUI2(V_UI2(ps), &V_I8(pd));
case VT_UI4: return VarI8FromUI4(V_UI4(ps), &V_I8(pd));
case VT_UI8: return VarI8FromUI8(V_I8(ps), &V_I8(pd));
case VT_UI8: V_I8(pd) = V_UI8(ps); return S_OK;
case VT_R4: return VarI8FromR4(V_R4(ps), &V_I8(pd));
case VT_R8: return VarI8FromR8(V_R8(ps), &V_I8(pd));
case VT_DATE: return VarI8FromDate(V_DATE(ps), &V_I8(pd));
@ -2443,6 +2431,17 @@ VarNumFromParseNum_DecOverflow:
/**********************************************************************
* VarCat [OLEAUT32.318]
*
* Concatenates one variant onto another.
*
* 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.
*/
HRESULT WINAPI VarCat(LPVARIANT left, LPVARIANT right, LPVARIANT out)
{
@ -2638,6 +2637,16 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
/**********************************************************************
* VarAnd [OLEAUT32.142]
*
* Computes the logical AND of 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.
*/
HRESULT WINAPI VarAnd(LPVARIANT left, LPVARIANT right, LPVARIANT result)
{
@ -3073,6 +3082,16 @@ end:
/**********************************************************************
* VarDiv [OLEAUT32.143]
*
* Divides one variant with another.
*
* 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.
*/
HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
{
@ -3132,6 +3151,16 @@ HRESULT WINAPI VarDiv(LPVARIANT left, LPVARIANT right, LPVARIANT result)
/**********************************************************************
* VarSub [OLEAUT32.159]
*
* Subtract 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.
*/
HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result)
{
@ -4528,6 +4557,16 @@ HRESULT WINAPI VarMod(LPVARIANT left, LPVARIANT right, LPVARIANT result)
/**********************************************************************
* VarPow [OLEAUT32.158]
*
* Computes the power of one variant to another variant.
*
* 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.
*/
HRESULT WINAPI VarPow(LPVARIANT left, LPVARIANT right, LPVARIANT result)
{

View file

@ -5258,6 +5258,19 @@ static HRESULT VARIANT_BstrFromReal(DOUBLE dblIn, LCID lcid, ULONG dwFlags,
return E_INVALIDARG;
sprintfW( buff, lpszFormat, dblIn );
/* Negative zeroes are disallowed (some applications depend on this).
If buff starts with a minus, and then nothing follows but zeroes
and/or a period, it is a negative zero and is replaced with a
canonical zero. This duplicates native oleaut32 behavior.
*/
if (buff[0] == '-')
{
const WCHAR szAccept[] = {'0', '.', '\0'};
if (strlenW(buff + 1) == strspnW(buff + 1, szAccept))
{ buff[0] = '0'; buff[1] = '\0'; }
}
TRACE("created string %s\n", debugstr_w(buff));
if (dwFlags & LOCALE_USE_NLS)
{