diff --git a/reactos/doc/README.WINE b/reactos/doc/README.WINE index 15ce553dea9..340f4266784 100644 --- a/reactos/doc/README.WINE +++ b/reactos/doc/README.WINE @@ -45,7 +45,7 @@ reactos/lib/msacm # Out of sync reactos/lib/msvidoe # Out of sync reactos/lib/odbc32 # In sync. Depends on port of Linux ODBC. reactos/lib/ole32 # Synced to Wine-20041019 -reactos/lib/oleaut32 # Out of sync +reactos/lib/oleaut32 # Synced to Wine-20041202 reactos/lib/oledlg # Synced to Wine-20041019 reactos/lib/oldpro32 # Out of sync reactos/lib/richedit # Synced to Wine-20041019 diff --git a/reactos/lib/oleaut32/.cvsignore b/reactos/lib/oleaut32/.cvsignore index 54e5f606adb..2aa8b6adb56 100644 --- a/reactos/lib/oleaut32/.cvsignore +++ b/reactos/lib/oleaut32/.cvsignore @@ -1,8 +1,9 @@ *.coff *.dll -*.sym -*.o *.d +*.a +*.o +*.sym *.map *.tmp Makefile.ros diff --git a/reactos/lib/oleaut32/Makefile.in b/reactos/lib/oleaut32/Makefile.in index 815b49206d7..428c9e85356 100644 --- a/reactos/lib/oleaut32/Makefile.in +++ b/reactos/lib/oleaut32/Makefile.in @@ -6,10 +6,7 @@ VPATH = @srcdir@ MODULE = oleaut32.dll IMPORTS = ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll DELAYIMPORTS = comctl32 -ALTNAMES = ole2disp.dll typelib.dll -EXTRALIBS = $(LIBUNICODE) -luuid @GIFLIB@ @JPEGLIB@ - -SPEC_SRCS16 = $(ALTNAMES:.dll=.spec) +EXTRALIBS = $(LIBUNICODE) -luuid C_SRCS = \ connpt.c \ @@ -34,6 +31,10 @@ C_SRCS16 = \ ole2disp.c \ typelib16.c +SPEC_SRCS16 = \ + ole2disp.spec \ + typelib.spec + RC_SRCS = oleaut32.rc SUBDIRS = tests diff --git a/reactos/lib/oleaut32/connpt.c b/reactos/lib/oleaut32/connpt.c index e6bf0987151..5cc49c57984 100644 --- a/reactos/lib/oleaut32/connpt.c +++ b/reactos/lib/oleaut32/connpt.c @@ -25,6 +25,9 @@ #include #include #include + +#define COBJMACROS + #include "winerror.h" #include "windef.h" #include "winbase.h" @@ -194,9 +197,7 @@ static ULONG WINAPI ConnectionPointImpl_AddRef(IConnectionPoint* iface) { ConnectionPointImpl *This = (ConnectionPointImpl *)iface; TRACE("(%p)->(ref=%ld)\n", This, This->ref); - This->ref++; - - return This->ref; + return InterlockedIncrement(&This->ref); } /************************************************************************ @@ -208,24 +209,20 @@ static ULONG WINAPI ConnectionPointImpl_Release( IConnectionPoint* iface) { ConnectionPointImpl *This = (ConnectionPointImpl *)iface; + ULONG ref; TRACE("(%p)->(ref=%ld)\n", This, This->ref); /* * Decrease the reference count on this object. */ - This->ref--; + ref = InterlockedDecrement(&This->ref); /* * If the reference count goes down to 0, perform suicide. */ - if (This->ref==0) - { - ConnectionPointImpl_Destroy(This); + if (ref == 0) ConnectionPointImpl_Destroy(This); - return 0; - } - - return This->ref; + return ref; } /************************************************************************ @@ -473,10 +470,11 @@ static HRESULT WINAPI EnumConnectionsImpl_QueryInterface( static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface) { EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface; + ULONG ref; TRACE("(%p)->(ref=%ld)\n", This, This->ref); - This->ref++; + ref = InterlockedIncrement(&This->ref); IUnknown_AddRef(This->pUnk); - return This->ref; + return ref; } /************************************************************************ @@ -487,6 +485,7 @@ static ULONG WINAPI EnumConnectionsImpl_AddRef(IEnumConnections* iface) static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface) { EnumConnectionsImpl *This = (EnumConnectionsImpl *)iface; + ULONG ref; TRACE("(%p)->(ref=%ld)\n", This, This->ref); IUnknown_Release(This->pUnk); @@ -494,19 +493,14 @@ static ULONG WINAPI EnumConnectionsImpl_Release(IEnumConnections* iface) /* * Decrease the reference count on this object. */ - This->ref--; + ref = InterlockedDecrement(&This->ref); /* * If the reference count goes down to 0, perform suicide. */ - if (This->ref==0) - { - EnumConnectionsImpl_Destroy(This); + if (ref == 0) EnumConnectionsImpl_Destroy(This); - return 0; - } - - return This->ref; + return ref; } /************************************************************************ diff --git a/reactos/lib/oleaut32/dispatch.c b/reactos/lib/oleaut32/dispatch.c index 5e0ca90917d..a3ce7440ece 100644 --- a/reactos/lib/oleaut32/dispatch.c +++ b/reactos/lib/oleaut32/dispatch.c @@ -28,6 +28,8 @@ #include #include +#define COBJMACROS + #include "windef.h" #include "winbase.h" #include "objbase.h" @@ -180,28 +182,6 @@ HRESULT WINAPI CreateStdDispatch( return S_OK; } -/****************************************************************************** - * CreateDispTypeInfo [OLEAUT32.31] - * - * Build type information for an object so it can be called through an - * IDispatch interface. - * - * RETURNS - * Success: S_OK. pptinfo contains the created ITypeInfo object. - * Failure: E_INVALIDARG, if one or more arguments is invalid. - * - * NOTES - * This call allows an objects methods to be accessed through IDispatch, by - * building an ITypeInfo object that IDispatch can use to call through. - */ -HRESULT WINAPI CreateDispTypeInfo( - INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */ - LCID lcid, /* [I] Locale Id */ - ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ -{ - FIXME("(%p,%ld,%p),stub\n",pidata,lcid,pptinfo); - return 0; -} /****************************************************************************** * IDispatch {OLEAUT32} @@ -278,7 +258,7 @@ static ULONG WINAPI StdDispatch_AddRef(LPDISPATCH iface) StdDispatch *This = (StdDispatch *)iface; TRACE("()\n"); - return ++This->ref; + return InterlockedIncrement(&This->ref); } /****************************************************************************** @@ -289,18 +269,18 @@ static ULONG WINAPI StdDispatch_AddRef(LPDISPATCH iface) static ULONG WINAPI StdDispatch_Release(LPDISPATCH iface) { StdDispatch *This = (StdDispatch *)iface; - ULONG ret; + ULONG ref; TRACE("(%p)->()\n", This); - ret = This->ref--; + ref = InterlockedDecrement(&This->ref); - if (This->ref == 0) + if (ref == 0) { ITypeInfo_Release(This->pTypeInfo); CoTaskMemFree(This); } - return ret; + return ref; } /****************************************************************************** diff --git a/reactos/lib/oleaut32/hash.c b/reactos/lib/oleaut32/hash.c index 3bb524ebe6d..ce2f0e41232 100644 --- a/reactos/lib/oleaut32/hash.c +++ b/reactos/lib/oleaut32/hash.c @@ -23,6 +23,7 @@ #include "windef.h" #include "winbase.h" #include "winnls.h" +#include "objbase.h" #include "oaidl.h" #include "wine/debug.h" @@ -537,9 +538,7 @@ ULONG WINAPI LHashValOfNameSysA( SYSKIND skind, LCID lcid, LPCSTR lpStr) case LANG_SWEDISH: case LANG_SYRIAC: case LANG_TAMIL: case LANG_TATAR: case LANG_TELUGU: case LANG_THAI: case LANG_UKRAINIAN: case LANG_URDU: case LANG_UZBEK: - case LANG_VIETNAMESE: -#ifndef __REACTOS__ /* non standard languages */ - case LANG_GAELIC: case LANG_MALTESE: + case LANG_VIETNAMESE: case LANG_GAELIC: case LANG_MALTESE: case LANG_MAORI: case LANG_RHAETO_ROMANCE: case LANG_SAAMI: case LANG_SORBIAN: case LANG_SUTU: case LANG_TSONGA: case LANG_TSWANA: case LANG_VENDA: @@ -549,7 +548,6 @@ ULONG WINAPI LHashValOfNameSysA( SYSKIND skind, LCID lcid, LPCSTR lpStr) nOffset = 16; pnLookup = Lookup_16; break; -#endif /* __REACTOS__ */ case LANG_CZECH: case LANG_HUNGARIAN: case LANG_POLISH: case LANG_SLOVAK: case LANG_SPANISH: nOffset = 32; diff --git a/reactos/lib/oleaut32/oaidl_p.c b/reactos/lib/oleaut32/oaidl_p.c index cb2c46456e8..541056f8ebb 100644 --- a/reactos/lib/oleaut32/oaidl_p.c +++ b/reactos/lib/oleaut32/oaidl_p.c @@ -28,6 +28,8 @@ #include +#define COBJMACROS + #include "windef.h" #include "winbase.h" #include "objbase.h" diff --git a/reactos/lib/oleaut32/oleaut.c b/reactos/lib/oleaut32/oleaut.c index eb1298b9202..901c603fa20 100644 --- a/reactos/lib/oleaut32/oleaut.c +++ b/reactos/lib/oleaut32/oleaut.c @@ -21,6 +21,8 @@ #include #include +#define COBJMACROS + #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -47,7 +49,6 @@ static BOOL BSTR_bCache = TRUE; /* Cache allocations to minimise alloc calls? */ HMODULE OLEAUT32_hModule = NULL; - /****************************************************************************** * BSTR {OLEAUT32} * @@ -569,6 +570,28 @@ ULONG WINAPI OaBuildVersion() } } +/****************************************************************************** + * GetRecordInfoFromGuids [OLEAUT32.322] + * + * RETURNS + * Success: S_OK + * Failure: E_INVALIDARG, if any argument is invalid. + * + * BUGS + * Unimplemented + */ +HRESULT WINAPI GetRecordInfoFromGuids( + REFGUID rGuidTypeLib, + ULONG uVerMajor, + ULONG uVerMinor, + LCID lcid, + REFGUID rGuidTypeInfo, + IRecordInfo** ppRecInfo) +{ + FIXME("(%p,%ld,%ld,%ld,%p,%p),stub!\n",rGuidTypeLib, uVerMajor, uVerMinor, lcid, rGuidTypeInfo, ppRecInfo); + return E_NOTIMPL; +} + /****************************************************************************** * OleTranslateColor [OLEAUT32.421] * @@ -644,7 +667,7 @@ HRESULT WINAPI OleTranslateColor( /* * Validate GetSysColor index. */ - if ((index < COLOR_SCROLLBAR) || (index > COLOR_GRADIENTINACTIVECAPTION)) + if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR)) return E_INVALIDARG; *pColorRef = GetSysColor(index); @@ -667,7 +690,6 @@ extern void _get_STDPIC_CF(LPVOID); /*********************************************************************** * DllGetClassObject (OLEAUT32.1) */ -#ifndef __REACTOS__ /*FIXME: no marshalling yet*/ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) { *ppv = NULL; @@ -696,7 +718,6 @@ HRESULT WINAPI OLEAUT32_DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *p FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE; } -#endif /*********************************************************************** * DllCanUnloadNow (OLEAUT32.410) @@ -709,7 +730,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() +HRESULT WINAPI OLEAUT32_DllCanUnloadNow(void) { return S_FALSE; } diff --git a/reactos/lib/oleaut32/oleaut32.rc b/reactos/lib/oleaut32/oleaut32.rc index 500cf104976..fcff4f6e541 100644 --- a/reactos/lib/oleaut32/oleaut32.rc +++ b/reactos/lib/oleaut32/oleaut32.rc @@ -34,13 +34,14 @@ #include "oleaut32_It.rc" #include "oleaut32_Nl.rc" #include "oleaut32_No.rc" +#include "oleaut32_Pl.rc" #include "oleaut32_Pt.rc" #include "oleaut32_Sv.rc" #include "oleaut32_Th.rc" /* * FIXME: - * Polish, Finnish, Greek, Hebrew, Japanese, Korean, Portuguese, + * Finnish, Greek, Hebrew, Japanese, Korean, Portuguese, * Russian, Turkish, Slovenian (at least) are localised in XP Home. * I expect Chinese etc are localised in Asian Editions also. */ diff --git a/reactos/lib/oleaut32/oleaut32.spec b/reactos/lib/oleaut32/oleaut32.spec index 5455a3dada3..e9abcc769a6 100644 --- a/reactos/lib/oleaut32/oleaut32.spec +++ b/reactos/lib/oleaut32/oleaut32.spec @@ -1,4 +1,4 @@ -#1 stdcall -private DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject +1 stdcall -private DllGetClassObject(ptr ptr ptr) OLEAUT32_DllGetClassObject 2 stdcall SysAllocString(wstr) 3 stdcall SysReAllocString(ptr wstr) 4 stdcall SysAllocStringLen(wstr long) @@ -142,12 +142,12 @@ 142 stdcall VarAnd(ptr ptr ptr) 143 stdcall VarDiv(ptr ptr ptr) 144 stub OACreateTypeLib2 -#146 stdcall DispCallFunc(ptr long long long long ptr ptr ptr) +146 stdcall DispCallFunc(ptr long long long long ptr ptr ptr) 147 stdcall VariantChangeTypeEx(ptr ptr long long long) 148 stdcall SafeArrayPtrOfIndex(ptr ptr ptr) 149 stdcall SysStringByteLen(ptr) 150 stdcall SysAllocStringByteLen(ptr long) -152 stub VarEqv # stdcall (ptr ptr ptr) +152 stdcall VarEqv(ptr ptr ptr) 153 stub VarIdiv # stdcall (ptr ptr ptr) 154 stub VarImp # stdcall (ptr ptr ptr) 155 stdcall VarMod(ptr ptr ptr) @@ -155,18 +155,18 @@ 157 stdcall VarOr(ptr ptr ptr) 158 stdcall VarPow(ptr ptr ptr) 159 stdcall VarSub(ptr ptr ptr) -#160 stdcall CreateTypeLib(long wstr ptr) -#161 stdcall LoadTypeLib (wstr ptr) -#162 stdcall LoadRegTypeLib (ptr long long long ptr) -#163 stdcall RegisterTypeLib(ptr wstr wstr) -#164 stdcall QueryPathOfRegTypeLib(ptr long long long ptr) +160 stdcall CreateTypeLib(long wstr ptr) +161 stdcall LoadTypeLib (wstr ptr) +162 stdcall LoadRegTypeLib (ptr long long long ptr) +163 stdcall RegisterTypeLib(ptr wstr wstr) +164 stdcall QueryPathOfRegTypeLib(ptr long long long ptr) 165 stdcall LHashValOfNameSys(long long wstr) 166 stdcall LHashValOfNameSysA(long long str) -167 stub VarXor # stdcall (ptr ptr ptr) +167 stdcall VarXor(ptr ptr ptr) 168 stdcall VarAbs(ptr ptr) 169 stdcall VarFix(ptr ptr) 170 stdcall OaBuildVersion() -171 stub ClearCustData +171 stdcall ClearCustData(ptr) 172 stdcall VarInt(ptr ptr) 173 stdcall VarNeg(ptr ptr) 174 stdcall VarNot(ptr ptr) @@ -175,13 +175,13 @@ 177 stdcall VarDecAdd(ptr ptr ptr) 178 stdcall VarDecDiv(ptr ptr ptr) 179 stdcall VarDecMul(ptr ptr ptr) -#180 stdcall CreateTypeLib2(long wstr ptr) +180 stdcall CreateTypeLib2(long wstr ptr) 181 stdcall VarDecSub(ptr ptr ptr) 182 stdcall VarDecAbs(ptr ptr) -#183 stdcall LoadTypeLibEx (wstr long ptr) +183 stdcall LoadTypeLibEx (wstr long ptr) 184 stdcall SystemTimeToVariantTime(ptr ptr) 185 stdcall VariantTimeToSystemTime(double ptr) -#186 stdcall UnRegisterTypeLib (ptr long long long long) +186 stdcall UnRegisterTypeLib (ptr long long long long) 187 stdcall VarDecFix(ptr ptr) 188 stdcall VarDecInt(ptr ptr) 189 stdcall VarDecNeg(ptr ptr) @@ -278,14 +278,14 @@ 280 stdcall VarUI4FromI1(long ptr) 281 stdcall VarUI4FromUI2(long ptr) 282 stdcall VarUI4FromDec(ptr ptr) -#283 stdcall BSTR_UserSize(ptr long ptr) -#284 stdcall BSTR_UserMarshal(ptr ptr ptr) -#285 stdcall BSTR_UserUnmarshal(ptr ptr ptr) -#286 stdcall BSTR_UserFree(ptr ptr) -#287 stdcall VARIANT_UserSize(ptr long ptr) -#288 stdcall VARIANT_UserMarshal(ptr ptr ptr) -#289 stdcall VARIANT_UserUnmarshal(ptr ptr ptr) -#290 stdcall VARIANT_UserFree(ptr ptr) +283 stdcall BSTR_UserSize(ptr long ptr) +284 stdcall BSTR_UserMarshal(ptr ptr ptr) +285 stdcall BSTR_UserUnmarshal(ptr ptr ptr) +286 stdcall BSTR_UserFree(ptr ptr) +287 stdcall VARIANT_UserSize(ptr long ptr) +288 stdcall VARIANT_UserMarshal(ptr ptr ptr) +289 stdcall VARIANT_UserUnmarshal(ptr ptr ptr) +290 stdcall VARIANT_UserFree(ptr ptr) 291 stub LPSAFEARRAY_UserSize 292 stub LPSAFEARRAY_UserMarshal 293 stub LPSAFEARRAY_UserUnmarshal @@ -311,10 +311,10 @@ 316 stdcall VarR4CmpR8(long double) 317 stdcall VarR8Round(double long ptr) 318 stdcall VarCat(ptr ptr ptr) -319 stub VarDateFromUdateEx # stdcall (ptr long long ptr) -#320 stdcall -private DllRegisterServer() OLEAUT32_DllRegisterServer -#321 stdcall -private DllUnregisterServer() OLEAUT32_DllUnregisterServer -322 stub GetRecordInfoFromGuids # stdcall (ptr long long long ptr ptr) +319 stdcall VarDateFromUdateEx(ptr long long ptr) +320 stdcall -private DllRegisterServer() OLEAUT32_DllRegisterServer +321 stdcall -private DllUnregisterServer() OLEAUT32_DllUnregisterServer +322 stdcall GetRecordInfoFromGuids(ptr long long long ptr ptr) 323 stub GetRecordInfoFromTypeInfo # stdcall (ptr ptr) 325 stub SetVarConversionLocaleSetting 326 stub GetVarConversionLocaleSetting @@ -392,7 +392,7 @@ 417 stdcall OleCreatePropertyFrame(ptr long long ptr long ptr long ptr ptr long ptr) 418 stdcall OleLoadPicture(ptr long long ptr ptr) 419 stdcall OleCreatePictureIndirect(ptr ptr long ptr) -#420 stdcall OleCreateFontIndirect(ptr ptr ptr) +420 stdcall OleCreateFontIndirect(ptr ptr ptr) 421 stdcall OleTranslateColor(long long long) 422 stub OleLoadPictureFile 423 stub OleSavePictureFile diff --git a/reactos/lib/oleaut32/oleaut32_De.rc b/reactos/lib/oleaut32/oleaut32_De.rc index 5b177846681..711a310213d 100644 --- a/reactos/lib/oleaut32/oleaut32_De.rc +++ b/reactos/lib/oleaut32/oleaut32_De.rc @@ -25,7 +25,7 @@ STRINGTABLE DISCARDABLE IDS_TRUE "Wahr" IDS_FALSE "Falsch" IDS_YES "Ja" - IDS_NO "Nei" + IDS_NO "Nein" IDS_ON "Ein" IDS_OFF "Aus" } diff --git a/reactos/lib/oleaut32/oleaut32_Pl.rc b/reactos/lib/oleaut32/oleaut32_Pl.rc new file mode 100644 index 00000000000..92b453c5b14 --- /dev/null +++ b/reactos/lib/oleaut32/oleaut32_Pl.rc @@ -0,0 +1,32 @@ +/* + * Polish resources for oleaut32 + * + * Copyright 2003 Jon Griffiths + * Copyright 2004 Jacek Caban + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +LANGUAGE LANG_POLISH, SUBLANG_DEFAULT + +STRINGTABLE DISCARDABLE +{ + IDS_TRUE "Prawda" + IDS_FALSE "Fałsz" + IDS_YES "Tak" + IDS_NO "Nie" + IDS_ON "Włączone" + IDS_OFF "Wyłączone" +} diff --git a/reactos/lib/oleaut32/olefont.c b/reactos/lib/oleaut32/olefont.c index dc888b03300..0823feee766 100644 --- a/reactos/lib/oleaut32/olefont.c +++ b/reactos/lib/oleaut32/olefont.c @@ -101,7 +101,7 @@ struct OLEFontImpl /* * Here, I define utility macros to help with the casting of the * "this" parameter. - * There is a version to accomodate all of the VTables implemented + * There is a version to accommodate all of the VTables implemented * by this object. */ #define _ICOM_THIS_From_IDispatch(class, name) class* this = (class*)(((char*)name)-sizeof(void*)) @@ -139,7 +139,7 @@ static HRESULT WINAPI OLEFontImpl_put_Charset(IFont* iface, short charset); static HRESULT WINAPI OLEFontImpl_get_hFont(IFont* iface, HFONT* phfont); static HRESULT WINAPI OLEFontImpl_Clone(IFont* iface, IFont** ppfont); static HRESULT WINAPI OLEFontImpl_IsEqual(IFont* iface, IFont* pFontOther); -static HRESULT WINAPI OLEFontImpl_SetRatio(IFont* iface, long cyLogical, long cyHimetric); +static HRESULT WINAPI OLEFontImpl_SetRatio(IFont* iface, LONG cyLogical, LONG cyHimetric); static HRESULT WINAPI OLEFontImpl_QueryTextMetrics(IFont* iface, TEXTMETRICOLE* ptm); static HRESULT WINAPI OLEFontImpl_AddRefHfont(IFont* iface, HFONT hfont); static HRESULT WINAPI OLEFontImpl_ReleaseHfont(IFont* iface, HFONT hfont); @@ -1048,8 +1048,8 @@ static HRESULT WINAPI OLEFontImpl_IsEqual( */ static HRESULT WINAPI OLEFontImpl_SetRatio( IFont* iface, - long cyLogical, - long cyHimetric) + LONG cyLogical, + LONG cyHimetric) { OLEFontImpl *this = (OLEFontImpl *)iface; TRACE("(%p)->(%ld, %ld)\n", this, cyLogical, cyHimetric); @@ -1210,7 +1210,7 @@ static HRESULT WINAPI OLEFontImpl_GetTypeInfo( HRESULT hres; _ICOM_THIS_From_IDispatch(OLEFontImpl, iface); - TRACE("(%p, iTInfo=%d, lcid=%04x, %p), unimplemented stub!\n", this, iTInfo, (int)lcid, ppTInfo); + TRACE("(%p, iTInfo=%d, lcid=%04x, %p)\n", this, iTInfo, (int)lcid, ppTInfo); if (iTInfo != 0) return E_FAIL; hres = LoadTypeLib(stdole32tlb, &tl); @@ -1276,11 +1276,36 @@ static HRESULT WINAPI OLEFontImpl_Invoke( V_VT(pVarResult) = VT_BSTR; return OLEFontImpl_get_Name(this, &V_BSTR(pVarResult)); case DISPATCH_PROPERTYPUT: { - BSTR name = V_BSTR(&pDispParams->rgvarg[0]); - if (V_VT(&pDispParams->rgvarg[0])!=VT_BSTR) { - FIXME("property put of Name, vt is not VT_BSTR but %d\n",V_VT(&pDispParams->rgvarg[0])); - return E_FAIL; + BSTR name; + BOOL freename; + + if (V_VT(&pDispParams->rgvarg[0]) == VT_DISPATCH) { + IFont *font; + HRESULT hr = S_OK; + + hr = IUnknown_QueryInterface(V_DISPATCH(&pDispParams->rgvarg[0]), &IID_IFont, (void **) &font); + if (FAILED(hr)) + { + FIXME("dispatch value for name property is not an OleFont, returning hr=0x%lx\n", hr); + return hr; + } + + hr = IFont_get_Name(font, &name); /* this allocates a new BSTR so free it later */ + if (FAILED(hr)) return hr; + + IUnknown_Release(font); + + freename = TRUE; + } else if (V_VT(&pDispParams->rgvarg[0]) == VT_BSTR) { + name = V_BSTR(&pDispParams->rgvarg[0]); + freename = FALSE; + } else { + FIXME("app is trying to set name property with a non BSTR, non dispatch value. returning E_FAIL\n"); + return E_FAIL; } + + TRACE("name is %s\n", debugstr_w(name)); + if (!xthis->description.lpstrName) xthis->description.lpstrName = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(name)+1) * sizeof(WCHAR)); else @@ -1289,6 +1314,9 @@ static HRESULT WINAPI OLEFontImpl_Invoke( if (xthis->description.lpstrName==0) return E_OUTOFMEMORY; strcpyW(xthis->description.lpstrName, name); + + if (freename) SysFreeString(name); + return S_OK; } } diff --git a/reactos/lib/oleaut32/olepicture.c b/reactos/lib/oleaut32/olepicture.c index 94d66a32c25..6a99f5b1684 100644 --- a/reactos/lib/oleaut32/olepicture.c +++ b/reactos/lib/oleaut32/olepicture.c @@ -36,6 +36,7 @@ */ #include "config.h" +#include "wine/port.h" #ifdef HAVE_UNISTD_H # include @@ -49,10 +50,18 @@ */ #ifdef HAVE_GIF_LIB_H # include +# ifndef SONAME_LIBUNGIF +# define SONAME_LIBUNGIF "libungif.so" +# endif +# ifndef SONAME_LIBGIF +# define SONAME_LIBGIF "libgif.so" +# endif #endif +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "winerror.h" #include "windef.h" #include "winbase.h" @@ -67,16 +76,17 @@ #include "wine/wingdi16.h" #include "cursoricon.h" -#ifdef HAVE_LIBJPEG +#ifdef HAVE_JPEGLIB_H /* This is a hack, so jpeglib.h does not redefine INT32 and the like*/ #define XMD_H #define UINT8 JPEG_UINT8 #define UINT16 JPEG_UINT16 #undef FAR -#ifdef HAVE_JPEGLIB_H # include -#endif #undef UINT16 +#ifndef SONAME_LIBJPEG +#define SONAME_LIBJPEG "libjpeg.so" +#endif #endif WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -118,9 +128,16 @@ typedef struct OLEPictureImpl { BOOL keepOrigFormat; HDC hDCCur; + /* Bitmap transparency mask */ + HBITMAP hbmMask; + COLORREF rgbTrans; + /* data */ void* data; int datalen; + BOOL bIsDirty; /* Set to TRUE if picture has changed */ + unsigned int loadtime_magic; /* If a length header was found, saves value */ + unsigned int loadtime_format; /* for PICTYPE_BITMAP only, keeps track of image format (GIF/BMP/JPEG) */ } OLEPictureImpl; /* @@ -212,6 +229,11 @@ static OLEPictureImpl* OLEPictureImpl_Construct(LPPICTDESC pictDesc, BOOL fOwn) /* dunno about original value */ newObject->keepOrigFormat = TRUE; + newObject->hbmMask = NULL; + newObject->loadtime_magic = 0xdeadbeef; + newObject->loadtime_format = 0; + newObject->bIsDirty = FALSE; + if (pictDesc) { if(pictDesc->cbSizeofstruct != sizeof(PICTDESC)) { FIXME("struct size = %d\n", pictDesc->cbSizeofstruct); @@ -388,9 +410,7 @@ static ULONG WINAPI OLEPictureImpl_AddRef( { OLEPictureImpl *This = (OLEPictureImpl *)iface; TRACE("(%p)->(ref=%ld)\n", This, This->ref); - This->ref++; - - return This->ref; + return InterlockedIncrement(&This->ref); } /************************************************************************ @@ -402,24 +422,20 @@ static ULONG WINAPI OLEPictureImpl_Release( IPicture* iface) { OLEPictureImpl *This = (OLEPictureImpl *)iface; + ULONG ret; TRACE("(%p)->(ref=%ld)\n", This, This->ref); /* * Decrease the reference count on this object. */ - This->ref--; + ret = InterlockedDecrement(&This->ref); /* * If the reference count goes down to 0, perform suicide. */ - if (This->ref==0) - { - OLEPictureImpl_Destroy(This); + if (ret==0) OLEPictureImpl_Destroy(This); - return 0; - } - - return This->ref; + return ret; } @@ -503,7 +519,7 @@ static HRESULT WINAPI OLEPictureImpl_get_Height(IPicture *iface, * OLEPictureImpl_Render */ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc, - long x, long y, long cx, long cy, + LONG x, LONG y, LONG cx, LONG cy, OLE_XPOS_HIMETRIC xSrc, OLE_YPOS_HIMETRIC ySrc, OLE_XSIZE_HIMETRIC cxSrc, @@ -541,7 +557,25 @@ static HRESULT WINAPI OLEPictureImpl_Render(IPicture *iface, HDC hdc, hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap); - StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY); + if (This->hbmMask) { + HDC hdcMask = CreateCompatibleDC(0); + HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask); + + SetMapMode(hdcMask, MM_ANISOTROPIC); + SetWindowOrgEx(hdcMask, 0, 0, NULL); + SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL); + SetViewportOrgEx(hdcMask, 0, This->origHeight, NULL); + SetViewportExtEx(hdcMask, This->origWidth, -This->origHeight, NULL); + + SetBkColor(hdc, RGB(255, 255, 255)); + SetTextColor(hdc, RGB(0, 0, 0)); + StretchBlt(hdc, x, y, cx, cy, hdcMask, xSrc, ySrc, cxSrc, cySrc, SRCAND); + StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCPAINT); + + SelectObject(hdcMask, hOldbm); + DeleteDC(hdcMask); + } else + StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY); SelectObject(hdcBmp, hbmpOld); DeleteDC(hdcBmp); @@ -645,6 +679,7 @@ static HRESULT WINAPI OLEPictureImpl_PictureChanged(IPicture *iface) OLEPictureImpl *This = (OLEPictureImpl *)iface; TRACE("(%p)->()\n", This); OLEPicture_SendNotify(This,DISPID_PICT_HANDLE); + This->bIsDirty = TRUE; return S_OK; } @@ -787,7 +822,7 @@ static HRESULT WINAPI OLEPictureImpl_GetClassID( { ICOM_THIS_From_IPersistStream(IPicture, iface); FIXME("(%p),stub!\n",This); - return E_NOTIMPL; + return E_FAIL; } /************************************************************************ @@ -801,7 +836,41 @@ static HRESULT WINAPI OLEPictureImpl_IsDirty( return E_NOTIMPL; } -#ifdef HAVE_LIBJPEG +#ifdef HAVE_JPEGLIB_H + +static void *libjpeg_handle; +#define MAKE_FUNCPTR(f) static typeof(f) * p##f +MAKE_FUNCPTR(jpeg_std_error); +MAKE_FUNCPTR(jpeg_CreateDecompress); +MAKE_FUNCPTR(jpeg_read_header); +MAKE_FUNCPTR(jpeg_start_decompress); +MAKE_FUNCPTR(jpeg_read_scanlines); +MAKE_FUNCPTR(jpeg_finish_decompress); +MAKE_FUNCPTR(jpeg_destroy_decompress); +#undef MAKE_FUNCPTR + +static void *load_libjpeg(void) +{ + if((libjpeg_handle = wine_dlopen(SONAME_LIBJPEG, RTLD_NOW, NULL, 0)) != NULL) { + +#define LOAD_FUNCPTR(f) \ + if((p##f = wine_dlsym(libjpeg_handle, #f, NULL, 0)) == NULL) { \ + libjpeg_handle = NULL; \ + return NULL; \ + } + + LOAD_FUNCPTR(jpeg_std_error); + LOAD_FUNCPTR(jpeg_CreateDecompress); + LOAD_FUNCPTR(jpeg_read_header); + LOAD_FUNCPTR(jpeg_start_decompress); + LOAD_FUNCPTR(jpeg_read_scanlines); + LOAD_FUNCPTR(jpeg_finish_decompress); + LOAD_FUNCPTR(jpeg_destroy_decompress); +#undef LOAD_FUNCPTR + } + return libjpeg_handle; +} + /* for the jpeg decompressor source manager. */ static void _jpeg_init_source(j_decompress_ptr cinfo) { } @@ -821,15 +890,43 @@ static boolean _jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired) { return FALSE; } static void _jpeg_term_source(j_decompress_ptr cinfo) { } -#endif /* HAVE_LIBJPEG */ +#endif /* HAVE_JPEGLIB_H */ + +#ifdef HAVE_GIF_LIB_H + +static void *libungif_handle; +#define MAKE_FUNCPTR(f) static typeof(f) * p##f +MAKE_FUNCPTR(DGifOpen); +MAKE_FUNCPTR(DGifSlurp); +MAKE_FUNCPTR(DGifCloseFile); +#undef MAKE_FUNCPTR -#ifdef HAVE_LIBGIF struct gifdata { unsigned char *data; unsigned int curoff; unsigned int len; }; +static void *load_libungif(void) +{ + if(((libungif_handle = wine_dlopen(SONAME_LIBUNGIF, RTLD_NOW, NULL, 0)) != NULL) || + ((libungif_handle = wine_dlopen(SONAME_LIBGIF , RTLD_NOW, NULL, 0)) != NULL) + ) { + +#define LOAD_FUNCPTR(f) \ + if((p##f = wine_dlsym(libungif_handle, #f, NULL, 0)) == NULL) { \ + libungif_handle = NULL; \ + return NULL; \ + } + + LOAD_FUNCPTR(DGifOpen); + LOAD_FUNCPTR(DGifSlurp); + LOAD_FUNCPTR(DGifCloseFile); +#undef LOAD_FUNCPTR + } + return libungif_handle; +} + static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) { struct gifdata *gd = (struct gifdata*)gif->UserData; @@ -841,7 +938,8 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) { gd->curoff += len; return len; } -#endif + +#endif /* HAVE_GIF_LIB_H */ /************************************************************************ * OLEPictureImpl_IPersistStream_Load (IUnknown) @@ -851,7 +949,7 @@ static int _gif_inputfunc(GifFileType *gif, GifByteType *data, int len) { * DWORD magic; * DWORD len; * - * Currently implemented: BITMAP, ICON, JPEG. + * Currently implemented: BITMAP, ICON, JPEG, GIF */ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { HRESULT hr = E_FAIL; @@ -866,6 +964,13 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { /* Sometimes we have a header, sometimes we don't. Apply some guesses to find * out whether we do. + * + * UPDATE: the IStream can be mapped to a plain file instead of a stream in a + * compound file. This may explain most, if not all, of the cases of "no header", + * and the header validation should take this into account. At least in Visual Basic 6, + * resource streams, valid headers are + * header[0] == "lt\0\0", + * header[1] == length_of_stream. */ hr=IStream_Stat(pStm,&statstg,STATFLAG_NONAME); if (hr) @@ -875,7 +980,10 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { FIXME("Failure while reading picture header (hr is %lx, nread is %ld).\n",hr,xread); return hr; } - if (header[1] > statstg.cbSize.QuadPart || (header[1]==0)) {/* Incorrect header, assume none. */ + 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); @@ -906,7 +1014,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { magic = xbuf[0] + (xbuf[1]<<8); switch (magic) { case 0x4947: { /* GIF */ -#ifdef HAVE_LIBGIF +#ifdef HAVE_GIF_LIB_H struct gifdata gd; GifFileType *gif; BITMAPINFO *bmi; @@ -916,12 +1024,22 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { GifImageDesc *gid; SavedImage *si; ColorMapObject *cm; - + int transparent = -1; + ExtensionBlock *eb; + int padding; + + if(!libungif_handle) { + if(!load_libungif()) { + FIXME("Failed reading GIF because unable to find %s/%s\n", SONAME_LIBUNGIF, SONAME_LIBGIF); + return E_FAIL; + } + } + gd.data = xbuf; gd.curoff = 0; gd.len = xread; - gif = DGifOpen((void*)&gd, _gif_inputfunc); - ret = DGifSlurp(gif); + gif = pDGifOpen((void*)&gd, _gif_inputfunc); + ret = pDGifSlurp(gif); if (ret == GIF_ERROR) { FIXME("Failed reading GIF using libgif.\n"); return E_FAIL; @@ -939,28 +1057,69 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { gif->Image.Interlace ); /* */ + padding = (gif->SWidth+3) & ~3; bmi = HeapAlloc(GetProcessHeap(),0,sizeof(BITMAPINFOHEADER)+(1<SColorResolution)*sizeof(RGBQUAD)); - bytes= HeapAlloc(GetProcessHeap(),0,gif->SWidth*gif->SHeight); + bytes= HeapAlloc(GetProcessHeap(),0,padding*gif->SHeight); si = gif->SavedImages+0; gid = &(si->ImageDesc); cm = gid->ColorMap; if (!cm) cm = gif->SColorMap; + + /* look for the transparent color extension */ + for (i = 0; i < si->ExtensionBlockCount; ++i) { + eb = si->ExtensionBlocks + i; + if (eb->Function == 0xF9 && eb->ByteCount == 4) { + if ((eb->Bytes[0] & 1) == 1) { + transparent = eb->Bytes[3]; + } + } + } + for (i=0;i<(1<SColorResolution);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; + if (i == transparent) { + This->rgbTrans = RGB(bmi->bmiColors[i].rgbRed, + bmi->bmiColors[i].rgbGreen, + bmi->bmiColors[i].rgbBlue); + } } + /* Map to in picture coordinates */ - for (i=0;iHeight;i++) - for (j=0;jWidth;j++) - bytes[(gid->Top+i)*gif->SWidth+gid->Left+j]=si->RasterBits[i*gid->Width+j]; + for (i = 0, j = 0; i < gid->Height; i++) { + if (gif->Image.Interlace) { + memcpy( + bytes + (gid->Top + j) * padding + gid->Left, + si->RasterBits + i * gid->Width, + gid->Width); + + /* Lower bits of interlaced counter encode current interlace */ + if (j & 1) j += 2; /* Currently filling odd rows */ + else if (j & 2) j += 4; /* Currently filling even rows not multiples of 4 */ + else j += 8; /* Currently filling every 8th row or 4th row in-between */ + + if (j >= gid->Height && i < gid->Height && (j & 1) == 0) { + /* End of current interlace, go to next interlace */ + if (j & 2) j = 1; /* Next iteration fills odd rows */ + else if (j & 4) j = 2; /* Next iteration fills even rows not mod 4 and not mod 8 */ + else j = 4; /* Next iteration fills rows in-between rows mod 6 */ + } + } else { + memcpy( + bytes + (gid->Top + i) * padding + gid->Left, + si->RasterBits + i * gid->Width, + gid->Width); + } + } + bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi->bmiHeader.biWidth = gif->SWidth; - bmi->bmiHeader.biHeight = gif->SHeight; + bmi->bmiHeader.biHeight = -gif->SHeight; bmi->bmiHeader.biPlanes = 1; bmi->bmiHeader.biBitCount = 8; bmi->bmiHeader.biCompression = BI_RGB; - bmi->bmiHeader.biSizeImage = gif->SWidth*gif->SHeight; + bmi->bmiHeader.biSizeImage = padding*gif->SHeight; bmi->bmiHeader.biXPelsPerMeter = 0; bmi->bmiHeader.biYPelsPerMeter = 0; bmi->bmiHeader.biClrUsed = 1 << gif->SColorResolution; @@ -973,12 +1132,40 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { CBM_INIT, bytes, bmi, - DIB_PAL_COLORS + DIB_RGB_COLORS ); + + if (transparent > -1) { + /* Create the Mask */ + HDC hdc = CreateCompatibleDC(0); + HDC hdcMask = CreateCompatibleDC(0); + HBITMAP hOldbitmap; + HBITMAP hOldbitmapmask; + + This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL); + + hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap); + hOldbitmapmask = SelectObject(hdcMask, This->hbmMask); + SetBkColor(hdc, This->rgbTrans); + BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY); + + /* We no longer need the original bitmap, so we apply the first + transformation with the mask to speed up the rendering */ + SetBkColor(hdc, RGB(0,0,0)); + SetTextColor(hdc, RGB(255,255,255)); + BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, + hdcMask, 0, 0, SRCAND); + + SelectObject(hdc, hOldbitmap); + SelectObject(hdcMask, hOldbitmapmask); + DeleteDC(hdcMask); + DeleteDC(hdc); + } + DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; OLEPictureImpl_SetBitmap(This); - DGifCloseFile(gif); + pDGifCloseFile(gif); HeapFree(GetProcessHeap(),0,bytes); return S_OK; #else @@ -988,7 +1175,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { break; } case 0xd8ff: { /* JPEG */ -#ifdef HAVE_LIBJPEG +#ifdef HAVE_JPEGLIB_H struct jpeg_decompress_struct jd; struct jpeg_error_mgr jerr; int ret; @@ -999,7 +1186,14 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { HDC hdcref; struct jpeg_source_mgr xjsm; LPBYTE oldbits; - int i; + unsigned int i; + + if(!libjpeg_handle) { + if(!load_libjpeg()) { + FIXME("Failed reading JPEG because unable to find %s\n", SONAME_LIBJPEG); + return E_FAIL; + } + } /* This is basically so we can use in-memory data for jpeg decompression. * We need to have all the functions. @@ -1012,12 +1206,14 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { xjsm.resync_to_restart = _jpeg_resync_to_restart; xjsm.term_source = _jpeg_term_source; - jd.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&jd); + jd.err = pjpeg_std_error(&jerr); + /* jpeg_create_decompress is a macro that expands to jpeg_CreateDecompress - see jpeglib.h + * jpeg_create_decompress(&jd); */ + pjpeg_CreateDecompress(&jd, JPEG_LIB_VERSION, (size_t) sizeof(struct jpeg_decompress_struct)); jd.src = &xjsm; - ret=jpeg_read_header(&jd,TRUE); + ret=pjpeg_read_header(&jd,TRUE); jd.out_color_space = JCS_RGB; - jpeg_start_decompress(&jd); + pjpeg_start_decompress(&jd); if (ret != JPEG_HEADER_OK) { ERR("Jpeg image in stream has bad format, read header returned %d.\n",ret); HeapFree(GetProcessHeap(),0,xbuf); @@ -1031,7 +1227,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { oldbits = bits; oldsamprow = samprow; while ( jd.output_scanlinedesc.u.bmp.hbitmap=CreateDIBitmap( hdcref, @@ -1097,7 +1293,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { CBM_INIT, xbuf+bfh->bfOffBits, bi, - (bi->bmiHeader.biBitCount<=8)?DIB_PAL_COLORS:DIB_RGB_COLORS + DIB_RGB_COLORS ); DeleteDC(hdcref); This->desc.picType = PICTYPE_BITMAP; @@ -1108,6 +1304,7 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { case 0x0000: { /* ICON , first word is dwReserved */ HICON hicon; CURSORICONFILEDIR *cifd = (CURSORICONFILEDIR*)xbuf; + HDC hdcRef; int i; /* @@ -1153,15 +1350,19 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { } else { This->desc.picType = PICTYPE_ICON; This->desc.u.icon.hicon = hicon; - This->himetricWidth = cifd->idEntries[i].bWidth; - This->himetricHeight = cifd->idEntries[i].bHeight; + This->origWidth = cifd->idEntries[i].bWidth; + This->origHeight = cifd->idEntries[i].bHeight; + hdcRef = CreateCompatibleDC(0); + This->himetricWidth =(cifd->idEntries[i].bWidth *2540)/GetDeviceCaps(hdcRef, LOGPIXELSX); + This->himetricHeight=(cifd->idEntries[i].bHeight*2540)/GetDeviceCaps(hdcRef, LOGPIXELSY); + DeleteDC(hdcRef); hr = S_OK; } break; } default: { - int i; + unsigned int i; FIXME("Unknown magic %04x, %ld read bytes:\n",magic,xread); hr=E_FAIL; for (i=0;ibIsDirty = FALSE; /* FIXME: this notify is not really documented */ if (hr==S_OK) @@ -1180,12 +1382,324 @@ static HRESULT WINAPI OLEPictureImpl_Load(IPersistStream* iface,IStream*pStm) { return hr; } +static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength); +static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength); static HRESULT WINAPI OLEPictureImpl_Save( IPersistStream* iface,IStream*pStm,BOOL fClearDirty) { - ICOM_THIS_From_IPersistStream(IPicture, iface); - FIXME("(%p,%p,%d),stub!\n",This,pStm,fClearDirty); - return E_NOTIMPL; + HRESULT hResult = E_NOTIMPL; + void * pIconData; + unsigned int iDataSize; + ULONG dummy; + int iSerializeResult = 0; + + ICOM_THIS_From_IPersistStream(OLEPictureImpl, iface); + + switch (This->desc.picType) { + case PICTYPE_ICON: + if (This->bIsDirty) { + if (serializeIcon(This->desc.u.icon.hicon, &pIconData, &iDataSize)) { + if (This->loadtime_magic != 0xdeadbeef) { + DWORD header[2]; + + header[0] = This->loadtime_magic; + header[1] = iDataSize; + IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); + } + IStream_Write(pStm, pIconData, iDataSize, &dummy); + + HeapFree(GetProcessHeap(), 0, This->data); + This->data = pIconData; + This->datalen = iDataSize; + hResult = S_OK; + } else { + FIXME("(%p,%p,%d), unable to serializeIcon()!\n",This,pStm,fClearDirty); + hResult = E_FAIL; + } + } else { + if (This->loadtime_magic != 0xdeadbeef) { + DWORD header[2]; + + header[0] = This->loadtime_magic; + header[1] = This->datalen; + IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); + } + IStream_Write(pStm, This->data, This->datalen, &dummy); + hResult = S_OK; + } + break; + case PICTYPE_BITMAP: + if (This->bIsDirty) { + switch (This->keepOrigFormat ? This->loadtime_format : 0x4d42) { + case 0x4d42: + iSerializeResult = serializeBMP(This->desc.u.bmp.hbitmap, &pIconData, &iDataSize); + break; + case 0xd8ff: + FIXME("(%p,%p,%d), PICTYPE_BITMAP (format JPEG) not implemented!\n",This,pStm,fClearDirty); + break; + case 0x4947: + FIXME("(%p,%p,%d), PICTYPE_BITMAP (format GIF) not implemented!\n",This,pStm,fClearDirty); + break; + default: + FIXME("(%p,%p,%d), PICTYPE_BITMAP (format UNKNOWN, using BMP?) not implemented!\n",This,pStm,fClearDirty); + break; + } + if (iSerializeResult) { + /* + if (This->loadtime_magic != 0xdeadbeef) { + */ + if (1) { + DWORD header[2]; + + header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; + header[1] = iDataSize; + IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); + } + IStream_Write(pStm, pIconData, iDataSize, &dummy); + + HeapFree(GetProcessHeap(), 0, This->data); + This->data = pIconData; + This->datalen = iDataSize; + hResult = S_OK; + } + } else { + /* + if (This->loadtime_magic != 0xdeadbeef) { + */ + if (1) { + DWORD header[2]; + + header[0] = (This->loadtime_magic != 0xdeadbeef) ? This->loadtime_magic : 0x0000746c; + header[1] = This->datalen; + IStream_Write(pStm, header, 2 * sizeof(DWORD), &dummy); + } + IStream_Write(pStm, This->data, This->datalen, &dummy); + hResult = S_OK; + } + break; + case PICTYPE_METAFILE: + FIXME("(%p,%p,%d), PICTYPE_METAFILE not implemented!\n",This,pStm,fClearDirty); + break; + case PICTYPE_ENHMETAFILE: + FIXME("(%p,%p,%d),PICTYPE_ENHMETAFILE not implemented!\n",This,pStm,fClearDirty); + break; + default: + FIXME("(%p,%p,%d), [unknown type] not implemented!\n",This,pStm,fClearDirty); + break; + } + if (hResult == S_OK && fClearDirty) This->bIsDirty = FALSE; + return hResult; +} + +static int serializeBMP(HBITMAP hBitmap, void ** ppBuffer, unsigned int * pLength) +{ + int iSuccess = 0; + HDC hDC; + BITMAPINFO * pInfoBitmap; + int iNumPaletteEntries; + unsigned char * pPixelData; + BITMAPFILEHEADER * pFileHeader; + BITMAPINFO * pInfoHeader; + + pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + + /* Find out bitmap size and padded length */ + hDC = GetDC(0); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); + GetDIBits(hDC, hBitmap, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + + /* Fetch bitmap palette & pixel data */ + + pPixelData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + pInfoBitmap->bmiHeader.biSizeImage); + GetDIBits(hDC, hBitmap, 0, pInfoBitmap->bmiHeader.biHeight, pPixelData, pInfoBitmap, DIB_RGB_COLORS); + + /* Calculate the total length required for the BMP data */ + if (pInfoBitmap->bmiHeader.biClrUsed != 0) iNumPaletteEntries = pInfoBitmap->bmiHeader.biClrUsed; + else if (pInfoBitmap->bmiHeader.biBitCount <= 8) iNumPaletteEntries = 1 << pInfoBitmap->bmiHeader.biBitCount; + else iNumPaletteEntries = 0; + *pLength = + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD) + + pInfoBitmap->bmiHeader.biSizeImage; + *ppBuffer = (void *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *pLength); + + /* Fill the BITMAPFILEHEADER */ + pFileHeader = (BITMAPFILEHEADER *)(*ppBuffer); + pFileHeader->bfType = 0x4d42; + pFileHeader->bfSize = *pLength; + pFileHeader->bfOffBits = + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD); + + /* Fill the BITMAPINFOHEADER and the palette data */ + pInfoHeader = (BITMAPINFO *)((unsigned char *)(*ppBuffer) + sizeof(BITMAPFILEHEADER)); + memcpy(pInfoHeader, pInfoBitmap, sizeof(BITMAPINFOHEADER) + iNumPaletteEntries * sizeof(RGBQUAD)); + memcpy( + (unsigned char *)(*ppBuffer) + + sizeof(BITMAPFILEHEADER) + + sizeof(BITMAPINFOHEADER) + + iNumPaletteEntries * sizeof(RGBQUAD), + pPixelData, pInfoBitmap->bmiHeader.biSizeImage); + iSuccess = 1; + + HeapFree(GetProcessHeap(), 0, pPixelData); + HeapFree(GetProcessHeap(), 0, pInfoBitmap); + return iSuccess; +} + +static int serializeIcon(HICON hIcon, void ** ppBuffer, unsigned int * pLength) +{ + ICONINFO infoIcon; + int iSuccess = 0; + + *ppBuffer = NULL; *pLength = 0; + if (GetIconInfo(hIcon, &infoIcon)) { + HDC hDC; + BITMAPINFO * pInfoBitmap; + unsigned char * pIconData = NULL; + unsigned int iDataSize = 0; + + pInfoBitmap = (BITMAPINFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + + /* Find out icon size */ + hDC = GetDC(0); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); + GetDIBits(hDC, infoIcon.hbmColor, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + if (1) { + /* Auxiliary pointers */ + CURSORICONFILEDIR * pIconDir; + CURSORICONFILEDIRENTRY * pIconEntry; + BITMAPINFOHEADER * pIconBitmapHeader; + unsigned int iOffsetPalette; + unsigned int iOffsetColorData; + unsigned int iOffsetMaskData; + + unsigned int iLengthScanLineColor; + unsigned int iLengthScanLineMask; + unsigned int iNumEntriesPalette; + + iLengthScanLineMask = ((pInfoBitmap->bmiHeader.biWidth + 31) >> 5) << 2; + iLengthScanLineColor = ((pInfoBitmap->bmiHeader.biWidth * pInfoBitmap->bmiHeader.biBitCount + 31) >> 5) << 2; +/* + FIXME("DEBUG: bitmap size is %d x %d\n", + pInfoBitmap->bmiHeader.biWidth, + pInfoBitmap->bmiHeader.biHeight); + FIXME("DEBUG: bitmap bpp is %d\n", + pInfoBitmap->bmiHeader.biBitCount); + FIXME("DEBUG: bitmap nplanes is %d\n", + pInfoBitmap->bmiHeader.biPlanes); + FIXME("DEBUG: bitmap biSizeImage is %lu\n", + pInfoBitmap->bmiHeader.biSizeImage); +*/ + /* Let's start with one CURSORICONFILEDIR and one CURSORICONFILEDIRENTRY */ + iDataSize += 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY) + sizeof(BITMAPINFOHEADER); + pIconData = (unsigned char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, iDataSize); + + /* Fill out the CURSORICONFILEDIR */ + pIconDir = (CURSORICONFILEDIR *)pIconData; + pIconDir->idType = 1; + pIconDir->idCount = 1; + + /* Fill out the CURSORICONFILEDIRENTRY */ + pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); + pIconEntry->bWidth = (unsigned char)pInfoBitmap->bmiHeader.biWidth; + pIconEntry->bHeight = (unsigned char)pInfoBitmap->bmiHeader.biHeight; + pIconEntry->bColorCount = + (pInfoBitmap->bmiHeader.biBitCount < 8) + ? 1 << pInfoBitmap->bmiHeader.biBitCount + : 0; + pIconEntry->xHotspot = pInfoBitmap->bmiHeader.biPlanes; + pIconEntry->yHotspot = pInfoBitmap->bmiHeader.biBitCount; + pIconEntry->dwDIBSize = 0; + pIconEntry->dwDIBOffset = 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY); + + /* Fill out the BITMAPINFOHEADER */ + pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + memcpy(pIconBitmapHeader, &pInfoBitmap->bmiHeader, sizeof(BITMAPINFOHEADER)); + + /* Find out whether a palette exists for the bitmap */ + if ( (pInfoBitmap->bmiHeader.biBitCount == 16 && pInfoBitmap->bmiHeader.biCompression == BI_RGB) + || (pInfoBitmap->bmiHeader.biBitCount == 24) + || (pInfoBitmap->bmiHeader.biBitCount == 32 && pInfoBitmap->bmiHeader.biCompression == BI_RGB)) { + iNumEntriesPalette = pInfoBitmap->bmiHeader.biClrUsed; + } else if ((pInfoBitmap->bmiHeader.biBitCount == 16 || pInfoBitmap->bmiHeader.biBitCount == 32) + && pInfoBitmap->bmiHeader.biCompression == BI_BITFIELDS) { + iNumEntriesPalette = 3; + } else if (pInfoBitmap->bmiHeader.biBitCount <= 8) { + iNumEntriesPalette = 1 << pInfoBitmap->bmiHeader.biBitCount; + } else { + iNumEntriesPalette = 0; + } + + /* Add bitmap size and header size to icon data size. */ + iOffsetPalette = iDataSize; + iDataSize += iNumEntriesPalette * sizeof(DWORD); + iOffsetColorData = iDataSize; + iDataSize += pIconBitmapHeader->biSizeImage; + iOffsetMaskData = iDataSize; + iDataSize += pIconBitmapHeader->biHeight * iLengthScanLineMask; + pIconBitmapHeader->biSizeImage += pIconBitmapHeader->biHeight * iLengthScanLineMask; + pIconBitmapHeader->biHeight *= 2; + pIconData = (unsigned char *)HeapReAlloc(GetProcessHeap(), 0, pIconData, iDataSize); + pIconEntry = (CURSORICONFILEDIRENTRY *)(pIconData + 3 * sizeof(WORD)); + pIconBitmapHeader = (BITMAPINFOHEADER *)(pIconData + 3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + pIconEntry->dwDIBSize = iDataSize - (3 * sizeof(WORD) + sizeof(CURSORICONFILEDIRENTRY)); + + /* Get the actual bitmap data from the icon bitmap */ + GetDIBits(hDC, infoIcon.hbmColor, 0, pInfoBitmap->bmiHeader.biHeight, + pIconData + iOffsetColorData, pInfoBitmap, DIB_RGB_COLORS); + if (iNumEntriesPalette > 0) { + memcpy(pIconData + iOffsetPalette, pInfoBitmap->bmiColors, + iNumEntriesPalette * sizeof(RGBQUAD)); + } + + /* Reset all values so that GetDIBits call succeeds */ + memset(pIconData + iOffsetMaskData, 0, iDataSize - iOffsetMaskData); + memset(pInfoBitmap, 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); + pInfoBitmap->bmiHeader.biSize = sizeof(pInfoBitmap->bmiHeader); +/* + if (!(GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS) + && GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, + pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS))) { + + printf("ERROR: unable to get bitmap mask (error %lu)\n", + GetLastError()); + + } +*/ + GetDIBits(hDC, infoIcon.hbmMask, 0, 0, NULL, pInfoBitmap, DIB_RGB_COLORS); + GetDIBits(hDC, infoIcon.hbmMask, 0, pIconEntry->bHeight, pIconData + iOffsetMaskData, pInfoBitmap, DIB_RGB_COLORS); + + /* Write out everything produced so far to the stream */ + *ppBuffer = pIconData; *pLength = iDataSize; + iSuccess = 1; + } else { +/* + printf("ERROR: unable to get bitmap information via GetDIBits() (error %lu)\n", + GetLastError()); +*/ + } + /* + Remarks (from MSDN entry on GetIconInfo): + + GetIconInfo creates bitmaps for the hbmMask and hbmColor + members of ICONINFO. The calling application must manage + these bitmaps and delete them when they are no longer + necessary. + */ + if (hDC) ReleaseDC(0, hDC); + DeleteObject(infoIcon.hbmMask); + if (infoIcon.hbmColor) DeleteObject(infoIcon.hbmColor); + HeapFree(GetProcessHeap(), 0, pInfoBitmap); + } else { + printf("ERROR: Unable to get icon information (error %lu)\n", + GetLastError()); + } + return iSuccess; } static HRESULT WINAPI OLEPictureImpl_GetSizeMax( @@ -1493,13 +2007,13 @@ SPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { static ULONG WINAPI SPCF_AddRef(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - return ++(This->ref); + return InterlockedIncrement(&This->ref); } static ULONG WINAPI SPCF_Release(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; /* static class, won't be freed */ - return --(This->ref); + return InterlockedDecrement(&This->ref); } static HRESULT WINAPI SPCF_CreateInstance( diff --git a/reactos/lib/oleaut32/safearray.c b/reactos/lib/oleaut32/safearray.c index 8f2e140160d..1aaedb4704f 100644 --- a/reactos/lib/oleaut32/safearray.c +++ b/reactos/lib/oleaut32/safearray.c @@ -36,15 +36,16 @@ #include #include #include + +#define COBJMACROS + #include "windef.h" #include "winerror.h" #include "winbase.h" -#include "oleauto.h" -#include "wine/debug.h" #include "variant.h" +#include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(ole); - +WINE_DEFAULT_DEBUG_CHANNEL(variant); /************************************************************************ * SafeArray {OLEAUT32} @@ -61,8 +62,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); * using the IRecordInfo interface. * * There are two types of SafeArray, normal and vectors. Normal arrays can have - * multiple dimensions and the data for the array is allocated seperately from - * the array header. This is the most flexable type of array. Vectors, on the + * multiple dimensions and the data for the array is allocated separately from + * the array header. This is the most flexible type of array. Vectors, on the * other hand, are fixed in size and consist of a single allocated block, and a * single dimension. * @@ -341,7 +342,9 @@ static HRESULT SAFEARRAY_DestroyData(SAFEARRAY *psa, ULONG ulStartCell) while(ulCellCount--) { - VariantClear(lpVariant); + HRESULT hRet = VariantClear(lpVariant); + + if (FAILED(hRet)) FIXME("VariantClear of element failed!\n"); lpVariant++; } } @@ -368,7 +371,10 @@ static HRESULT SAFEARRAY_CopyData(SAFEARRAY *psa, SAFEARRAY *dest) while(ulCellCount--) { - VariantCopy(lpDest, lpVariant); + HRESULT hRet; + + hRet = VariantCopy(lpDest, lpVariant); + if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%lx\n", hRet); lpVariant++; lpDest++; } @@ -873,8 +879,10 @@ HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData VARIANT* lpVariant = (VARIANT*)pvData; VARIANT* lpDest = (VARIANT*)lpvDest; - VariantClear(lpDest); - VariantCopy(lpDest, lpVariant); + hRet = VariantClear(lpDest); + if (FAILED(hRet)) FIXME("VariantClear failed with 0x%lx\n", hRet); + hRet = VariantCopy(lpDest, lpVariant); + if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%lx\n", hRet); } else if (psa->fFeatures & FADF_BSTR) { @@ -958,7 +966,10 @@ HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData VARIANT* lpVariant = (VARIANT*)lpvSrc; VARIANT* lpDest = (VARIANT*)pvData; - VariantCopy(lpDest, lpVariant); + /* The original content of pvData is ignored. */ + V_VT(lpDest) = VT_EMPTY; + hRet = VariantCopy(lpDest, lpVariant); + if (FAILED(hRet)) FIXME("VariantCopy failed with 0x%lx\n", hRet); } else if (psa->fFeatures & FADF_BSTR) { @@ -1241,9 +1252,10 @@ HRESULT WINAPI SafeArrayDestroyData(SAFEARRAY *psa) return E_INVALIDARG; if (psa->cLocks) - return DISP_E_ARRAYISLOCKED; /* Cant delete a locked array */ + return DISP_E_ARRAYISLOCKED; /* Can't delete a locked array */ - if (psa->pvData) + /* If static, keep pvData and don't free */ + if (psa->pvData && !(psa->fFeatures & FADF_STATIC)) { /* Delete the actual item data */ if (FAILED(SAFEARRAY_DestroyData(psa, 0))) diff --git a/reactos/lib/oleaut32/tmarshal.c b/reactos/lib/oleaut32/tmarshal.c index a70ea634379..e29a7ae0df8 100644 --- a/reactos/lib/oleaut32/tmarshal.c +++ b/reactos/lib/oleaut32/tmarshal.c @@ -30,8 +30,10 @@ #include #include +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "winerror.h" #include "windef.h" #include "winbase.h" diff --git a/reactos/lib/oleaut32/typelib.c b/reactos/lib/oleaut32/typelib.c index eec67218cff..964727e5f4a 100644 --- a/reactos/lib/oleaut32/typelib.c +++ b/reactos/lib/oleaut32/typelib.c @@ -61,8 +61,10 @@ #include #include +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "winerror.h" #include "windef.h" #include "winbase.h" @@ -72,7 +74,6 @@ #include "wine/unicode.h" #include "objbase.h" -#include "heap.h" #include "ole2disp.h" #include "typelib.h" #include "wine/debug.h" @@ -148,6 +149,50 @@ static void FromLEDWords(void *p_Val, int p_iSize) #define FromLEDWords(X,Y) /*nothing*/ #endif +/* get the path of a typelib key, in the form "Typelib\\\\." */ +/* buffer must be at least 60 characters long */ +static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer ) +{ + static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0}; + static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0}; + + memcpy( buffer, TypelibW, sizeof(TypelibW) ); + StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); + sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin ); + return buffer; +} + +/* get the path of an interface key, in the form "Interface\\" */ +/* buffer must be at least 50 characters long */ +static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer ) +{ + static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0}; + + memcpy( buffer, InterfaceW, sizeof(InterfaceW) ); + StringFromGUID2( guid, buffer + strlenW(buffer), 40 ); + return buffer; +} + +/* get the lcid subkey for a typelib, in the form "\\" */ +/* buffer must be at least 16 characters long */ +static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer ) +{ + static const WCHAR LcidFormatW[] = {'%','l','x','\\',0}; + static const WCHAR win16W[] = {'w','i','n','1','6',0}; + static const WCHAR win32W[] = {'w','i','n','3','2',0}; + + sprintfW( buffer, LcidFormatW, lcid ); + switch(syskind) + { + case SYS_WIN16: strcatW( buffer, win16W ); break; + case SYS_WIN32: strcatW( buffer, win32W ); break; + default: + TRACE("Typelib is for unsupported syskind %i\n", syskind); + return NULL; + } + return buffer; +} + /**************************************************************************** * QueryPathOfRegTypeLib [OLEAUT32.164] @@ -162,40 +207,33 @@ QueryPathOfRegTypeLib( LCID lcid, /* [in] locale id */ LPBSTR path ) /* [out] path of typelib */ { - /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add - string termination character on output strings */ - - HRESULT hr = E_FAIL; - - LCID myLCID = lcid; - - char szXGUID[80]; - char szTypeLibKey[100]; - char szPath[MAX_PATH]; - DWORD dwPathLen = sizeof(szPath); + HRESULT hr = E_FAIL; + LCID myLCID = lcid; + HKEY hkey; + WCHAR buffer[60]; + WCHAR Path[MAX_PATH]; if ( !HIWORD(guid) ) { - sprintf(szXGUID, - "", - (DWORD) guid); + FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path); + return E_FAIL; + } - FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path); + get_typelib_key( guid, wMaj, wMin, buffer ); + + if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS) + { + TRACE_(typelib)("%s not found\n", debugstr_w(buffer)); return E_FAIL; } while (hr != S_OK) { - sprintf(szTypeLibKey, - "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32", - guid->Data1, guid->Data2, guid->Data3, - guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], - guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7], - wMaj, - wMin, - myLCID); + DWORD dwPathLen = sizeof(Path); - if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen)) + get_lcid_subkey( myLCID, SYS_WIN32, buffer ); + + if (RegQueryValueW(hkey, buffer, Path, &dwPathLen)) { if (!lcid) break; @@ -216,23 +254,11 @@ QueryPathOfRegTypeLib( } else { - DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 ); - BSTR bstrPath = SysAllocStringLen(NULL,len); - - MultiByteToWideChar(CP_ACP, - MB_PRECOMPOSED, - szPath, - dwPathLen, - bstrPath, - len); - *path = bstrPath; - hr = S_OK; + *path = SysAllocString( Path ); + hr = S_OK; } } - - if (hr != S_OK) - TRACE_(typelib)("%s not found\n", szTypeLibKey); - + RegCloseKey( hkey ); return hr; } @@ -385,6 +411,13 @@ HRESULT WINAPI LoadRegTypeLib( } +/* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */ +static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0}; +static const WCHAR FLAGSW[] = {'F','L','A','G','S',0}; +static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0}; +static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0}; +static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0}; + /****************************************************************************** * RegisterTypeLib [OLEAUT32.163] * Adds information about a type library to the System Registry @@ -403,17 +436,17 @@ HRESULT WINAPI RegisterTypeLib( OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library, may be NULL*/ { + static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-', + '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-', + '0','0','0','0','0','0','0','0','0','0','4','6','}',0}; HRESULT res; TLIBATTR *attr; - OLECHAR guid[80]; - LPSTR guidA; - CHAR keyName[120]; - CHAR tmp[MAX_PATH]; + WCHAR keyName[60]; + WCHAR tmp[16]; HKEY key, subKey; UINT types, tidx; TYPEKIND kind; DWORD disposition; - static const char *PSOA = "{00020424-0000-0000-C000-000000000046}"; if (ptlib == NULL || szFullPath == NULL) return E_INVALIDARG; @@ -421,14 +454,10 @@ HRESULT WINAPI RegisterTypeLib( if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr))) return E_FAIL; - StringFromGUID2(&attr->guid, guid, 80); - guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid); - snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x", - guidA, attr->wMajorVerNum, attr->wMinorVerNum); - HeapFree(GetProcessHeap(), 0, guidA); + get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName ); res = S_OK; - if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, + if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { LPOLESTR doc; @@ -446,24 +475,10 @@ HRESULT WINAPI RegisterTypeLib( res = E_FAIL; /* Make up the name of the typelib path subkey */ - sprintf(tmp, "%lu\\", attr->lcid); - switch(attr->syskind) { - case SYS_WIN16: - strcat(tmp, "win16"); - break; - - case SYS_WIN32: - strcat(tmp, "win32"); - break; - - default: - TRACE("Typelib is for unsupported syskind %i\n", attr->syskind); - res = E_FAIL; - break; - } + if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL; /* Create the typelib path subkey */ - if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0, + if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0, KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { if (RegSetValueExW(subKey, NULL, 0, REG_SZ, @@ -476,14 +491,15 @@ HRESULT WINAPI RegisterTypeLib( res = E_FAIL; /* Create the flags subkey */ - if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0, + if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0, KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { - CHAR buf[20]; /* FIXME: is %u correct? */ - snprintf(buf, sizeof(buf), "%u", attr->wLibFlags); - if (RegSetValueExA(subKey, NULL, 0, REG_SZ, - buf, lstrlenA(buf) + 1) != ERROR_SUCCESS) + static const WCHAR formatW[] = {'%','u',0}; + WCHAR buf[20]; + sprintfW(buf, formatW, attr->wLibFlags); + if (RegSetValueExW(subKey, NULL, 0, REG_SZ, + (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS) res = E_FAIL; RegCloseKey(subKey); @@ -492,7 +508,7 @@ HRESULT WINAPI RegisterTypeLib( res = E_FAIL; /* create the helpdir subkey */ - if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0, + if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0, KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS) { BOOL freeHelpDir = FALSE; @@ -598,41 +614,41 @@ HRESULT WINAPI RegisterTypeLib( } /* register interface<->typelib coupling */ - StringFromGUID2(&tattr->guid, guid, 80); - guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid); - snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA); - HeapFree(GetProcessHeap(), 0, guidA); - - if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, - KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) { + get_interface_key( &tattr->guid, keyName ); + if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0, + KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) + { if (name) RegSetValueExW(key, NULL, 0, REG_SZ, - (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR)); + (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR)); - if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0, + if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0, KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { - RegSetValueExA(subKey, NULL, 0, REG_SZ, - PSOA, strlen(PSOA)); - RegCloseKey(subKey); - } - - if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0, - KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { - RegSetValueExA(subKey, NULL, 0, REG_SZ, - PSOA, strlen(PSOA)); - RegCloseKey(subKey); - } - - if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0, - KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { - CHAR ver[32]; - StringFromGUID2(&attr->guid, guid, 80); - snprintf(ver, sizeof(ver), "%x.%x", - attr->wMajorVerNum, attr->wMinorVerNum); RegSetValueExW(subKey, NULL, 0, REG_SZ, - (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR)); - RegSetValueExA(subKey, "Version", 0, REG_SZ, - ver, lstrlenA(ver)); + (BYTE*)PSOA, sizeof PSOA); + RegCloseKey(subKey); + } + + if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0, + KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) { + RegSetValueExW(subKey, NULL, 0, REG_SZ, + (BYTE*)PSOA, sizeof PSOA); + RegCloseKey(subKey); + } + + if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0, + KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) + { + WCHAR buffer[40]; + static const WCHAR fmtver[] = {'%','u','.','%','u',0 }; + static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0}; + + StringFromGUID2(&attr->guid, buffer, 40); + RegSetValueExW(subKey, NULL, 0, REG_SZ, + (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); + sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum); + RegSetValueExW(subKey, VersionW, 0, REG_SZ, + (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR)); RegCloseKey(subKey); } @@ -674,13 +690,10 @@ HRESULT WINAPI UnRegisterTypeLib( { BSTR tlibPath = NULL; DWORD tmpLength; - CHAR keyName[MAX_PATH]; - CHAR* syskindName; - CHAR subKeyName[MAX_PATH]; - LPSTR guidA; + WCHAR keyName[60]; + WCHAR subKeyName[50]; int result = S_OK; DWORD i = 0; - OLECHAR guid[80]; BOOL deleteOtherStuff; HKEY key = NULL; HKEY subKey = NULL; @@ -693,23 +706,10 @@ HRESULT WINAPI UnRegisterTypeLib( TRACE("(IID: %s): stub\n",debugstr_guid(libid)); /* Create the path to the key */ - StringFromGUID2(libid, guid, 80); - guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid); - snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x", - guidA, wVerMajor, wVerMinor); - HeapFree(GetProcessHeap(), 0, guidA); + get_typelib_key( libid, wVerMajor, wVerMinor, keyName ); - /* Work out the syskind name */ - switch(syskind) { - case SYS_WIN16: - syskindName = "win16"; - break; - - case SYS_WIN32: - syskindName = "win32"; - break; - - default: + if (syskind != SYS_WIN16 && syskind != SYS_WIN32) + { TRACE("Unsupported syskind %i\n", syskind); result = E_INVALIDARG; goto end; @@ -722,7 +722,7 @@ HRESULT WINAPI UnRegisterTypeLib( } /* Try and open the key to the type library. */ - if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) { + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) { result = E_INVALIDARG; goto end; } @@ -753,21 +753,18 @@ HRESULT WINAPI UnRegisterTypeLib( } /* the path to the type */ - StringFromGUID2(&typeAttr->guid, guid, 80); - guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid); - snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA); - HeapFree(GetProcessHeap(), 0, guidA); + get_interface_key( &typeAttr->guid, subKeyName ); /* Delete its bits */ - if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) { + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) { goto enddeleteloop; } - RegDeleteKeyA(subKey, "ProxyStubClsid"); - RegDeleteKeyA(subKey, "ProxyStubClsid32"); - RegDeleteKeyA(subKey, "TypeLib"); + RegDeleteKeyW(subKey, ProxyStubClsidW); + RegDeleteKeyW(subKey, ProxyStubClsid32W); + RegDeleteKeyW(subKey, TypeLibW); RegCloseKey(subKey); subKey = NULL; - RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName); + RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName); enddeleteloop: if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr); @@ -777,40 +774,36 @@ enddeleteloop: } /* Now, delete the type library path subkey */ - sprintf(subKeyName, "%lu\\%s", lcid, syskindName); - RegDeleteKeyA(key, subKeyName); - sprintf(subKeyName, "%lu", lcid); - RegDeleteKeyA(key, subKeyName); + get_lcid_subkey( lcid, syskind, subKeyName ); + RegDeleteKeyW(key, subKeyName); + *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */ + RegDeleteKeyW(key, subKeyName); /* check if there is anything besides the FLAGS/HELPDIR keys. If there is, we don't delete them */ - tmpLength = sizeof(subKeyName); + tmpLength = sizeof(subKeyName)/sizeof(WCHAR); deleteOtherStuff = TRUE; i = 0; - while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) { - tmpLength = sizeof(subKeyName); + while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) { + tmpLength = sizeof(subKeyName)/sizeof(WCHAR); /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */ - if (!strcmp(subKeyName, "FLAGS")) continue; - if (!strcmp(subKeyName, "HELPDIR")) continue; + if (!strcmpW(subKeyName, FLAGSW)) continue; + if (!strcmpW(subKeyName, HELPDIRW)) continue; deleteOtherStuff = FALSE; break; } /* only delete the other parts of the key if we're absolutely sure */ if (deleteOtherStuff) { - RegDeleteKeyA(key, "FLAGS"); - RegDeleteKeyA(key, "HELPDIR"); + RegDeleteKeyW(key, FLAGSW); + RegDeleteKeyW(key, HELPDIRW); RegCloseKey(key); key = NULL; - StringFromGUID2(libid, guid, 80); - guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid); - sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor); - RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName); - sprintf(keyName, "TypeLib\\%s", guidA); - RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName); - HeapFree(GetProcessHeap(), 0, guidA); + RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); + *strrchrW( keyName, '\\' ) = 0; /* remove last path component */ + RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName); } end: @@ -2167,7 +2160,7 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 ); if (INVALID_HANDLE_VALUE != hFile) { - HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); + HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL ); if (hMapping) { LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); @@ -2200,8 +2193,8 @@ int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib) LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH); if (hinstDLL) { - HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index), - "TYPELIB"); + static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0}; + HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW); if (hrsrc) { HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc); @@ -3995,8 +3988,8 @@ static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface) static HRESULT WINAPI ITypeLibComp_fnBind( ITypeComp * iface, OLECHAR * szName, - unsigned long lHash, - unsigned short wFlags, + ULONG lHash, + WORD wFlags, ITypeInfo ** ppTInfo, DESCKIND * pDescKind, BINDPTR * pBindPtr) @@ -4008,7 +4001,7 @@ static HRESULT WINAPI ITypeLibComp_fnBind( static HRESULT WINAPI ITypeLibComp_fnBindType( ITypeComp * iface, OLECHAR * szName, - unsigned long lHash, + ULONG lHash, ITypeInfo ** ppTInfo, ITypeComp ** ppTComp) { @@ -5739,6 +5732,75 @@ static ITypeInfo2Vtbl tinfvt = ITypeInfo2_fnGetAllImplTypeCustData, }; +/****************************************************************************** + * CreateDispTypeInfo [OLEAUT32.31] + * + * Build type information for an object so it can be called through an + * IDispatch interface. + * + * RETURNS + * Success: S_OK. pptinfo contains the created ITypeInfo object. + * Failure: E_INVALIDARG, if one or more arguments is invalid. + * + * NOTES + * This call allows an objects methods to be accessed through IDispatch, by + * building an ITypeInfo object that IDispatch can use to call through. + */ +HRESULT WINAPI CreateDispTypeInfo( + INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */ + LCID lcid, /* [I] Locale Id */ + ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */ +{ + ITypeInfoImpl *pTIImpl; + int param, func; + TLBFuncDesc **ppFuncDesc; + + pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor(); + pTIImpl->pTypeLib = NULL; + pTIImpl->index = 0; + pTIImpl->Name = NULL; + pTIImpl->dwHelpContext = -1; + memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID)); + pTIImpl->TypeAttr.lcid = lcid; + pTIImpl->TypeAttr.typekind = TKIND_COCLASS; + pTIImpl->TypeAttr.wMajorVerNum = 0; + pTIImpl->TypeAttr.wMinorVerNum = 0; + pTIImpl->TypeAttr.cbAlignment = 2; + pTIImpl->TypeAttr.cbSizeInstance = -1; + pTIImpl->TypeAttr.cbSizeVft = -1; + pTIImpl->TypeAttr.cFuncs = 0; + pTIImpl->TypeAttr.cImplTypes = 1; + pTIImpl->TypeAttr.cVars = 0; + pTIImpl->TypeAttr.wTypeFlags = 0; + + ppFuncDesc = &pTIImpl->funclist; + for(func = 0; func < pidata->cMembers; func++) { + METHODDATA *md = pidata->pmethdata + func; + *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc)); + (*ppFuncDesc)->Name = SysAllocString(md->szName); + (*ppFuncDesc)->funcdesc.memid = md->dispid; + (*ppFuncDesc)->funcdesc.invkind = md->wFlags; + (*ppFuncDesc)->funcdesc.callconv = md->cc; + (*ppFuncDesc)->funcdesc.cParams = md->cArgs; + (*ppFuncDesc)->funcdesc.cParamsOpt = 0; + (*ppFuncDesc)->funcdesc.oVft = md->iMeth; + (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/ + (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn; + (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + md->cArgs * sizeof(ELEMDESC)); + (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + md->cArgs * sizeof(TLBParDesc)); + for(param = 0; param < md->cArgs; param++) { + (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt; + (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName); + } + ppFuncDesc = &(*ppFuncDesc)->next; + } + *pptinfo = (ITypeInfo*)pTIImpl; + return S_OK; + +} + static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv) { ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface); @@ -5763,8 +5825,8 @@ static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface) static HRESULT WINAPI ITypeComp_fnBind( ITypeComp * iface, OLECHAR * szName, - unsigned long lHash, - unsigned short wFlags, + ULONG lHash, + WORD wFlags, ITypeInfo ** ppTInfo, DESCKIND * pDescKind, BINDPTR * pBindPtr) @@ -5831,7 +5893,7 @@ static HRESULT WINAPI ITypeComp_fnBind( static HRESULT WINAPI ITypeComp_fnBindType( ITypeComp * iface, OLECHAR * szName, - unsigned long lHash, + ULONG lHash, ITypeInfo ** ppTInfo, ITypeComp ** ppTComp) { diff --git a/reactos/lib/oleaut32/typelib2.c b/reactos/lib/oleaut32/typelib2.c index 7916c5e2ec5..a6a7d06ed02 100644 --- a/reactos/lib/oleaut32/typelib2.c +++ b/reactos/lib/oleaut32/typelib2.c @@ -35,8 +35,10 @@ #include #include +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "winerror.h" #include "windef.h" #include "winbase.h" @@ -46,7 +48,6 @@ #include "wine/unicode.h" #include "objbase.h" -#include "heap.h" #include "ole2disp.h" #include "typelib.h" #include "wine/debug.h" @@ -270,7 +271,7 @@ static int ctl2_hash_guid( hash = 0; for (i = 0; i < 8; i ++) { - hash ^= ((short *)guid)[i]; + hash ^= ((const short *)guid)[i]; } return (hash & 0xf) | ((hash & 0x10) & (0 - !!(hash & 0xe0))); diff --git a/reactos/lib/oleaut32/usrmarshal.c b/reactos/lib/oleaut32/usrmarshal.c index ae71e4dc014..585e9495451 100644 --- a/reactos/lib/oleaut32/usrmarshal.c +++ b/reactos/lib/oleaut32/usrmarshal.c @@ -22,8 +22,10 @@ #include #include +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "windef.h" #include "winbase.h" #include "wingdi.h" diff --git a/reactos/lib/oleaut32/varformat.c b/reactos/lib/oleaut32/varformat.c index 2f19ca87a1b..4319dbc7faf 100644 --- a/reactos/lib/oleaut32/varformat.c +++ b/reactos/lib/oleaut32/varformat.c @@ -35,13 +35,12 @@ #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" -#include "oleauto.h" -#include "wine/debug.h" #include "wine/unicode.h" #include "winerror.h" #include "variant.h" +#include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(ole); +WINE_DEFAULT_DEBUG_CHANNEL(variant); /* Make sure internal conversions to strings use the '.','+'/'-' and ',' * format chars from the US locale. This enables us to parse the created @@ -1387,7 +1386,7 @@ VARIANT_FormatNumber_Bool: TRACE("write %d fractional digits or skip\n", pToken[1]); for (count = 0; count < fractionalDigits; count++) - pBuff[count] = rgbDig[wholeNumberDigits + count]; + pBuff[count] = '0' + rgbDig[wholeNumberDigits + count]; pBuff += fractionalDigits; } else @@ -1417,7 +1416,7 @@ VARIANT_FormatNumber_Bool: TRACE("write %d fractional digits or 0's\n", pToken[1]); for (count = 0; count < fractionalDigits; count++) - pBuff[count] = rgbDig[wholeNumberDigits + count]; + pBuff[count] = '0' + rgbDig[wholeNumberDigits + count]; pBuff += fractionalDigits; if (pToken[1] > fractionalDigits) { diff --git a/reactos/lib/oleaut32/variant.c b/reactos/lib/oleaut32/variant.c index 2a1832ce4e5..d5a8087a88c 100644 --- a/reactos/lib/oleaut32/variant.c +++ b/reactos/lib/oleaut32/variant.c @@ -28,17 +28,18 @@ #include #include +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "windef.h" #include "winbase.h" -#include "oleauto.h" -#include "wine/debug.h" #include "wine/unicode.h" #include "winerror.h" #include "variant.h" +#include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(ole); +WINE_DEFAULT_DEBUG_CHANNEL(variant); const char* wine_vtypes[VT_CLSID] = { @@ -79,6 +80,7 @@ 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), @@ -113,7 +115,11 @@ 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; + { + vtFrom = VT_UI4; + if (vt == VT_I4) + bIgnoreOverflow = TRUE; + } if (vt == vtFrom) return VariantCopy(pd, ps); @@ -193,7 +199,14 @@ 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: return VarI4FromUI4(V_UI4(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_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)); @@ -449,7 +462,6 @@ static inline HRESULT VARIANT_Coerce(VARIANTARG* pd, LCID lcid, USHORT wFlags, case VT_DATE: return VarCyFromDate(V_DATE(ps), &V_CY(pd)); case VT_BOOL: return VarCyFromBool(V_BOOL(ps), &V_CY(pd)); case VT_DECIMAL: return VarCyFromDec(&V_DECIMAL(ps), &V_CY(pd)); - case VT_DISPATCH: return VarCyFromDisp(V_DISPATCH(ps), lcid, &V_CY(pd)); case VT_BSTR: return VarCyFromStr(V_BSTR(ps), lcid, dwFlags, &V_CY(pd)); } @@ -608,7 +620,6 @@ HRESULT WINAPI VariantClear(VARIANTARG* pVarg) if (V_BSTR(pVarg)) SysFreeString(V_BSTR(pVarg)); } -#ifndef __REACTOS__ /*FIXME: problems with MinGW and brecVal */ else if (V_VT(pVarg) == VT_RECORD) { struct __tagBRECORD* pBr = &V_UNION(pVarg,brecVal); @@ -618,7 +629,6 @@ HRESULT WINAPI VariantClear(VARIANTARG* pVarg) IRecordInfo_Release(pBr->pRecInfo); } } -#endif else if (V_VT(pVarg) == VT_DISPATCH || V_VT(pVarg) == VT_UNKNOWN) { @@ -636,7 +646,6 @@ HRESULT WINAPI VariantClear(VARIANTARG* pVarg) return hres; } -#ifndef __REACTOS__ /*FIXME: missing __tagBRECORD in MinGW */ /****************************************************************************** * Copy an IRecordInfo object contained in a variant. */ @@ -669,7 +678,6 @@ static HRESULT VARIANT_CopyIRecordInfo(struct __tagBRECORD* pBr) hres = E_INVALIDARG; return hres; } -#endif /****************************************************************************** * VariantCopy [OLEAUT32.10] @@ -735,12 +743,10 @@ HRESULT WINAPI VariantCopy(VARIANTARG* pvargDest, VARIANTARG* pvargSrc) } } } -#ifndef __REACTOS__ /*FIXME: missing __tagBRECORD in MinGW */ else if (V_VT(pvargSrc) == VT_RECORD) { hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal)); } -#endif else if (V_VT(pvargSrc) == VT_DISPATCH || V_VT(pvargSrc) == VT_UNKNOWN) { @@ -862,13 +868,11 @@ HRESULT WINAPI VariantCopyInd(VARIANT* pvargDest, VARIANTARG* pvargSrc) /* Native doesn't check that *V_BSTRREF(pSrc) is valid */ V_BSTR(pvargDest) = SysAllocStringByteLen((char*)*V_BSTRREF(pSrc), SysStringByteLen(*V_BSTRREF(pSrc))); } -#ifndef __REACTOS__ /*FIXME: missing __tagBRECORD in MinGW */ else if (V_VT(pSrc) == (VT_RECORD|VT_BYREF)) { V_UNION(pvargDest,brecVal) = V_UNION(pvargSrc,brecVal); hres = VARIANT_CopyIRecordInfo(&V_UNION(pvargDest,brecVal)); } -#endif else if (V_VT(pSrc) == (VT_DISPATCH|VT_BYREF) || V_VT(pSrc) == (VT_UNKNOWN|VT_BYREF)) { @@ -978,26 +982,35 @@ HRESULT WINAPI VariantChangeTypeEx(VARIANTARG* pvargDest, VARIANTARG* pvargSrc, if (SUCCEEDED(res)) { - VARIANTARG vTmp; + VARIANTARG vTmp, vSrcDeref; - V_VT(&vTmp) = VT_EMPTY; - res = VariantCopyInd(&vTmp, pvargSrc); + if(V_VT(pvargSrc)&VT_BYREF && !V_BYREF(pvargSrc)) + res = DISP_E_TYPEMISMATCH; + else + { + V_VT(&vTmp) = VT_EMPTY; + V_VT(&vSrcDeref) = VT_EMPTY; + VariantClear(&vTmp); + VariantClear(&vSrcDeref); + } if (SUCCEEDED(res)) { - res = VariantClear(pvargDest); - + res = VariantCopyInd(&vSrcDeref, pvargSrc); if (SUCCEEDED(res)) { - if (V_ISARRAY(&vTmp) || (vt & VT_ARRAY)) - res = VARIANT_CoerceArray(pvargDest, &vTmp, vt); + if (V_ISARRAY(&vSrcDeref) || (vt & VT_ARRAY)) + res = VARIANT_CoerceArray(&vTmp, &vSrcDeref, vt); else - res = VARIANT_Coerce(pvargDest, lcid, wFlags, &vTmp, vt); + res = VARIANT_Coerce(&vTmp, lcid, wFlags, &vSrcDeref, vt); - if (SUCCEEDED(res)) - V_VT(pvargDest) = vt; + if (SUCCEEDED(res)) { + V_VT(&vTmp) = vt; + VariantCopy(pvargDest, &vTmp); + } + VariantClear(&vTmp); + VariantClear(&vSrcDeref); } - VariantClear(&vTmp); } } } @@ -1289,12 +1302,13 @@ INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt) } /*********************************************************************** - * VarDateFromUdate [OLEAUT32.330] + * VarDateFromUdateEx [OLEAUT32.319] * * Convert an unpacked format date and time to a variant VT_DATE. * * PARAMS * pUdateIn [I] Unpacked format date and time to convert + * lcid [I] Locale identifier for the conversion * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") * pDateOut [O] Destination for variant VT_DATE. * @@ -1302,17 +1316,20 @@ INT WINAPI VariantTimeToSystemTime(double dateIn, LPSYSTEMTIME lpSt) * Success: S_OK. *pDateOut contains the converted value. * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format. */ -HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut) +HRESULT WINAPI VarDateFromUdateEx(UDATE *pUdateIn, LCID lcid, ULONG dwFlags, DATE *pDateOut) { UDATE ud; double dateVal; - TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08lx,%p)\n", pUdateIn, + TRACE("(%p->%d/%d/%d %d:%d:%d:%d %d %d,0x%08lx,0x%08lx,%p)\n", pUdateIn, pUdateIn->st.wMonth, pUdateIn->st.wDay, pUdateIn->st.wYear, pUdateIn->st.wHour, pUdateIn->st.wMinute, pUdateIn->st.wSecond, pUdateIn->st.wMilliseconds, pUdateIn->st.wDayOfWeek, - pUdateIn->wDayOfYear, dwFlags, pDateOut); + pUdateIn->wDayOfYear, lcid, dwFlags, pDateOut); + if (lcid != MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT)) + FIXME("lcid possibly not handled, treating as en-us\n"); + memcpy(&ud, pUdateIn, sizeof(ud)); if (dwFlags & VAR_VALIDDATE) @@ -1335,6 +1352,31 @@ HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut) return S_OK; } +/*********************************************************************** + * VarDateFromUdate [OLEAUT32.330] + * + * Convert an unpacked format date and time to a variant VT_DATE. + * + * PARAMS + * pUdateIn [I] Unpacked format date and time to convert + * dwFlags [I] Flags controlling the conversion (VAR_ flags from "oleauto.h") + * pDateOut [O] Destination for variant VT_DATE. + * + * RETURNS + * Success: S_OK. *pDateOut contains the converted value. + * Failure: E_INVALIDARG, if pUdateIn cannot be represented in VT_DATE format. + * + * NOTES + * This function uses the United States English locale for the conversion. Use + * VarDateFromUdateEx() for alternate locales. + */ +HRESULT WINAPI VarDateFromUdate(UDATE *pUdateIn, ULONG dwFlags, DATE *pDateOut) +{ + LCID lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); + + return VarDateFromUdateEx(pUdateIn, lcid, dwFlags, pDateOut); +} + /*********************************************************************** * VarUdateFromDate [OLEAUT32.331] * @@ -1473,6 +1515,8 @@ void VARIANT_GetLocalisedNumberChars(VARIANT_NUMBER_CHARS *lpChars, LCID lcid, D #define B_EXPONENT_START 0x4 #define B_INEXACT_ZEROS 0x8 #define B_LEADING_ZERO 0x10 +#define B_PROCESSING_HEX 0x20 +#define B_PROCESSING_OCT 0x40 /********************************************************************** * VarParseNumFromStr [OLEAUT32.46] @@ -1590,6 +1634,23 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, chars.cCurrencyDigitSeperator = chars.cDigitSeperator; } + if ((*lpszStr == '&' && (*(lpszStr+1) == 'H' || *(lpszStr+1) == 'h')) && + pNumprs->dwInFlags & NUMPRS_HEX_OCT) + { + dwState |= B_PROCESSING_HEX; + pNumprs->dwOutFlags |= NUMPRS_HEX_OCT; + cchUsed=cchUsed+2; + lpszStr=lpszStr+2; + } + else if ((*lpszStr == '&' && (*(lpszStr+1) == 'O' || *(lpszStr+1) == 'o')) && + pNumprs->dwInFlags & NUMPRS_HEX_OCT) + { + dwState |= B_PROCESSING_OCT; + pNumprs->dwOutFlags |= NUMPRS_HEX_OCT; + cchUsed=cchUsed+2; + lpszStr=lpszStr+2; + } + /* Strip Leading zeros */ while (*lpszStr == '0') { @@ -1607,14 +1668,14 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, int exponentSize = 0; if (dwState & B_EXPONENT_START) { + if (!isdigitW(*lpszStr)) + break; /* No exponent digits - invalid */ while (*lpszStr == '0') { /* Skip leading zero's in the exponent */ cchUsed++; lpszStr++; } - if (!isdigitW(*lpszStr)) - break; /* No exponent digits - invalid */ } while (isdigitW(*lpszStr)) @@ -1633,7 +1694,8 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, } else { - if (pNumprs->cDig >= iMaxDigits) + if ((pNumprs->cDig >= iMaxDigits) && !(dwState & B_PROCESSING_HEX) + && !(dwState & B_PROCESSING_OCT)) { pNumprs->dwOutFlags |= NUMPRS_INEXACT; @@ -1648,8 +1710,13 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, } else { + if ((dwState & B_PROCESSING_OCT) && ((*lpszStr == '8') || (*lpszStr == '9'))) { + return DISP_E_TYPEMISMATCH; + } + if (pNumprs->dwOutFlags & NUMPRS_DECIMAL) pNumprs->nPwr10--; /* Count decimal points in nPwr10 */ + rgbTmp[pNumprs->cDig] = *lpszStr - '0'; } pNumprs->cDig++; @@ -1668,13 +1735,6 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, pNumprs->dwOutFlags |= NUMPRS_DECIMAL; cchUsed++; - /* Remove trailing zeros from the whole number part */ - while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) - { - pNumprs->nPwr10++; - pNumprs->cDig--; - } - /* If we have no digits so far, skip leading zeros */ if (!pNumprs->cDig) { @@ -1683,6 +1743,7 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, dwState |= B_LEADING_ZERO; cchUsed++; lpszStr++; + pNumprs->nPwr10--; } } } @@ -1703,6 +1764,24 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, dwState |= B_NEGATIVE_EXPONENT; cchUsed++; } + else if (((*lpszStr >= 'a' && *lpszStr <= 'f') || + (*lpszStr >= 'A' && *lpszStr <= 'F')) && + dwState & B_PROCESSING_HEX) + { + if (pNumprs->cDig >= iMaxDigits) + { + return DISP_E_OVERFLOW; + } + else + { + if (*lpszStr >= 'a') + rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10; + else + rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10; + } + pNumprs->cDig++; + cchUsed++; + } else break; /* Stop at an unrecognised character */ @@ -1733,25 +1812,29 @@ HRESULT WINAPI VarParseNumFromStr(OLECHAR *lpszStr, LCID lcid, ULONG dwFlags, /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */ memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE)); - while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) - { - if (pNumprs->dwOutFlags & NUMPRS_DECIMAL) - pNumprs->nPwr10--; - else - pNumprs->nPwr10++; - - pNumprs->cDig--; + if (dwState & B_PROCESSING_HEX) { + /* hex numbers have always the same format */ + pNumprs->nPwr10=0; + pNumprs->nBaseShift=4; + } else { + if (dwState & B_PROCESSING_OCT) { + /* oct numbers have always the same format */ + pNumprs->nPwr10=0; + pNumprs->nBaseShift=3; + } else { + while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) + { + pNumprs->nPwr10++; + pNumprs->cDig--; + } + } } } else { /* Remove trailing zeros from the last (whole number or decimal) part */ while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1]) { - if (pNumprs->dwOutFlags & NUMPRS_DECIMAL) - pNumprs->nPwr10--; - else - pNumprs->nPwr10++; - + pNumprs->nPwr10++; pNumprs->cDig--; } } @@ -1875,7 +1958,110 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig, if (pNumprs->nBaseShift) { /* nBaseShift indicates a hex or octal number */ - FIXME("nBaseShift=%d not yet implemented, returning overflow\n", pNumprs->nBaseShift); + ULONG64 ul64 = 0; + LONG64 l64; + int i; + + /* Convert the hex or octal number string into a UI64 */ + for (i = 0; i < pNumprs->cDig; i++) + { + if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i])) + { + TRACE("Overflow multiplying digits\n"); + return DISP_E_OVERFLOW; + } + ul64 = (ul64<nBaseShift) + rgbDig[i]; + } + + /* also make a negative representation */ + l64=-ul64; + + /* Try signed and unsigned types in size order */ + if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN))) + { + V_VT(pVarDst) = VT_I1; + if (ul64 <= I1_MAX) + V_I1(pVarDst) = ul64; + else + V_I1(pVarDst) = l64; + return S_OK; + } + else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX) + { + V_VT(pVarDst) = VT_UI1; + V_UI1(pVarDst) = ul64; + return S_OK; + } + else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN))) + { + V_VT(pVarDst) = VT_I2; + if (ul64 <= I2_MAX) + V_I2(pVarDst) = ul64; + else + V_I2(pVarDst) = l64; + return S_OK; + } + else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX) + { + V_VT(pVarDst) = VT_UI2; + V_UI2(pVarDst) = ul64; + return S_OK; + } + else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) + { + V_VT(pVarDst) = VT_I4; + if (ul64 <= I4_MAX) + V_I4(pVarDst) = ul64; + else + V_I4(pVarDst) = l64; + return S_OK; + } + else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX) + { + V_VT(pVarDst) = VT_UI4; + V_UI4(pVarDst) = ul64; + return S_OK; + } + else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN))) + { + V_VT(pVarDst) = VT_I8; + V_I8(pVarDst) = ul64; + return S_OK; + } + else if (dwVtBits & VTBIT_UI8) + { + V_VT(pVarDst) = VT_UI8; + V_UI8(pVarDst) = ul64; + return S_OK; + } + else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL) + { + V_VT(pVarDst) = VT_DECIMAL; + DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0); + DEC_HI32(&V_DECIMAL(pVarDst)) = 0; + DEC_LO64(&V_DECIMAL(pVarDst)) = ul64; + return S_OK; + } + else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) + { + V_VT(pVarDst) = VT_R4; + if (ul64 <= I4_MAX) + V_R4(pVarDst) = ul64; + else + V_R4(pVarDst) = l64; + return S_OK; + } + else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN))) + { + V_VT(pVarDst) = VT_R8; + if (ul64 <= I4_MAX) + V_R8(pVarDst) = ul64; + else + V_R8(pVarDst) = l64; + return S_OK; + } + + TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64)); return DISP_E_OVERFLOW; } @@ -2146,7 +2332,7 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig, while (divisor10 > 10) { - if (whole < dblMinimums[10]) + if (whole < dblMinimums[10] && whole != 0) { dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */ bOverflow = TRUE; @@ -2157,7 +2343,7 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE *pNumprs, BYTE *rgbDig, } if (divisor10) { - if (whole < dblMinimums[divisor10]) + if (whole < dblMinimums[divisor10] && whole != 0) { dwVtBits &= ~(VTBIT_R4|VTBIT_R8|VTBIT_CY); /* Underflow */ bOverflow = TRUE; @@ -2899,84 +3085,260 @@ HRESULT WINAPI VarSub(LPVARIANT left, LPVARIANT right, LPVARIANT result) /********************************************************************** * VarOr [OLEAUT32.157] * + * Perform a logical or (OR) operation on two variants. + * + * PARAMS + * pVarLeft [I] First variant + * pVarRight [I] Variant to OR with pVarLeft + * pVarOut [O] Destination for OR result + * + * RETURNS + * Success: S_OK. pVarOut contains the result of the operation with its type + * taken from the table listed under VarXor(). + * Failure: An HRESULT error code indicating the error. + * + * NOTES + * See the Notes section of VarXor() for further information. */ -HRESULT WINAPI VarOr(LPVARIANT left, LPVARIANT right, LPVARIANT result) +HRESULT WINAPI VarOr(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) { - HRESULT rc = E_FAIL; + VARTYPE vt = VT_I4; + VARIANT varLeft, varRight, varStr; + HRESULT hRet; - TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left), - debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result); + TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft), + debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight), + debugstr_VF(pVarRight), pVarOut); - if ((V_VT(left)&VT_TYPEMASK) == VT_BOOL && - (V_VT(right)&VT_TYPEMASK) == VT_BOOL) { + if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) || + V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN || + V_VT(pVarLeft) == VT_DISPATCH || V_VT(pVarRight) == VT_DISPATCH || + V_VT(pVarLeft) == VT_RECORD || V_VT(pVarRight) == VT_RECORD) + return DISP_E_BADVARTYPE; - V_VT(result) = VT_BOOL; - if (V_BOOL(left) || V_BOOL(right)) { - V_BOOL(result) = VARIANT_TRUE; - } else { - V_BOOL(result) = VARIANT_FALSE; - } - rc = S_OK; + V_VT(&varLeft) = V_VT(&varRight) = V_VT(&varStr) = VT_EMPTY; - } 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, even unsigned ints (incl. UI2) */ + if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL) + { + /* NULL OR Zero is NULL, NULL OR value is value */ + if (V_VT(pVarLeft) == VT_NULL) + pVarLeft = pVarRight; /* point to the non-NULL var */ - lOk = TRUE; - switch (V_VT(left)&VT_TYPEMASK) { - case VT_I1 : lVal = V_UNION(left,cVal); resT=VT_I4; break; - case VT_I2 : lVal = V_UNION(left,iVal); resT=VT_I2; break; - case VT_I4 : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_INT : lVal = V_UNION(left,lVal); resT=VT_I4; break; - case VT_UI1 : lVal = V_UNION(left,bVal); resT=VT_I4; break; - case VT_UI2 : lVal = V_UNION(left,uiVal); resT=VT_I4; break; - case VT_UI4 : lVal = V_UNION(left,ulVal); resT=VT_I4; break; - case VT_UINT : lVal = V_UNION(left,ulVal); resT=VT_I4; break; - case VT_BOOL : lVal = V_UNION(left,boolVal); resT=VT_I4; break; - default: lOk = FALSE; - } + V_VT(pVarOut) = VT_NULL; + V_I4(pVarOut) = 0; - rOk = TRUE; - switch (V_VT(right)&VT_TYPEMASK) { - case VT_I1 : rVal = V_UNION(right,cVal); resT=VT_I4; break; - case VT_I2 : rVal = V_UNION(right,iVal); resT=max(VT_I2, resT); break; - case VT_I4 : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_INT : rVal = V_UNION(right,lVal); resT=VT_I4; break; - case VT_UI1 : rVal = V_UNION(right,bVal); resT=VT_I4; break; - case VT_UI2 : rVal = V_UNION(right,uiVal); resT=VT_I4; break; - case VT_UI4 : rVal = V_UNION(right,ulVal); resT=VT_I4; break; - case VT_UINT : rVal = V_UNION(right,ulVal); resT=VT_I4; break; - case VT_BOOL : rVal = V_UNION(right,boolVal); resT=VT_I4; break; - default: rOk = FALSE; - } + switch (V_VT(pVarLeft)) + { + case VT_DATE: case VT_R8: + if (V_R8(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_BOOL: + if (V_BOOL(pVarLeft)) + *pVarOut = *pVarLeft; + return S_OK; + case VT_I2: case VT_UI2: + if (V_I2(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_I1: + if (V_I1(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_UI1: + if (V_UI1(pVarLeft)) + *pVarOut = *pVarLeft; + return S_OK; + case VT_R4: + if (V_R4(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_I4: case VT_UI4: case VT_INT: case VT_UINT: + if (V_I4(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_CY: + if (V_CY(pVarLeft).int64) + goto VarOr_AsEmpty; + return S_OK; + case VT_I8: case VT_UI8: + if (V_I8(pVarLeft)) + goto VarOr_AsEmpty; + return S_OK; + case VT_DECIMAL: + if (DEC_HI32(&V_DECIMAL(pVarLeft)) || DEC_LO64(&V_DECIMAL(pVarLeft))) + goto VarOr_AsEmpty; + return S_OK; + case VT_BSTR: + { + VARIANT_BOOL b; - if (lOk && rOk) { - res = (lVal | rVal); - V_VT(result) = resT; - switch (resT) { - case VT_I2 : V_UNION(result,iVal) = res; break; - case VT_I4 : V_UNION(result,lVal) = res; break; - default: - FIXME("Unexpected result variant type %x\n", resT); - V_UNION(result,lVal) = res; + if (!V_BSTR(pVarLeft)) + return DISP_E_BADVARTYPE; + + hRet = VarBoolFromStr(V_BSTR(pVarLeft), LOCALE_USER_DEFAULT, VAR_LOCALBOOL, &b); + if (SUCCEEDED(hRet) && b) + { + V_VT(pVarOut) = VT_BOOL; + V_BOOL(pVarOut) = b; } - rc = S_OK; - - } else { - FIXME("unimplemented part, V_VT(left) == 0x%X, V_VT(right) == 0x%X\n", - V_VT(left) & VT_TYPEMASK, V_VT(right) & VT_TYPEMASK); + return hRet; + } + case VT_NULL: case VT_EMPTY: + V_VT(pVarOut) = VT_NULL; + return S_OK; + default: + return DISP_E_BADVARTYPE; } } - 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; + if (V_VT(pVarLeft) == VT_EMPTY || V_VT(pVarRight) == VT_EMPTY) + { + if (V_VT(pVarLeft) == VT_EMPTY) + pVarLeft = pVarRight; /* point to the non-EMPTY var */ + +VarOr_AsEmpty: + /* Since one argument is empty (0), OR'ing it with the other simply + * gives the others value (as 0|x => x). So just convert the other + * argument to the required result type. + */ + switch (V_VT(pVarLeft)) + { + case VT_BSTR: + if (!V_BSTR(pVarLeft)) + return DISP_E_BADVARTYPE; + + hRet = VariantCopy(&varStr, pVarLeft); + if (FAILED(hRet)) + goto VarOr_Exit; + pVarLeft = &varStr; + hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL); + if (FAILED(hRet)) + goto VarOr_Exit; + /* Fall Through ... */ + case VT_EMPTY: case VT_UI1: case VT_BOOL: case VT_I2: + V_VT(pVarOut) = VT_I2; + break; + case VT_DATE: case VT_CY: case VT_DECIMAL: case VT_R4: case VT_R8: + case VT_I1: case VT_UI2: case VT_I4: case VT_UI4: + case VT_INT: case VT_UINT: case VT_UI8: + V_VT(pVarOut) = VT_I4; + break; + case VT_I8: + V_VT(pVarOut) = VT_I8; + break; + default: + return DISP_E_BADVARTYPE; + } + hRet = VariantCopy(&varLeft, pVarLeft); + if (FAILED(hRet)) + goto VarOr_Exit; + pVarLeft = &varLeft; + hRet = VariantChangeType(pVarOut, pVarLeft, 0, V_VT(pVarOut)); + goto VarOr_Exit; + } + + if (V_VT(pVarLeft) == VT_BOOL && V_VT(pVarRight) == VT_BOOL) + { + V_VT(pVarOut) = VT_BOOL; + V_BOOL(pVarOut) = V_BOOL(pVarLeft) | V_BOOL(pVarRight); + return S_OK; + } + + if (V_VT(pVarLeft) == VT_UI1 && V_VT(pVarRight) == VT_UI1) + { + V_VT(pVarOut) = VT_UI1; + V_UI1(pVarOut) = V_UI1(pVarLeft) | V_UI1(pVarRight); + return S_OK; + } + + if (V_VT(pVarLeft) == VT_BSTR) + { + hRet = VariantCopy(&varStr, pVarLeft); + if (FAILED(hRet)) + goto VarOr_Exit; + pVarLeft = &varStr; + hRet = VariantChangeType(pVarLeft, pVarLeft, 0, VT_BOOL); + if (FAILED(hRet)) + goto VarOr_Exit; + } + + if (V_VT(pVarLeft) == VT_BOOL && + (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_BSTR)) + { + vt = VT_BOOL; + } + else if ((V_VT(pVarLeft) == VT_BOOL || V_VT(pVarLeft) == VT_UI1 || + V_VT(pVarLeft) == VT_I2 || V_VT(pVarLeft) == VT_BSTR) && + (V_VT(pVarRight) == VT_BOOL || V_VT(pVarRight) == VT_UI1 || + V_VT(pVarRight) == VT_I2 || V_VT(pVarRight) == VT_BSTR)) + { + vt = VT_I2; + } + else if (V_VT(pVarLeft) == VT_I8 || V_VT(pVarRight) == VT_I8) + { + if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT) + return DISP_E_TYPEMISMATCH; + vt = VT_I8; + } + + hRet = VariantCopy(&varLeft, pVarLeft); + if (FAILED(hRet)) + goto VarOr_Exit; + + hRet = VariantCopy(&varRight, pVarRight); + if (FAILED(hRet)) + goto VarOr_Exit; + + if (vt == VT_I4 && V_VT(&varLeft) == VT_UI4) + V_VT(&varLeft) = VT_I4; /* Don't overflow */ + else + { + double d; + + if (V_VT(&varLeft) == VT_BSTR && + FAILED(VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d))) + hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, VT_BOOL); + if (SUCCEEDED(hRet) && V_VT(&varLeft) != vt) + hRet = VariantChangeType(&varLeft, &varLeft, 0, vt); + if (FAILED(hRet)) + goto VarOr_Exit; + } + + if (vt == VT_I4 && V_VT(&varRight) == VT_UI4) + V_VT(&varRight) = VT_I4; /* Don't overflow */ + else + { + double d; + + if (V_VT(&varRight) == VT_BSTR && + FAILED(VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d))) + hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, VT_BOOL); + if (SUCCEEDED(hRet) && V_VT(&varRight) != vt) + hRet = VariantChangeType(&varRight, &varRight, 0, vt); + if (FAILED(hRet)) + goto VarOr_Exit; + } + + V_VT(pVarOut) = vt; + if (vt == VT_I8) + { + V_I8(pVarOut) = V_I8(&varLeft) | V_I8(&varRight); + } + else if (vt == VT_I4) + { + V_I4(pVarOut) = V_I4(&varLeft) | V_I4(&varRight); + } + else + { + V_I2(pVarOut) = V_I2(&varLeft) | V_I2(&varRight); + } + +VarOr_Exit: + VariantClear(&varStr); + VariantClear(&varLeft); + VariantClear(&varRight); + return hRet; } /********************************************************************** @@ -3053,10 +3415,13 @@ HRESULT WINAPI VarAbs(LPVARIANT pVarIn, LPVARIANT pVarOut) case VT_UINT: case VT_UI4: case VT_UI8: - case VT_EMPTY: - case VT_NULL: /* No-Op */ break; + case VT_EMPTY: + V_VT(pVarOut) = VT_I2; + case VT_NULL: + V_I2(pVarOut) = 0; + break; default: hRet = DISP_E_BADVARTYPE; } @@ -3220,6 +3585,211 @@ HRESULT WINAPI VarInt(LPVARIANT pVarIn, LPVARIANT pVarOut) return hRet; } +/********************************************************************** + * VarXor [OLEAUT32.167] + * + * Perform a logical exclusive-or (XOR) operation on two variants. + * + * PARAMS + * pVarLeft [I] First variant + * pVarRight [I] Variant to XOR with pVarLeft + * pVarOut [O] Destination for XOR result + * + * RETURNS + * Success: S_OK. pVarOut contains the result of the operation with its type + * taken from the table below). + * Failure: An HRESULT error code indicating the error. + * + * NOTES + * - Neither pVarLeft or pVarRight are modified by this function. + * - This function does not process by-reference variants. + * - Input types of VT_BSTR may be numeric strings or boolean text. + * - The type of result stored in pVarOut depends on the types of pVarLeft + * and pVarRight, and will be one of VT_UI1, VT_I2, VT_I4, VT_I8, VT_BOOL, + * or VT_NULL if the function succeeds. + * - Type promotion is inconsistent and as a result certain combinations of + * values will return DISP_E_OVERFLOW even when they could be represented. + * This matches the behaviour of native oleaut32. + */ +HRESULT WINAPI VarXor(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) +{ + VARTYPE vt; + VARIANT varLeft, varRight; + double d; + HRESULT hRet; + + TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft), + debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight), + debugstr_VF(pVarRight), pVarOut); + + if (V_EXTRA_TYPE(pVarLeft) || V_EXTRA_TYPE(pVarRight) || + V_VT(pVarLeft) > VT_UINT || V_VT(pVarRight) > VT_UINT || + V_VT(pVarLeft) == VT_VARIANT || V_VT(pVarRight) == VT_VARIANT || + V_VT(pVarLeft) == VT_UNKNOWN || V_VT(pVarRight) == VT_UNKNOWN || + V_VT(pVarLeft) == (VARTYPE)15 || V_VT(pVarRight) == (VARTYPE)15 || + V_VT(pVarLeft) == VT_ERROR || V_VT(pVarRight) == VT_ERROR) + return DISP_E_BADVARTYPE; + + if (V_VT(pVarLeft) == VT_NULL || V_VT(pVarRight) == VT_NULL) + { + /* NULL XOR anything valid is NULL */ + V_VT(pVarOut) = VT_NULL; + return S_OK; + } + + /* Copy our inputs so we don't disturb anything */ + V_VT(&varLeft) = V_VT(&varRight) = VT_EMPTY; + + hRet = VariantCopy(&varLeft, pVarLeft); + if (FAILED(hRet)) + goto VarXor_Exit; + + hRet = VariantCopy(&varRight, pVarRight); + if (FAILED(hRet)) + goto VarXor_Exit; + + /* Try any strings first as numbers, then as VT_BOOL */ + if (V_VT(&varLeft) == VT_BSTR) + { + hRet = VarR8FromStr(V_BSTR(&varLeft), LOCALE_USER_DEFAULT, 0, &d); + hRet = VariantChangeType(&varLeft, &varLeft, VARIANT_LOCALBOOL, + FAILED(hRet) ? VT_BOOL : VT_I4); + if (FAILED(hRet)) + goto VarXor_Exit; + } + + if (V_VT(&varRight) == VT_BSTR) + { + hRet = VarR8FromStr(V_BSTR(&varRight), LOCALE_USER_DEFAULT, 0, &d); + hRet = VariantChangeType(&varRight, &varRight, VARIANT_LOCALBOOL, + FAILED(hRet) ? VT_BOOL : VT_I4); + if (FAILED(hRet)) + goto VarXor_Exit; + } + + /* Determine the result type */ + if (V_VT(&varLeft) == VT_I8 || V_VT(&varRight) == VT_I8) + { + if (V_VT(pVarLeft) == VT_INT || V_VT(pVarRight) == VT_INT) + return DISP_E_TYPEMISMATCH; + vt = VT_I8; + } + else + { + switch ((V_VT(&varLeft) << 16) | V_VT(&varRight)) + { + case (VT_BOOL << 16) | VT_BOOL: + vt = VT_BOOL; + break; + case (VT_UI1 << 16) | VT_UI1: + vt = VT_UI1; + break; + case (VT_EMPTY << 16) | VT_EMPTY: + case (VT_EMPTY << 16) | VT_UI1: + case (VT_EMPTY << 16) | VT_I2: + case (VT_EMPTY << 16) | VT_BOOL: + case (VT_UI1 << 16) | VT_EMPTY: + case (VT_UI1 << 16) | VT_I2: + case (VT_UI1 << 16) | VT_BOOL: + case (VT_I2 << 16) | VT_EMPTY: + case (VT_I2 << 16) | VT_UI1: + case (VT_I2 << 16) | VT_I2: + case (VT_I2 << 16) | VT_BOOL: + case (VT_BOOL << 16) | VT_EMPTY: + case (VT_BOOL << 16) | VT_UI1: + case (VT_BOOL << 16) | VT_I2: + vt = VT_I2; + break; + default: + vt = VT_I4; + break; + } + } + + /* VT_UI4 does not overflow */ + if (vt != VT_I8) + { + if (V_VT(&varLeft) == VT_UI4) + V_VT(&varLeft) = VT_I4; + if (V_VT(&varRight) == VT_UI4) + V_VT(&varRight) = VT_I4; + } + + /* Convert our input copies to the result type */ + if (V_VT(&varLeft) != vt) + hRet = VariantChangeType(&varLeft, &varLeft, 0, vt); + if (FAILED(hRet)) + goto VarXor_Exit; + + if (V_VT(&varRight) != vt) + hRet = VariantChangeType(&varRight, &varRight, 0, vt); + if (FAILED(hRet)) + goto VarXor_Exit; + + V_VT(pVarOut) = vt; + + /* Calculate the result */ + switch (vt) + { + case VT_I8: + V_I8(pVarOut) = V_I8(&varLeft) ^ V_I8(&varRight); + break; + case VT_I4: + V_I4(pVarOut) = V_I4(&varLeft) ^ V_I4(&varRight); + break; + case VT_BOOL: + case VT_I2: + V_I2(pVarOut) = V_I2(&varLeft) ^ V_I2(&varRight); + break; + case VT_UI1: + V_UI1(pVarOut) = V_UI1(&varLeft) ^ V_UI1(&varRight); + break; + } + +VarXor_Exit: + VariantClear(&varLeft); + VariantClear(&varRight); + return hRet; +} + +/********************************************************************** + * VarEqv [OLEAUT32.172] + * + * Determine if two variants contain the same value. + * + * PARAMS + * pVarLeft [I] First variant to compare + * pVarRight [I] Variant to compare to pVarLeft + * pVarOut [O] Destination for comparison result + * + * RETURNS + * Success: S_OK. pVarOut contains the result of the comparison (VARIANT_TRUE + * if equivalent or non-zero otherwise. + * Failure: An HRESULT error code indicating the error. + * + * NOTES + * - This function simply calls VarXor() on pVarLeft and pVarRight and inverts + * the result. + */ +HRESULT WINAPI VarEqv(LPVARIANT pVarLeft, LPVARIANT pVarRight, LPVARIANT pVarOut) +{ + HRESULT hRet; + + TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", pVarLeft, debugstr_VT(pVarLeft), + debugstr_VF(pVarLeft), pVarRight, debugstr_VT(pVarRight), + debugstr_VF(pVarRight), pVarOut); + + hRet = VarXor(pVarLeft, pVarRight, pVarOut); + if (SUCCEEDED(hRet)) + { + if (V_VT(pVarOut) == VT_I8) + V_I8(pVarOut) = ~V_I8(pVarOut); + else + V_UI4(pVarOut) = ~V_UI4(pVarOut); + } + return hRet; +} + /********************************************************************** * VarNeg [OLEAUT32.173] * @@ -3366,6 +3936,7 @@ HRESULT WINAPI VarNeg(LPVARIANT pVarIn, LPVARIANT pVarOut) * according to the following table: *| Input Type Output Type *| ---------- ----------- + *| VT_EMPTY VT_I2 *| VT_R4 VT_I4 *| VT_R8 VT_I4 *| VT_BSTR VT_I4 @@ -3385,24 +3956,37 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) switch (V_VT(pVarIn)) { - case VT_I1: V_I1(pVarOut) = ~V_I1(pVarIn); break; + case VT_I1: + V_I4(pVarOut) = ~V_I1(pVarIn); + V_VT(pVarOut) = VT_I4; + break; case VT_UI1: V_UI1(pVarOut) = ~V_UI1(pVarIn); break; case VT_BOOL: case VT_I2: V_I2(pVarOut) = ~V_I2(pVarIn); break; - case VT_UI2: V_UI2(pVarOut) = ~V_UI2(pVarIn); break; + case VT_UI2: + V_I4(pVarOut) = ~V_UI2(pVarIn); + V_VT(pVarOut) = VT_I4; + break; case VT_DECIMAL: hRet = VarI4FromDec(&V_DECIMAL(pVarIn), &V_I4(&varIn)); if (FAILED(hRet)) break; pVarIn = &varIn; - V_VT(pVarOut) = VT_I4; /* Fall through ... */ case VT_INT: + V_VT(pVarOut) = VT_I4; + /* Fall through ... */ case VT_I4: V_I4(pVarOut) = ~V_I4(pVarIn); break; case VT_UINT: - case VT_UI4: V_UI4(pVarOut) = ~V_UI4(pVarIn); break; + case VT_UI4: + V_I4(pVarOut) = ~V_UI4(pVarIn); + V_VT(pVarOut) = VT_I4; + break; case VT_I8: V_I8(pVarOut) = ~V_I8(pVarIn); break; - case VT_UI8: V_UI8(pVarOut) = ~V_UI8(pVarIn); break; + case VT_UI8: + V_I4(pVarOut) = ~V_UI8(pVarIn); + V_VT(pVarOut) = VT_I4; + break; case VT_R4: hRet = VarI4FromR4(V_R4(pVarIn), &V_I4(pVarOut)); V_I4(pVarOut) = ~V_I4(pVarOut); @@ -3426,6 +4010,9 @@ HRESULT WINAPI VarNot(LPVARIANT pVarIn, LPVARIANT pVarOut) V_VT(pVarOut) = VT_I4; break; case VT_EMPTY: + V_I2(pVarOut) = ~0; + V_VT(pVarOut) = VT_I2; + break; case VT_NULL: /* No-Op */ break; diff --git a/reactos/lib/oleaut32/variant.h b/reactos/lib/oleaut32/variant.h index e096f8e8c3e..7bf6a510ecf 100644 --- a/reactos/lib/oleaut32/variant.h +++ b/reactos/lib/oleaut32/variant.h @@ -21,10 +21,10 @@ #define NONAMELESSSTRUCT #include "windef.h" #include "winerror.h" +#include "objbase.h" #include "oleauto.h" #include - /* Get just the type from a variant pointer */ #define V_TYPE(v) (V_VT((v)) & VT_TYPEMASK) @@ -82,15 +82,13 @@ extern const char* wine_vflags[]; #endif /* Macros for getting at a DECIMAL's parts */ -#ifndef DEC_LO64 -#define DEC_SIGN(d) ((d)->u.s.sign) -#define DEC_SCALE(d) ((d)->u.s.scale) -#define DEC_SIGNSCALE(d) ((d)->u.signscale) +#define DEC_SIGN(d) ((d)->sign) +#define DEC_SCALE(d) ((d)->scale) +#define DEC_SIGNSCALE(d) ((d)->signscale) #define DEC_HI32(d) ((d)->Hi32) -#define DEC_MID32(d) ((d)->DUMMYUNIONNAME2.DUMMYSTRUCTNAME2.Mid32) -#define DEC_LO32(d) ((d)->DUMMYUNIONNAME2.DUMMYSTRUCTNAME2.Lo32) -#define DEC_LO64(d) ((d)->DUMMYUNIONNAME2.Lo64) -#endif +#define DEC_MID32(d) ((d)->Mid32) +#define DEC_LO32(d) ((d)->Lo32) +#define DEC_LO64(d) ((d)->Lo64) #define DEC_MAX_SCALE 28 /* Maximum scale for a decimal */ diff --git a/reactos/lib/oleaut32/vartype.c b/reactos/lib/oleaut32/vartype.c index 219a7b7d977..940d1b7fca0 100644 --- a/reactos/lib/oleaut32/vartype.c +++ b/reactos/lib/oleaut32/vartype.c @@ -17,8 +17,11 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define COBJMACROS #define NONAMELESSUNION #define NONAMELESSSTRUCT + #include "wine/debug.h" #include "wine/unicode.h" #include "winbase.h" @@ -27,7 +30,7 @@ #include "variant.h" #include "resource.h" -WINE_DEFAULT_DEBUG_CHANNEL(ole); +WINE_DEFAULT_DEBUG_CHANNEL(variant); extern HMODULE OLEAUT32_hModule; @@ -1356,7 +1359,7 @@ HRESULT WINAPI VarI4FromUI1(BYTE bIn, LONG *piOut) * Convert a VT_I2 to a VT_I4. * * PARAMS - * iIn [I] Source + * sIn [I] Source * piOut [O] Destination * * RETURNS @@ -3848,7 +3851,7 @@ HRESULT WINAPI VarCyRound(const CY cyIn, int cDecimals, CY* pCyOut) * RETURNS * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that the value to * compare is less, equal or greater than source respectively. - * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason + * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison */ HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight) { @@ -3882,7 +3885,7 @@ HRESULT WINAPI VarCyCmp(const CY cyLeft, const CY cyRight) * RETURNS * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight is * less than, equal to or greater than cyLeft respectively. - * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason + * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison */ HRESULT WINAPI VarCyCmpR8(const CY cyLeft, double dblRight) { @@ -4574,7 +4577,7 @@ HRESULT WINAPI VarDecAbs(const DECIMAL* pDecIn, DECIMAL* pDecOut) */ HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut) { - if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG) + if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) return E_INVALIDARG; if (!DEC_SCALE(pDecIn)) @@ -4606,10 +4609,10 @@ HRESULT WINAPI VarDecFix(const DECIMAL* pDecIn, DECIMAL* pDecOut) */ HRESULT WINAPI VarDecInt(const DECIMAL* pDecIn, DECIMAL* pDecOut) { - if (DEC_SIGN(pDecOut) & ~DECIMAL_NEG) + if (DEC_SIGN(pDecIn) & ~DECIMAL_NEG) return E_INVALIDARG; - if (!(DEC_SIGN(pDecOut) & DECIMAL_NEG) || !DEC_SCALE(pDecIn)) + if (!(DEC_SIGN(pDecIn) & DECIMAL_NEG) || !DEC_SCALE(pDecIn)) return VarDecFix(pDecIn, pDecOut); /* The same, if +ve or no fractionals */ FIXME("semi-stub!\n"); @@ -4677,7 +4680,7 @@ HRESULT WINAPI VarDecRound(const DECIMAL* pDecIn, int cDecimals, DECIMAL* pDecOu * RETURNS * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that pDecLeft * is less than, equal to or greater than pDecRight respectively. - * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason + * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison */ HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight) { @@ -4713,7 +4716,7 @@ HRESULT WINAPI VarDecCmp(const DECIMAL* pDecLeft, const DECIMAL* pDecRight) * RETURNS * Success: VARCMP_LT, VARCMP_EQ or VARCMP_GT indicating that dblRight * is less than, equal to or greater than pDecLeft respectively. - * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparason + * Failure: DISP_E_OVERFLOW, if overflow occurs during the comparison */ HRESULT WINAPI VarDecCmpR8(const DECIMAL* pDecLeft, double dblRight) { @@ -5706,7 +5709,7 @@ HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut) * PARAMS * pbstrLeft [I] Source * pbstrRight [I] Value to compare - * lcid [I] LCID for the comparason + * lcid [I] LCID for the comparison * dwFlags [I] Flags to pass directly to CompareStringW(). * * RETURNS diff --git a/reactos/lib/oleaut32/winehq2ros.patch b/reactos/lib/oleaut32/winehq2ros.patch new file mode 100644 index 00000000000..440e5bc67ae --- /dev/null +++ b/reactos/lib/oleaut32/winehq2ros.patch @@ -0,0 +1,33 @@ +--- variant.c Thu Dec 2 19:30:53 2004 ++++ variant.c Thu Dec 2 19:38:26 2004 +@@ -2390,7 +2390,7 @@ + ULONG64 tmp; + DECIMAL* pDec = &V_DECIMAL(pVarDst); + +- DECIMAL_SETZERO(pDec); ++ DECIMAL_SETZERO(*pDec); + DEC_LO32(pDec) = 0; + + if (pNumprs->dwOutFlags & NUMPRS_NEG) +--- variant.h Mon Aug 23 07:35:19 2004 ++++ variant.h Thu Dec 2 19:43:06 2004 +@@ -82,13 +82,13 @@ + #endif + + /* Macros for getting at a DECIMAL's parts */ +-#define DEC_SIGN(d) ((d)->u.s.sign) +-#define DEC_SCALE(d) ((d)->u.s.scale) +-#define DEC_SIGNSCALE(d) ((d)->u.signscale) ++#define DEC_SIGN(d) ((d)->sign) ++#define DEC_SCALE(d) ((d)->scale) ++#define DEC_SIGNSCALE(d) ((d)->signscale) + #define DEC_HI32(d) ((d)->Hi32) +-#define DEC_MID32(d) ((d)->u1.s1.Mid32) +-#define DEC_LO32(d) ((d)->u1.s1.Lo32) +-#define DEC_LO64(d) ((d)->u1.Lo64) ++#define DEC_MID32(d) ((d)->Mid32) ++#define DEC_LO32(d) ((d)->Lo32) ++#define DEC_LO64(d) ((d)->Lo64) + + #define DEC_MAX_SCALE 28 /* Maximum scale for a decimal */ + diff --git a/reactos/w32api/include/oaidl.h b/reactos/w32api/include/oaidl.h index cc271c89a35..f33f0fba779 100644 --- a/reactos/w32api/include/oaidl.h +++ b/reactos/w32api/include/oaidl.h @@ -11,9 +11,10 @@ extern "C" { #define __VARIANT_NAME_1 n1 #define __VARIANT_NAME_2 n2 #define __VARIANT_NAME_3 n3 -#define __VARIANT_NAME_4 n4 +#define __VARIANT_NAME_4 brecVal #else #define __tagVARIANT +#define __tagBRECORD #define __VARIANT_NAME_1 #define __VARIANT_NAME_2 #define __VARIANT_NAME_3 @@ -238,7 +239,7 @@ typedef struct tagVARIANT { ULONG *pulVal; INT *pintVal; UINT *puintVal; - _ANONYMOUS_STRUCT struct { + _ANONYMOUS_STRUCT struct __tagBRECORD { PVOID pvRecord; struct IRecordInfo *pRecInfo; } __VARIANT_NAME_4; diff --git a/reactos/w32api/include/oleauto.h b/reactos/w32api/include/oleauto.h index c68d2356492..f1ff738ed0e 100644 --- a/reactos/w32api/include/oleauto.h +++ b/reactos/w32api/include/oleauto.h @@ -37,9 +37,13 @@ #if __STDC__ || defined(NONAMELESSUNION) #define V_UNION(X,Y) ((X)->__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.Y) #define V_VT(X) ((X)->__VARIANT_NAME_1.__VARIANT_NAME_2.vt) +#define V_RECORDINFO(X) ((X)->__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.__VARIANT_NAME_4.pRecInfo) +#define V_RECORD(X) ((X)->__VARIANT_NAME_1.__VARIANT_NAME_2.__VARIANT_NAME_3.__VARIANT_NAME_4.pvRecord) #else #define V_UNION(X,Y) ((X)->Y) #define V_VT(X) ((X)->vt) +#define V_RECORDINFO(X) ((X)->pRecInfo) +#define V_RECORD(X) ((X)->pvRecord) #endif #define V_BOOL(X) V_UNION(X,boolVal) #define V_ISBYREF(X) (V_VT(X)&VT_BYREF) diff --git a/reactos/w32api/include/winuser.h b/reactos/w32api/include/winuser.h index 021def4a795..1926d22fbed 100644 --- a/reactos/w32api/include/winuser.h +++ b/reactos/w32api/include/winuser.h @@ -845,6 +845,10 @@ extern "C" { #define COLOR_HOTLIGHT 26 #define COLOR_GRADIENTACTIVECAPTION 27 #define COLOR_GRADIENTINACTIVECAPTION 28 +#if WINVER >= 0x0501 +#define COLOR_MENUHILIGHT 29 +#define COLOR_MENUBAR 30 +#endif #define CTLCOLOR_MSGBOX 0 #define CTLCOLOR_EDIT 1 #define CTLCOLOR_LISTBOX 2 diff --git a/reactos/w32api/include/wtypes.h b/reactos/w32api/include/wtypes.h index 326964273eb..aa749e0209e 100644 --- a/reactos/w32api/include/wtypes.h +++ b/reactos/w32api/include/wtypes.h @@ -11,23 +11,6 @@ extern "C" { #endif -#ifdef NONAMELESSUNION -#define DEC_SIGN(d) ((d)->DUMMYUNIONNAME.DUMMYSTRUCTNAME.sign) -#define DEC_SCALE(d) ((d)->DUMMYUNIONNAME.DUMMYSTRUCTNAME.scale) -#define DEC_SIGNSCALE(d) ((d)->DUMMYUNIONNAME.signscale) -#define DEC_MID32(d) ((d)->DUMMYUNIONNAME2.DUMMYSTRUCTNAME2.Mid32) -#define DEC_LO32(d) ((d)->DUMMYUNIONNAME2.DUMMYSTRUCTNAME2.Lo32) -#define DEC_LO64(d) ((d)->DUMMYUNIONNAME2.Lo64) -#else -#define DEC_SIGN(d) ((d)->sign) -#define DEC_SCALE(d) ((d)->scale) -#define DEC_SIGNSCALE(d) ((d)->signscale) -#define DEC_MID32(d) ((d)->Mid32) -#define DEC_LO32(d) ((d)->Lo32) -#define DEC_LO64(d) ((d)->Lo64) -#endif -#define DEC_HI32(d) ((d)->Hi32) - #define IID_NULL GUID_NULL #define CLSID_NULL GUID_NULL #define CBPCLIPDATA(d) ((d).cbSize-sizeof((d).ulClipFmt)) @@ -160,21 +143,21 @@ typedef struct _HYPER_SIZEDARR { typedef double DOUBLE; typedef struct tagDEC { USHORT wReserved; - _ANONYMOUS_UNION union { - _ANONYMOUS_STRUCT struct { + union { + struct { BYTE scale; BYTE sign; - }_STRUCT_NAME(s); + }; USHORT signscale; - } DUMMYUNIONNAME; + }; ULONG Hi32; - _ANONYMOUS_UNION union { - _ANONYMOUS_STRUCT struct { + union { + struct { ULONG Lo32; ULONG Mid32; - }_STRUCT_NAME(s2); + }; ULONGLONG Lo64; - } DUMMYUNIONNAME2; + }; } DECIMAL; typedef void *HMETAFILEPICT; #ifdef __cplusplus