Created
April 24, 2015 22:24
-
-
Save DrYak/81f73fff0d572130ff9d to your computer and use it in GitHub Desktop.
disphelper patch - for wine and byref support - split source
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/source/convert.c b/source/convert.c | |
index ae61fe4..0c85ef9 100644 | |
--- a/source/convert.c | |
+++ b/source/convert.c | |
@@ -25,13 +25,13 @@ | |
#include <math.h> | |
/* Number of 100 nannosecond units in a FILETIME day */ | |
-static const LONGLONG FILE_TIME_ONE_DAY = 864000000000; | |
+static const LONGLONG FILE_TIME_ONE_DAY = 864000000000LL; | |
/* VARIANT DATE 0 (1899-Dec-30) as a FILETIME */ | |
-static const LONGLONG FILE_TIME_VARIANT_DAY0 = 94353120000000000; | |
+static const LONGLONG FILE_TIME_VARIANT_DAY0 = 94353120000000000LL; | |
/* FILETIME of day 1, year 10,000 */ | |
-static const ULONGLONG FILE_TIME_VARIANT_OVERFLOW = 2650467744000000000; | |
+static const ULONGLONG FILE_TIME_VARIANT_OVERFLOW = 2650467744000000000ULL; | |
/* FILETIME date 0 (1601-Jan-1) as a VARIANT DATE */ | |
static const DATE VARIANT_FILE_TIME_DAY0 = -109205; | |
diff --git a/source/dh_enum.c b/source/dh_enum.c | |
index 406df09..67e2e42 100644 | |
--- a/source/dh_enum.c | |
+++ b/source/dh_enum.c | |
@@ -60,10 +60,10 @@ HRESULT dhEnumBeginV(IEnumVARIANT ** ppEnum, IDispatch * pDisp, LPCOLESTR szMemb | |
if (FAILED(hr)) return DH_EXITEX(hr, TRUE, L"_NewEnum", szMember, &excep, 0); | |
/* Retrieve an IEnumVariant interface from the returned interface */ | |
- if (vtResult.vt == VT_DISPATCH) | |
- hr = vtResult.pdispVal->lpVtbl->QueryInterface(vtResult.pdispVal, &IID_IEnumVARIANT, (void **) ppEnum); | |
- else if (vtResult.vt == VT_UNKNOWN) | |
- hr = vtResult.punkVal->lpVtbl->QueryInterface(vtResult.punkVal, &IID_IEnumVARIANT, (void **) ppEnum); | |
+ if (V_VT(&vtResult) == VT_DISPATCH) | |
+ hr = V_DISPATCH(&vtResult)->lpVtbl->QueryInterface(V_DISPATCH(&vtResult), &IID_IEnumVARIANT, (void **) ppEnum); | |
+ else if (V_VT(&vtResult) == VT_UNKNOWN) | |
+ hr = V_UNKNOWN(&vtResult)->lpVtbl->QueryInterface(V_UNKNOWN(&vtResult), &IID_IEnumVARIANT, (void **) ppEnum); | |
else | |
hr = E_NOINTERFACE; | |
@@ -112,14 +112,14 @@ HRESULT dhEnumNextObject(IEnumVARIANT * pEnum, IDispatch ** ppDisp) | |
if (hr == S_OK) | |
{ | |
- if (vtResult.vt == VT_DISPATCH) | |
+ if (V_VT(&vtResult) == VT_DISPATCH) | |
{ | |
- *ppDisp = vtResult.pdispVal; | |
+ *ppDisp = V_DISPATCH(&vtResult); | |
} | |
else | |
{ | |
hr = VariantChangeType(&vtResult, &vtResult, 0, VT_DISPATCH); | |
- if (SUCCEEDED(hr)) *ppDisp = vtResult.pdispVal; | |
+ if (SUCCEEDED(hr)) *ppDisp = V_DISPATCH(&vtResult); | |
else VariantClear(&vtResult); | |
} | |
} | |
diff --git a/source/dh_exceptions.c b/source/dh_exceptions.c | |
index 4b506ab..15de8dc 100644 | |
--- a/source/dh_exceptions.c | |
+++ b/source/dh_exceptions.c | |
@@ -20,6 +20,13 @@ | |
#include "disphelper.h" | |
#include <assert.h> | |
+#ifdef __WINE__ | |
+// Wine uses the system widechar string function which as C99 compliant ( swprintf is the wide equivalent of snprintf ) | |
+// whereas Windows' API, and thus MinGW, Visual Studio, etc. are not compliant ( swprintf is the wide equivalent of sprintf, snwprintf is the wide equivalent of snprintf) | |
+#define _snwprintf swprintf | |
+#endif | |
+ | |
+ | |
#ifndef DISPHELPER_NO_EXCEPTIONS | |
/* Structure to store global exception options. */ | |
@@ -314,7 +321,7 @@ HRESULT dhFormatExceptionW(PDH_EXCEPTION pException, LPWSTR szBuffer, UINT cchBu | |
{ | |
if (!bFixedFont) | |
{ | |
- _snwprintf(szBuffer, cchBufferSize, L"Member:\t %s\r\nFunction:\t %s\t\t\r\nError In:\t %s\r\nError:\t %s\r\nCode:\t %x\r\nSource:\t %s", | |
+ _snwprintf(szBuffer, cchBufferSize, L"Member:\t %ls\r\nFunction:\t %ls\t\t\r\nError In:\t %ls\r\nError:\t %ls\r\nCode:\t %x\r\nSource:\t %ls", | |
pException->szCompleteMember, | |
pException->szInitialFunction, pException->szErrorFunction, | |
pException->szDescription, hr, | |
@@ -322,7 +329,7 @@ HRESULT dhFormatExceptionW(PDH_EXCEPTION pException, LPWSTR szBuffer, UINT cchBu | |
} | |
else | |
{ | |
- _snwprintf(szBuffer, cchBufferSize, L"Member: %s\r\nFunction: %s\r\nError In: %s\r\nError: %s\r\nCode: %x\r\nSource: %s", | |
+ _snwprintf(szBuffer, cchBufferSize, L"Member: %ls\r\nFunction: %ls\r\nError In: %ls\r\nError: %ls\r\nCode: %x\r\nSource: %ls", | |
pException->szCompleteMember, | |
pException->szInitialFunction, pException->szErrorFunction, | |
pException->szDescription, hr, | |
diff --git a/source/dh_invoke.c b/source/dh_invoke.c | |
index eea4093..17338bc 100644 | |
--- a/source/dh_invoke.c | |
+++ b/source/dh_invoke.c | |
@@ -23,7 +23,7 @@ | |
static HRESULT TraverseSubObjects(IDispatch ** ppDisp, LPWSTR * lpszMember, va_list * marker); | |
static HRESULT CreateArgumentArray(LPWSTR szTemp, VARIANT * pArgs, BOOL * pbFreeList, UINT * pcArgs, va_list * marker); | |
static HRESULT InternalInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvResult, IDispatch * pDisp, LPOLESTR szMember, va_list * marker); | |
-static HRESULT ExtractArgument(VARIANT * pvArg, WCHAR chIdentifier, BOOL * pbFreeArg, va_list * marker); | |
+static HRESULT ExtractArgument(VARIANT * pvArg, const WCHAR * chIdentifierPtr, BOOL * pbFreeArg, va_list * marker); | |
/* ************************************************************************** | |
@@ -120,7 +120,7 @@ static HRESULT TraverseSubObjects(IDispatch ** ppDisp, LPWSTR * lpszMember, va_l | |
hr = InternalInvokeV(DISPATCH_METHOD|DISPATCH_PROPERTYGET, VT_DISPATCH, | |
&vtObject, *ppDisp, szTemp, marker); | |
- if (!vtObject.pdispVal && SUCCEEDED(hr)) hr = E_NOINTERFACE; | |
+ if (! V_DISPATCH(&vtObject) && SUCCEEDED(hr)) hr = E_NOINTERFACE; | |
/* Release old object in *ppDisp */ | |
(*ppDisp)->lpVtbl->Release(*ppDisp); | |
@@ -128,7 +128,7 @@ static HRESULT TraverseSubObjects(IDispatch ** ppDisp, LPWSTR * lpszMember, va_l | |
if (FAILED(hr)) break; | |
/* Copy new object into *ppDisp */ | |
- *ppDisp = vtObject.pdispVal; | |
+ *ppDisp = V_DISPATCH(&vtObject); | |
/* Point next object name to start at character after '.'. | |
* eg. szTemp will now equal "Range.Font.Bold" */ | |
@@ -183,7 +183,7 @@ static HRESULT InternalInvokeV(int invokeType, VARTYPE returnType, VARIANT * pvR | |
/* Coerce result (if it exists) into the desired type. | |
* Note that VT_EMPTY means do not coerce the return value. */ | |
if (SUCCEEDED(hr) && pvResult != NULL && | |
- pvResult->vt != returnType && returnType != VT_EMPTY) | |
+ V_VT(pvResult) != returnType && returnType != VT_EMPTY) | |
{ | |
hr = VariantChangeType(pvResult, pvResult, 16 /* = VARIANT_LOCALBOOL */, returnType); | |
if (FAILED(hr)) VariantClear(pvResult); | |
@@ -246,7 +246,7 @@ static HRESULT CreateArgumentArray(LPWSTR szMember, VARIANT * pArgs, BOOL * pbFr | |
szMember++; /* Move forward to actual identifier */ | |
/* Extract argument based on identifier */ | |
- hr = ExtractArgument(&pArgs[iArg], *szMember, &pbFreeList[iArg], marker); | |
+ hr = ExtractArgument(&pArgs[iArg], szMember, &pbFreeList[iArg], marker); | |
if (FAILED(hr)) break; | |
} | |
@@ -277,31 +277,172 @@ static HRESULT CreateArgumentArray(LPWSTR szMember, VARIANT * pArgs, BOOL * pbFr | |
* identifier and pack it in a VARIANT. | |
* | |
============================================================================ */ | |
-static HRESULT ExtractArgument(VARIANT * pvArg, WCHAR chIdentifier, BOOL * pbFreeArg, va_list * marker) | |
+static HRESULT ExtractArgument(VARIANT * pvArg, const WCHAR * chIdentifier, BOOL * pbFreeArg, va_list * marker) | |
{ | |
HRESULT hr = NOERROR; | |
+ WCHAR chIdentifier = *chIdentifierPtr; | |
+ BOOL isRef = FALSE; | |
+ INT size = 0; | |
/* By default, the argument does not need to be freed */ | |
*pbFreeArg = FALSE; | |
+ /* C++ -like "byref" modifier */ | |
+ if (chIdentifier == L'&') | |
+ { | |
+ isRef = TRUE; | |
+ chIdentifier = *(++chIdentifierPtr); | |
+ } | |
+ | |
+ /* scanf -like format modifier */ | |
+ while(chIdentifier) | |
+ { | |
+ if (chIdentifier == L'h') | |
+ size--; | |
+ else if (chIdentifier == L'l') | |
+ size++; | |
+ else if (chIdentifier == L'L') | |
+ size=2; // long-long is always 64bits | |
+ else break; | |
+ | |
+ chIdentifier = *(++chIdentifierPtr); | |
+ } | |
+ | |
/* Change 'T' identifier to 'S' or 's' based on UNICODE mode */ | |
if (chIdentifier == L'T') chIdentifier = (dh_g_bIsUnicodeMode ? L'S' : L's'); | |
switch (chIdentifier) | |
{ | |
case L'd': /* LONG */ | |
- V_VT(pvArg) = VT_I4; | |
- V_I4(pvArg) = va_arg(*marker, LONG); | |
+ if (isRef) | |
+ { | |
+ switch(size) | |
+ { | |
+ case -2: | |
+ V_VT(pvArg) = VT_I1 | VT_BYREF; | |
+// V_I1REF(pvArg) = va_arg(*marker, CHAR *); | |
+ break; | |
+ case -1: | |
+ V_VT(pvArg) = VT_I2 | VT_BYREF; | |
+ V_I2REF(pvArg) = va_arg(*marker, SHORT *); | |
+ break; | |
+ case 0: | |
+ /* WIN32/WIN64 is assumed : 32bit int (are there still any 16bit OLE in circulation ?!?) */ | |
+ case 1: | |
+ /* WIN64 is LLP64 thus even long are always 32bits regardless of OS */ | |
+ V_VT(pvArg) = VT_I4 | VT_BYREF; | |
+ V_I4REF(pvArg) = va_arg(*marker, LONG *); | |
+ break; | |
+ case 2: | |
+ V_VT(pvArg) = VT_I8 | VT_BYREF; | |
+ V_I8REF(pvArg) = va_arg(*marker, LONGLONG *); | |
+ break; | |
+ default: | |
+ hr = E_INVALIDARG; | |
+ DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier); | |
+ break; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if (size == 2) | |
+ { | |
+ /* special case for 64-bits integers */ | |
+ V_VT(pvArg) = VT_I8; | |
+ V_I8(pvArg) = va_arg(*marker, LONGLONG); | |
+ } | |
+ else | |
+ { | |
+ /* all other are promoted to 32-bits integers when passed as arguments */ | |
+ V_VT(pvArg) = VT_I4; | |
+ V_I4(pvArg) = va_arg(*marker, LONG); | |
+ } | |
+ } | |
break; | |
case L'u': /* ULONG */ | |
- V_VT(pvArg) = VT_UI4; | |
- V_UI4(pvArg) = va_arg(*marker, ULONG); | |
+ if (isRef) { | |
+ switch(size) | |
+ { | |
+ case -2: | |
+ V_VT(pvArg) = VT_UI1 | VT_BYREF; | |
+// V_UI1REF(pvArg) = va_arg(*marker, BYTE *); | |
+ break; | |
+ case -1: | |
+ V_VT(pvArg) = VT_UI2 | VT_BYREF; | |
+ V_UI2REF(pvArg) = va_arg(*marker, USHORT *); | |
+ break; | |
+ case 0: | |
+ /* WIN32/WIN64 is assumed : 32bit int (are there still any 16bit OLE in circulation ?!?) */ | |
+ case 1: | |
+ /* WIN64 is LLP64 thus even long are always 32bits regardless of OS */ | |
+ V_VT(pvArg) = VT_UI4 | VT_BYREF; | |
+ V_UI4REF(pvArg) = va_arg(*marker, ULONG *); | |
+ break; | |
+ case 2: | |
+ V_VT(pvArg) = VT_UI8 | VT_BYREF; | |
+ V_UI8REF(pvArg) = va_arg(*marker, ULONGLONG *); | |
+ break; | |
+ default: | |
+ hr = E_INVALIDARG; | |
+ DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier); | |
+ break; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if (size == 2) | |
+ { | |
+ /* special case for 64-bits integers */ | |
+ V_VT(pvArg) = VT_UI8; | |
+ V_UI8(pvArg) = va_arg(*marker, ULONGLONG); | |
+ } | |
+ else | |
+ { | |
+ /* all other are promoted to 32-bits integers when passed as arguments */ | |
+ V_VT(pvArg) = VT_UI4; | |
+ V_UI4(pvArg) = va_arg(*marker, ULONG); | |
+ } | |
+ } | |
break; | |
case L'e': /* DOUBLE */ | |
- V_VT(pvArg) = VT_R8; | |
- V_R8(pvArg) = va_arg(*marker, DOUBLE); | |
+ if (isRef) | |
+ { | |
+ switch(size) | |
+ { | |
+ case -1: | |
+ case 0: | |
+ /* Warning, we mimick SCANF default behaviour with efg being 32bits float by default */ | |
+ V_VT(pvArg) = VT_R4 | VT_BYREF; | |
+ V_R4REF(pvArg) = va_arg(*marker, FLOAT *); | |
+ break; | |
+ case 1: | |
+ V_VT(pvArg) = VT_R8 | VT_BYREF; | |
+ V_R8REF(pvArg) = va_arg(*marker, DOUBLE *); | |
+ break; | |
+ default: | |
+ /* OLE32 doesn't support 128bits (default) & 80bits (387) long double floats */ | |
+ hr = E_INVALIDARG; | |
+ DEBUG_NOTIFY_INVALID_IDENTIFIER(chIdentifier); | |
+ break; | |
+ } | |
+ } | |
+ else | |
+ { | |
+ if (size == 2) | |
+ { | |
+ /* long double floats take 80bits or 128bits and should be consumed accordingly */ | |
+ V_VT(pvArg) = VT_R8; | |
+ V_R8(pvArg) = (DOUBLE) va_arg(*marker, long double); | |
+ } | |
+ else | |
+ { | |
+ /* float are auto-promoted to 64bit double float when passed as argument */ | |
+ V_VT(pvArg) = VT_R8; | |
+ V_R8(pvArg) = va_arg(*marker, DOUBLE); | |
+ } | |
+ } | |
break; | |
case L'b': /* BOOL */ | |
diff --git a/source/disphelper.h b/source/disphelper.h | |
index 9a3f9c4..c933eab 100644 | |
--- a/source/disphelper.h | |
+++ b/source/disphelper.h | |
@@ -19,6 +19,7 @@ | |
#ifndef DISPHELPER_H_INCLUDED | |
#define DISPHELPER_H_INCLUDED | |
+#include <ocidl.h> | |
#include <objbase.h> | |
#include <time.h> | |
@@ -547,11 +548,12 @@ inline std::ostream& operator<<(std::ostream& os, const CDhStringA& s) | |
return os << (s ? s : (char*) "(null)"); | |
} | |
+#ifdef _GLIBCXX_USE_WCHAR_T | |
inline std::wostream& operator<<(std::wostream& os, const CDhStringW& s) | |
{ | |
return os << (s ? s : (wchar_t*) L"(null)"); | |
} | |
- | |
+#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment