Skip to content

Commit 2c4c57a

Browse files
1. Improved handling of managed objects (detect by presence of IReflect interface)
2. valueOf for variants of IUnknown returns [Unknown] 3. Improved error handling. It checks scode, message and description. Also it now contains list of known error messages (i.e. STG_E_FILENOTFOUND) to show. So current output is a way more informative. 4. Message loop handling improved. So once you do WScript.Sleep etc it actually pumps messages from the loop.
1 parent ece4b9a commit 2c4c57a

6 files changed

Lines changed: 470 additions & 31 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ This is a key drawback of v8 engine compared to MS. Consider an example:
271271
if( a.Prop )
272272
{
273273
// If 'Prop' is a dynamic property (i.e. it is not defined in TypeInfo and
274-
// not marked explicitly as a property, then never got here. Even if a.Prop is null or false.
274+
// not marked explicitly as a property, then execution never gets here. Even if a.Prop is null or false.
275275
}
276276
```
277277

src/disp.cpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,23 +112,27 @@ bool DispObject::get(LPOLESTR tag, LONG index, const PropertyCallbackInfo<Value>
112112
else {
113113
if (disp_info->is_property()) opt |= option_property;
114114
is_property_simple = disp_info->is_property_simple();
115+
116+
if (disp->bManaged && tag && *tag && wcscmp(tag, L"ToString")==0)
117+
{
118+
// .NET ToString is reported as a property while we normally use it via .ToString() - i.e. as a method.
119+
is_property_simple = false;
120+
}
121+
115122
}
116123
}
117-
else {
118-
// We were unable to figure out if it is a property or method.
119-
// This is typical for .NET objects. So we may check if it is actually
120-
// a .NET object by checking presense of IReflect interface and then asking
121-
CComPtr<IDispatch> preflect;
122-
HRESULT hr = disp->ptr->QueryInterface(IID_IReflect, (void**)&preflect);
124+
else if ( disp->bManaged && tag && *tag && wcscmp(tag, L"length") == 0) {
123125
DISPID lenprop;
124-
125-
if (SUCCEEDED(hr) && this_prop && SUCCEEDED(disp->FindProperty(L"length", &lenprop)) )
126+
if ( SUCCEEDED(disp->FindProperty(L"length", &lenprop)) )
126127
{
127128

128129
// If we have 'IReflect' and '.length' - assume it is .NET JS Array or JS Object
129130
is_property_simple = true;
130131
}
131-
132+
}
133+
else if (disp->bManaged && tag && *tag && index>=0 ) {
134+
// jsarray[x]
135+
is_property_simple = true;
132136
}
133137
}
134138

@@ -1042,7 +1046,8 @@ void VariantObject::NodeValueOf(const FunctionCallbackInfo<Value>& args) {
10421046
isolate->ThrowException(DispErrorInvalid(isolate));
10431047
return;
10441048
}
1045-
Local<Value> result = Variant2Value(isolate, self->value, true);
1049+
// Last parameter false because valueOf should return primitive value
1050+
Local<Value> result = Variant2Value(isolate, self->value, false);
10461051
args.GetReturnValue().Set(result);
10471052
}
10481053

@@ -1066,7 +1071,7 @@ void VariantObject::NodeGet(Local<Name> name, const PropertyCallbackInfo<Value>&
10661071
}
10671072

10681073
String::Value vname(isolate, name);
1069-
LPOLESTR id = (vname.length() > 0) ? (LPOLESTR)*vname : L"valueOf";
1074+
LPOLESTR id = (vname.length() > 0) ? (LPOLESTR)*vname : L"valueOf";
10701075
if (_wcsicmp(id, L"__value") == 0) {
10711076
Local<Value> result = Variant2Value(isolate, self->value);
10721077
args.GetReturnValue().Set(result);

src/disp.h

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ bool TypeLibEnumerate(ITypeLib *typelib, int mode, T process) {
7878
return cnt > 0;
7979
}
8080

81+
class DispInfo;
82+
8183
template<typename T>
82-
bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) {
84+
bool TypeInfoEnumerate(DispInfo* dispInfo, int mode, T process) {
85+
IDispatch* disp = dispInfo->ptr;
8386
UINT i, cnt;
8487
CComPtr<ITypeLib> prevtypelib;
8588
if (!disp || FAILED(disp->GetTypeInfoCount(&cnt))) cnt = 0;
@@ -92,6 +95,21 @@ bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) {
9295
CComPtr<ITypeLib> typelib;
9396
if (info->GetContainingTypeLib(&typelib, &typeindex) == S_OK) {
9497

98+
// Check if typelib is managed
99+
CComPtr<ITypeLib2> typeLib2;
100+
101+
if (SUCCEEDED(typelib->QueryInterface(IID_ITypeLib2, (void**)&typeLib2)) )
102+
{
103+
// {90883F05-3D28-11D2-8F17-00A0C9A6186D}
104+
const GUID GUID_ExportedFromComPlus = { 0x90883F05, 0x3D28, 0x11D2, { 0x8F, 0x17, 0x00, 0xA0, 0xC9, 0xA6, 0x18, 0x6D } };
105+
106+
CComVariant cv;
107+
if (SUCCEEDED(typeLib2->GetCustData(GUID_ExportedFromComPlus, &cv)))
108+
{
109+
dispInfo->bManaged = true;
110+
}
111+
}
112+
95113
// Enumerate all types in library types
96114
// May be very slow! need a special method
97115
/*
@@ -104,7 +122,7 @@ bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) {
104122
CComPtr<ITypeInfo> tinfo;
105123
if (typelib->GetTypeInfo(typeindex, &tinfo) == S_OK) {
106124
TypeInfoPrepare<T>(tinfo, mode, process);
107-
}
125+
}
108126
}
109127

110128
// Process types
@@ -121,6 +139,7 @@ class DispInfo {
121139
CComPtr<IDispatch> ptr;
122140
std::wstring name;
123141
int options;
142+
bool bManaged;
124143

125144
struct type_t {
126145
DISPID dispid;
@@ -137,7 +156,7 @@ class DispInfo {
137156
types_by_dispid_t types_by_dispid;
138157

139158
inline DispInfo(IDispatch *disp, const std::wstring &nm, int opt, std::shared_ptr<DispInfo> *parnt = nullptr)
140-
: ptr(disp), options(opt), name(nm)
159+
: ptr(disp), options(opt), name(nm), bManaged(false)
141160
{
142161
if (parnt) parent = *parnt;
143162
if ((options & option_type) != 0)
@@ -160,7 +179,7 @@ class DispInfo {
160179

161180
template<typename T>
162181
bool Enumerate(int mode, T process) {
163-
return TypeInfoEnumerate((IDispatch*)ptr, mode, process);
182+
return TypeInfoEnumerate(this, mode, process);
164183
}
165184

166185
inline bool GetTypeInfo(const DISPID dispid, type_ptr &info) {

0 commit comments

Comments
 (0)