From 658798de997c15b95a94ff16dcf728d86505451f Mon Sep 17 00:00:00 2001 From: Manuel Leclerc Date: Thu, 23 Mar 2023 19:14:12 +0100 Subject: [PATCH 1/9] Allow to use node-activex with COM Objects NOT present in the ROT if they are able to return an IUnknown via the Win32 API: AccessibleObjectFromWindow --- src/disp.cpp | 34 +++++++++++++++++++++------------- src/utils.cpp | 28 ++++++++++++++++++++++++++++ src/utils.h | 1 + 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/disp.cpp b/src/disp.cpp index b27e4ea..a4ef2ed 100644 --- a/src/disp.cpp +++ b/src/disp.cpp @@ -461,6 +461,7 @@ void DispObject::NodeCreate(const FunctionCallbackInfo &args) { Isolate *isolate = args.GetIsolate(); Local ctx = isolate->GetCurrentContext(); bool isGetObject = false; + bool isGetAccessibleObject = false; int argcnt = args.Length(); if (argcnt < 1) { isolate->ThrowException(InvalidArgumentsError(isolate)); @@ -485,6 +486,9 @@ void DispObject::NodeCreate(const FunctionCallbackInfo &args) { if (opt->Get(ctx, v8str(isolate, "getobject")).ToLocal(&val)) { if (v8val2bool(isolate, val, false)) isGetObject = true; } + if (opt->Get(ctx, v8str(isolate, "getaccessibleobject")).ToLocal(&val)) { + if (v8val2bool(isolate, val, false)) isGetAccessibleObject = true; + } } } @@ -520,24 +524,28 @@ void DispObject::NodeCreate(const FunctionCallbackInfo &args) { else { name.assign((LPOLESTR)*vname, vname.length()); + CComPtr unk; if (isGetObject) { - CComPtr unk; hrcode = CoGetObject(name.c_str(), NULL, IID_IUnknown, (void**)&unk); if SUCCEEDED(hrcode) hrcode = unk->QueryInterface(&disp); - } else { - CLSID clsid; - hrcode = CLSIDFromProgID(name.c_str(), &clsid); - if SUCCEEDED(hrcode) { - if ((options & option_activate) == 0) hrcode = E_FAIL; - else { - CComPtr unk; - hrcode = GetActiveObject(clsid, NULL, &unk); - if SUCCEEDED(hrcode) hrcode = unk->QueryInterface(&disp); - } - if FAILED(hrcode) { - hrcode = disp.CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER); + if (isGetAccessibleObject) + { + hrcode = GetAccessibleObject(name.c_str(), unk); + if SUCCEEDED(hrcode) hrcode = unk->QueryInterface(&disp); + } else { + CLSID clsid; + hrcode = CLSIDFromProgID(name.c_str(), &clsid); + if SUCCEEDED(hrcode) { + if ((options & option_activate) == 0) hrcode = E_FAIL; + else { + hrcode = GetActiveObject(clsid, NULL, &unk); + if SUCCEEDED(hrcode) hrcode = unk->QueryInterface(&disp); + } + if FAILED(hrcode) { + hrcode = disp.CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER); + } } } } diff --git a/src/utils.cpp b/src/utils.cpp index 2d08060..30a66be 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,6 +6,8 @@ #include "stdafx.h" #include "disp.h" +#include // for AccessibleObjectFromWindow +#pragma comment(lib, "OleAcc.lib") // for AccessibleObjectFromWindow const GUID CLSID_DispObjectImpl = { 0x9dce8520, 0x2efe, 0x48c0,{ 0xa0, 0xdc, 0x95, 0x1b, 0x29, 0x18, 0x72, 0xc0 } }; @@ -761,4 +763,30 @@ void WinaxSleep(const FunctionCallbackInfo& args) { uint32_t ms = (args[0]->Uint32Value(ctx)).FromMaybe(0); Sleep(ms); args.GetReturnValue().SetUndefined(); +} + +// Get a COM pointer from a window found by it's text +HRESULT GetAccessibleObject(const wchar_t* pszWindowText, CComPtr& spIUnknown) { + struct ew { + static BOOL CALLBACK ecp(HWND hWnd, LPARAM lParam) { + wchar_t szWindowText[128]; + if (GetWindowTextW(hWnd, szWindowText, _countof(szWindowText))) { + ewp* pparams = reinterpret_cast(lParam); + if (!wcscmp(szWindowText, pparams->pszWindowText)) { + pparams->hWnd = hWnd; + return FALSE; + } + } + return TRUE; + } + struct ewp { + const wchar_t* pszWindowText; + HWND hWnd; + }; + }; + ew::ewp params{ pszWindowText, nullptr }; + EnumChildWindows(GetDesktopWindow(), ew::ecp, reinterpret_cast(¶ms)); + if (params.hWnd == nullptr) return _HRESULT_TYPEDEF_(0x80070057L); // ERROR_INVALID_PARAMETER + return AccessibleObjectFromWindow(params.hWnd, OBJID_NATIVEOM, IID_IUnknown, + reinterpret_cast(&spIUnknown)); } \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index adba491..caae938 100644 --- a/src/utils.h +++ b/src/utils.h @@ -523,3 +523,4 @@ class NodeMethods : public std::map > void WinaxSleep(const FunctionCallbackInfo& args); //------------------------------------------------------------------------------------------------------- +HRESULT GetAccessibleObject(const wchar_t* pszWindowText, CComPtr& spIUnknown); From 3d9e6eee8b09f5634f16ed5f169398e648cf8c4f Mon Sep 17 00:00:00 2001 From: durs Date: Sat, 1 Apr 2023 19:32:51 +0300 Subject: [PATCH 2/9] version 3.3.6 --- README.md | 8 +++++--- package.json | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 097dddb..50045d2 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ * Using optional parameters on constructor call ``` js -var con = new ActiveXObject("ADODB.Connection", { - activate: false, // Allow activate existance object instance, false by default - async: true, // Allow asynchronius calls, true by default (not implemented, for future usage) +var con = new ActiveXObject("Object.Name", { + activate: false, // Allow activate existance object instance (through CoGetObject), false by default + getobject: false, // Allow using name of the file in the ROT (through GetAccessibleObject), false by default type: true // Allow using type information, true by default }); ``` @@ -303,4 +303,6 @@ mocha --expose-gc test * [durs](https://github.com/durs) * [somanuell](https://github.com/somanuell) +* [Daniel-Userlane](https://github.com/Daniel-Userlane) +* [alexeygrinevich](https://github.com/alexeygrinevich) diff --git a/package.json b/package.json index 88ce4be..c4d5196 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "winax", - "version": "3.3.4", + "version": "3.3.6", "description": "Windows COM bindings", "homepage": "https://github.com/durs/node-activex", "keywords": [ @@ -29,6 +29,8 @@ }, "contributors": [ "Yuri Dursin ", + "Somanuell" + "Daniel-Userlane", "Alexey Grinevich " ], "repository": { From 3a676dc0da773b334a8779ccb2c067c78e9f0e79 Mon Sep 17 00:00:00 2001 From: durs Date: Sat, 1 Apr 2023 19:41:02 +0300 Subject: [PATCH 3/9] package fix --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c4d5196..c702fcb 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "contributors": [ "Yuri Dursin ", - "Somanuell" + "Somanuell", "Daniel-Userlane", "Alexey Grinevich " ], From 075731a81d9089018d4d98bbe2c25059e87c3c8d Mon Sep 17 00:00:00 2001 From: durs Date: Tue, 30 May 2023 12:49:55 +0300 Subject: [PATCH 4/9] license file appended --- .gitignore | 1 + LICENSE | 21 +++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- src/utils.h | 1 + 5 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 LICENSE diff --git a/.gitignore b/.gitignore index c9fe745..0a7a7f7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ node_modules build npm-debug.log +test.js /data/PERSONS.DBF /debug* \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..46e1710 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Yuri Dursin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/package-lock.json b/package-lock.json index 32106e0..fd638ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "winax", - "version": "3.3.4", + "version": "3.3.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "winax", - "version": "3.3.4", + "version": "3.3.7", "license": "MIT", "os": [ "win32" diff --git a/package.json b/package.json index c702fcb..9959a41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "winax", - "version": "3.3.6", + "version": "3.3.7", "description": "Windows COM bindings", "homepage": "https://github.com/durs/node-activex", "keywords": [ diff --git a/src/utils.h b/src/utils.h index caae938..a4b913f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -195,6 +195,7 @@ class CComPtr { inline HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { Release(); + HRESULT hr = ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(IUnknown), (void**)&p); return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); } From ece4b9a0b08f21de78c464cf808836336e3e74b3 Mon Sep 17 00:00:00 2001 From: durs Date: Tue, 30 May 2023 12:53:45 +0300 Subject: [PATCH 5/9] revert CoCreateInstance changes --- src/utils.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/utils.h b/src/utils.h index a4b913f..caae938 100644 --- a/src/utils.h +++ b/src/utils.h @@ -195,7 +195,6 @@ class CComPtr { inline HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL) { Release(); - HRESULT hr = ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(IUnknown), (void**)&p); return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p); } From 2c4c57ac296646eab02b5cd6c1b7d5934f1c3db6 Mon Sep 17 00:00:00 2001 From: Alexey Grinevich Date: Tue, 26 Sep 2023 10:45:57 +0300 Subject: [PATCH 6/9] 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. --- README.md | 2 +- src/disp.cpp | 27 ++-- src/disp.h | 27 +++- src/utils.cpp | 407 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/utils.h | 29 +++- test/excel.js | 9 ++ 6 files changed, 470 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 50045d2..ed58edb 100644 --- a/README.md +++ b/README.md @@ -271,7 +271,7 @@ This is a key drawback of v8 engine compared to MS. Consider an example: if( a.Prop ) { // If 'Prop' is a dynamic property (i.e. it is not defined in TypeInfo and - // not marked explicitly as a property, then never got here. Even if a.Prop is null or false. + // not marked explicitly as a property, then execution never gets here. Even if a.Prop is null or false. } ``` diff --git a/src/disp.cpp b/src/disp.cpp index a4ef2ed..f1671b9 100644 --- a/src/disp.cpp +++ b/src/disp.cpp @@ -112,23 +112,27 @@ bool DispObject::get(LPOLESTR tag, LONG index, const PropertyCallbackInfo else { if (disp_info->is_property()) opt |= option_property; is_property_simple = disp_info->is_property_simple(); + + if (disp->bManaged && tag && *tag && wcscmp(tag, L"ToString")==0) + { + // .NET ToString is reported as a property while we normally use it via .ToString() - i.e. as a method. + is_property_simple = false; + } + } } - else { - // We were unable to figure out if it is a property or method. - // This is typical for .NET objects. So we may check if it is actually - // a .NET object by checking presense of IReflect interface and then asking - CComPtr preflect; - HRESULT hr = disp->ptr->QueryInterface(IID_IReflect, (void**)&preflect); + else if ( disp->bManaged && tag && *tag && wcscmp(tag, L"length") == 0) { DISPID lenprop; - - if (SUCCEEDED(hr) && this_prop && SUCCEEDED(disp->FindProperty(L"length", &lenprop)) ) + if ( SUCCEEDED(disp->FindProperty(L"length", &lenprop)) ) { // If we have 'IReflect' and '.length' - assume it is .NET JS Array or JS Object is_property_simple = true; } - + } + else if (disp->bManaged && tag && *tag && index>=0 ) { + // jsarray[x] + is_property_simple = true; } } @@ -1042,7 +1046,8 @@ void VariantObject::NodeValueOf(const FunctionCallbackInfo& args) { isolate->ThrowException(DispErrorInvalid(isolate)); return; } - Local result = Variant2Value(isolate, self->value, true); + // Last parameter false because valueOf should return primitive value + Local result = Variant2Value(isolate, self->value, false); args.GetReturnValue().Set(result); } @@ -1066,7 +1071,7 @@ void VariantObject::NodeGet(Local name, const PropertyCallbackInfo& } String::Value vname(isolate, name); - LPOLESTR id = (vname.length() > 0) ? (LPOLESTR)*vname : L"valueOf"; + LPOLESTR id = (vname.length() > 0) ? (LPOLESTR)*vname : L"valueOf"; if (_wcsicmp(id, L"__value") == 0) { Local result = Variant2Value(isolate, self->value); args.GetReturnValue().Set(result); diff --git a/src/disp.h b/src/disp.h index 6272ac8..ba87298 100644 --- a/src/disp.h +++ b/src/disp.h @@ -78,8 +78,11 @@ bool TypeLibEnumerate(ITypeLib *typelib, int mode, T process) { return cnt > 0; } +class DispInfo; + template -bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) { +bool TypeInfoEnumerate(DispInfo* dispInfo, int mode, T process) { + IDispatch* disp = dispInfo->ptr; UINT i, cnt; CComPtr prevtypelib; if (!disp || FAILED(disp->GetTypeInfoCount(&cnt))) cnt = 0; @@ -92,6 +95,21 @@ bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) { CComPtr typelib; if (info->GetContainingTypeLib(&typelib, &typeindex) == S_OK) { + // Check if typelib is managed + CComPtr typeLib2; + + if (SUCCEEDED(typelib->QueryInterface(IID_ITypeLib2, (void**)&typeLib2)) ) + { + // {90883F05-3D28-11D2-8F17-00A0C9A6186D} + const GUID GUID_ExportedFromComPlus = { 0x90883F05, 0x3D28, 0x11D2, { 0x8F, 0x17, 0x00, 0xA0, 0xC9, 0xA6, 0x18, 0x6D } }; + + CComVariant cv; + if (SUCCEEDED(typeLib2->GetCustData(GUID_ExportedFromComPlus, &cv))) + { + dispInfo->bManaged = true; + } + } + // Enumerate all types in library types // May be very slow! need a special method /* @@ -104,7 +122,7 @@ bool TypeInfoEnumerate(IDispatch *disp, int mode, T process) { CComPtr tinfo; if (typelib->GetTypeInfo(typeindex, &tinfo) == S_OK) { TypeInfoPrepare(tinfo, mode, process); - } + } } // Process types @@ -121,6 +139,7 @@ class DispInfo { CComPtr ptr; std::wstring name; int options; + bool bManaged; struct type_t { DISPID dispid; @@ -137,7 +156,7 @@ class DispInfo { types_by_dispid_t types_by_dispid; inline DispInfo(IDispatch *disp, const std::wstring &nm, int opt, std::shared_ptr *parnt = nullptr) - : ptr(disp), options(opt), name(nm) + : ptr(disp), options(opt), name(nm), bManaged(false) { if (parnt) parent = *parnt; if ((options & option_type) != 0) @@ -160,7 +179,7 @@ class DispInfo { template bool Enumerate(int mode, T process) { - return TypeInfoEnumerate((IDispatch*)ptr, mode, process); + return TypeInfoEnumerate(this, mode, process); } inline bool GetTypeInfo(const DISPID dispid, type_ptr &info) { diff --git a/src/utils.cpp b/src/utils.cpp index 30a66be..f47e9ef 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,6 +6,7 @@ #include "stdafx.h" #include "disp.h" +#include #include // for AccessibleObjectFromWindow #pragma comment(lib, "OleAcc.lib") // for AccessibleObjectFromWindow @@ -18,7 +19,328 @@ const IID IID_IReflect = { 0xAFBF15E5, 0xC37C, 0x11D2,{ 0xB8, 0x8E, 0x00, 0xA0, #define ERROR_MESSAGE_WIDE_MAXSIZE 1024 #define ERROR_MESSAGE_UTF8_MAXSIZE 2048 -uint16_t *GetWin32ErroroMessage(uint16_t *buf, size_t buflen, Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { +void GetScodeString(HRESULT hr, wchar_t* buf, int bufSize) +{ + struct HRESULT_ENTRY + { + HRESULT hr; + LPCWSTR lpszName; + }; +#define MAKE_HRESULT_ENTRY(hr) { hr, L#hr } + static const HRESULT_ENTRY hrNameTable[] = + { + MAKE_HRESULT_ENTRY(S_OK), + MAKE_HRESULT_ENTRY(S_FALSE), + + MAKE_HRESULT_ENTRY(CACHE_S_FORMATETC_NOTSUPPORTED), + MAKE_HRESULT_ENTRY(CACHE_S_SAMECACHE), + MAKE_HRESULT_ENTRY(CACHE_S_SOMECACHES_NOTUPDATED), + MAKE_HRESULT_ENTRY(CONVERT10_S_NO_PRESENTATION), + MAKE_HRESULT_ENTRY(DATA_S_SAMEFORMATETC), + MAKE_HRESULT_ENTRY(DRAGDROP_S_CANCEL), + MAKE_HRESULT_ENTRY(DRAGDROP_S_DROP), + MAKE_HRESULT_ENTRY(DRAGDROP_S_USEDEFAULTCURSORS), + MAKE_HRESULT_ENTRY(INPLACE_S_TRUNCATED), + MAKE_HRESULT_ENTRY(MK_S_HIM), + MAKE_HRESULT_ENTRY(MK_S_ME), + MAKE_HRESULT_ENTRY(MK_S_MONIKERALREADYREGISTERED), + MAKE_HRESULT_ENTRY(MK_S_REDUCED_TO_SELF), + MAKE_HRESULT_ENTRY(MK_S_US), + MAKE_HRESULT_ENTRY(OLE_S_MAC_CLIPFORMAT), + MAKE_HRESULT_ENTRY(OLE_S_STATIC), + MAKE_HRESULT_ENTRY(OLE_S_USEREG), + MAKE_HRESULT_ENTRY(OLEOBJ_S_CANNOT_DOVERB_NOW), + MAKE_HRESULT_ENTRY(OLEOBJ_S_INVALIDHWND), + MAKE_HRESULT_ENTRY(OLEOBJ_S_INVALIDVERB), + MAKE_HRESULT_ENTRY(OLEOBJ_S_LAST), + MAKE_HRESULT_ENTRY(STG_S_CONVERTED), + MAKE_HRESULT_ENTRY(VIEW_S_ALREADY_FROZEN), + + MAKE_HRESULT_ENTRY(E_UNEXPECTED), + MAKE_HRESULT_ENTRY(E_NOTIMPL), + MAKE_HRESULT_ENTRY(E_OUTOFMEMORY), + MAKE_HRESULT_ENTRY(E_INVALIDARG), + MAKE_HRESULT_ENTRY(E_NOINTERFACE), + MAKE_HRESULT_ENTRY(E_POINTER), + MAKE_HRESULT_ENTRY(E_HANDLE), + MAKE_HRESULT_ENTRY(E_ABORT), + MAKE_HRESULT_ENTRY(E_FAIL), + MAKE_HRESULT_ENTRY(E_ACCESSDENIED), + + MAKE_HRESULT_ENTRY(CACHE_E_NOCACHE_UPDATED), + MAKE_HRESULT_ENTRY(CLASS_E_CLASSNOTAVAILABLE), + MAKE_HRESULT_ENTRY(CLASS_E_NOAGGREGATION), + MAKE_HRESULT_ENTRY(CLIPBRD_E_BAD_DATA), + MAKE_HRESULT_ENTRY(CLIPBRD_E_CANT_CLOSE), + MAKE_HRESULT_ENTRY(CLIPBRD_E_CANT_EMPTY), + MAKE_HRESULT_ENTRY(CLIPBRD_E_CANT_OPEN), + MAKE_HRESULT_ENTRY(CLIPBRD_E_CANT_SET), + MAKE_HRESULT_ENTRY(CO_E_ALREADYINITIALIZED), + MAKE_HRESULT_ENTRY(CO_E_APPDIDNTREG), + MAKE_HRESULT_ENTRY(CO_E_APPNOTFOUND), + MAKE_HRESULT_ENTRY(CO_E_APPSINGLEUSE), + MAKE_HRESULT_ENTRY(CO_E_BAD_PATH), + MAKE_HRESULT_ENTRY(CO_E_CANTDETERMINECLASS), + MAKE_HRESULT_ENTRY(CO_E_CLASS_CREATE_FAILED), + MAKE_HRESULT_ENTRY(CO_E_CLASSSTRING), + MAKE_HRESULT_ENTRY(CO_E_DLLNOTFOUND), + MAKE_HRESULT_ENTRY(CO_E_ERRORINAPP), + MAKE_HRESULT_ENTRY(CO_E_ERRORINDLL), + MAKE_HRESULT_ENTRY(CO_E_IIDSTRING), + MAKE_HRESULT_ENTRY(CO_E_NOTINITIALIZED), + MAKE_HRESULT_ENTRY(CO_E_OBJISREG), + MAKE_HRESULT_ENTRY(CO_E_OBJNOTCONNECTED), + MAKE_HRESULT_ENTRY(CO_E_OBJNOTREG), + MAKE_HRESULT_ENTRY(CO_E_OBJSRV_RPC_FAILURE), + MAKE_HRESULT_ENTRY(CO_E_SCM_ERROR), + MAKE_HRESULT_ENTRY(CO_E_SCM_RPC_FAILURE), + MAKE_HRESULT_ENTRY(CO_E_SERVER_EXEC_FAILURE), + MAKE_HRESULT_ENTRY(CO_E_SERVER_STOPPING), + MAKE_HRESULT_ENTRY(CO_E_WRONGOSFORAPP), + MAKE_HRESULT_ENTRY(CONVERT10_E_OLESTREAM_BITMAP_TO_DIB), + MAKE_HRESULT_ENTRY(CONVERT10_E_OLESTREAM_FMT), + MAKE_HRESULT_ENTRY(CONVERT10_E_OLESTREAM_GET), + MAKE_HRESULT_ENTRY(CONVERT10_E_OLESTREAM_PUT), + MAKE_HRESULT_ENTRY(CONVERT10_E_STG_DIB_TO_BITMAP), + MAKE_HRESULT_ENTRY(CONVERT10_E_STG_FMT), + MAKE_HRESULT_ENTRY(CONVERT10_E_STG_NO_STD_STREAM), + MAKE_HRESULT_ENTRY(DISP_E_ARRAYISLOCKED), + MAKE_HRESULT_ENTRY(DISP_E_BADCALLEE), + MAKE_HRESULT_ENTRY(DISP_E_BADINDEX), + MAKE_HRESULT_ENTRY(DISP_E_BADPARAMCOUNT), + MAKE_HRESULT_ENTRY(DISP_E_BADVARTYPE), + MAKE_HRESULT_ENTRY(DISP_E_EXCEPTION), + MAKE_HRESULT_ENTRY(DISP_E_MEMBERNOTFOUND), + MAKE_HRESULT_ENTRY(DISP_E_NONAMEDARGS), + MAKE_HRESULT_ENTRY(DISP_E_NOTACOLLECTION), + MAKE_HRESULT_ENTRY(DISP_E_OVERFLOW), + MAKE_HRESULT_ENTRY(DISP_E_PARAMNOTFOUND), + MAKE_HRESULT_ENTRY(DISP_E_PARAMNOTOPTIONAL), + MAKE_HRESULT_ENTRY(DISP_E_TYPEMISMATCH), + MAKE_HRESULT_ENTRY(DISP_E_UNKNOWNINTERFACE), + MAKE_HRESULT_ENTRY(DISP_E_UNKNOWNLCID), + MAKE_HRESULT_ENTRY(DISP_E_UNKNOWNNAME), + MAKE_HRESULT_ENTRY(DRAGDROP_E_ALREADYREGISTERED), + MAKE_HRESULT_ENTRY(DRAGDROP_E_INVALIDHWND), + MAKE_HRESULT_ENTRY(DRAGDROP_E_NOTREGISTERED), + MAKE_HRESULT_ENTRY(DV_E_CLIPFORMAT), + MAKE_HRESULT_ENTRY(DV_E_DVASPECT), + MAKE_HRESULT_ENTRY(DV_E_DVTARGETDEVICE), + MAKE_HRESULT_ENTRY(DV_E_DVTARGETDEVICE_SIZE), + MAKE_HRESULT_ENTRY(DV_E_FORMATETC), + MAKE_HRESULT_ENTRY(DV_E_LINDEX), + MAKE_HRESULT_ENTRY(DV_E_NOIVIEWOBJECT), + MAKE_HRESULT_ENTRY(DV_E_STATDATA), + MAKE_HRESULT_ENTRY(DV_E_STGMEDIUM), + MAKE_HRESULT_ENTRY(DV_E_TYMED), + MAKE_HRESULT_ENTRY(INPLACE_E_NOTOOLSPACE), + MAKE_HRESULT_ENTRY(INPLACE_E_NOTUNDOABLE), + MAKE_HRESULT_ENTRY(MEM_E_INVALID_LINK), + MAKE_HRESULT_ENTRY(MEM_E_INVALID_ROOT), + MAKE_HRESULT_ENTRY(MEM_E_INVALID_SIZE), + MAKE_HRESULT_ENTRY(MK_E_CANTOPENFILE), + MAKE_HRESULT_ENTRY(MK_E_CONNECTMANUALLY), + MAKE_HRESULT_ENTRY(MK_E_ENUMERATION_FAILED), + MAKE_HRESULT_ENTRY(MK_E_EXCEEDEDDEADLINE), + MAKE_HRESULT_ENTRY(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED), + MAKE_HRESULT_ENTRY(MK_E_INVALIDEXTENSION), + MAKE_HRESULT_ENTRY(MK_E_MUSTBOTHERUSER), + MAKE_HRESULT_ENTRY(MK_E_NEEDGENERIC), + MAKE_HRESULT_ENTRY(MK_E_NO_NORMALIZED), + MAKE_HRESULT_ENTRY(MK_E_NOINVERSE), + MAKE_HRESULT_ENTRY(MK_E_NOOBJECT), + MAKE_HRESULT_ENTRY(MK_E_NOPREFIX), + MAKE_HRESULT_ENTRY(MK_E_NOSTORAGE), + MAKE_HRESULT_ENTRY(MK_E_NOTBINDABLE), + MAKE_HRESULT_ENTRY(MK_E_NOTBOUND), + MAKE_HRESULT_ENTRY(MK_E_SYNTAX), + MAKE_HRESULT_ENTRY(MK_E_UNAVAILABLE), + MAKE_HRESULT_ENTRY(OLE_E_ADVF), + MAKE_HRESULT_ENTRY(OLE_E_ADVISENOTSUPPORTED), + MAKE_HRESULT_ENTRY(OLE_E_BLANK), + MAKE_HRESULT_ENTRY(OLE_E_CANT_BINDTOSOURCE), + MAKE_HRESULT_ENTRY(OLE_E_CANT_GETMONIKER), + MAKE_HRESULT_ENTRY(OLE_E_CANTCONVERT), + MAKE_HRESULT_ENTRY(OLE_E_CLASSDIFF), + MAKE_HRESULT_ENTRY(OLE_E_ENUM_NOMORE), + MAKE_HRESULT_ENTRY(OLE_E_INVALIDHWND), + MAKE_HRESULT_ENTRY(OLE_E_INVALIDRECT), + MAKE_HRESULT_ENTRY(OLE_E_NOCACHE), + MAKE_HRESULT_ENTRY(OLE_E_NOCONNECTION), + MAKE_HRESULT_ENTRY(OLE_E_NOSTORAGE), + MAKE_HRESULT_ENTRY(OLE_E_NOT_INPLACEACTIVE), + MAKE_HRESULT_ENTRY(OLE_E_NOTRUNNING), + MAKE_HRESULT_ENTRY(OLE_E_OLEVERB), + MAKE_HRESULT_ENTRY(OLE_E_PROMPTSAVECANCELLED), + MAKE_HRESULT_ENTRY(OLE_E_STATIC), + MAKE_HRESULT_ENTRY(OLE_E_WRONGCOMPOBJ), + MAKE_HRESULT_ENTRY(OLEOBJ_E_INVALIDVERB), + MAKE_HRESULT_ENTRY(OLEOBJ_E_NOVERBS), + MAKE_HRESULT_ENTRY(REGDB_E_CLASSNOTREG), + MAKE_HRESULT_ENTRY(REGDB_E_IIDNOTREG), + MAKE_HRESULT_ENTRY(REGDB_E_INVALIDVALUE), + MAKE_HRESULT_ENTRY(REGDB_E_KEYMISSING), + MAKE_HRESULT_ENTRY(REGDB_E_READREGDB), + MAKE_HRESULT_ENTRY(REGDB_E_WRITEREGDB), + MAKE_HRESULT_ENTRY(RPC_E_ATTEMPTED_MULTITHREAD), + MAKE_HRESULT_ENTRY(RPC_E_CALL_CANCELED), + MAKE_HRESULT_ENTRY(RPC_E_CALL_REJECTED), + MAKE_HRESULT_ENTRY(RPC_E_CANTCALLOUT_AGAIN), + MAKE_HRESULT_ENTRY(RPC_E_CANTCALLOUT_INASYNCCALL), + MAKE_HRESULT_ENTRY(RPC_E_CANTCALLOUT_INEXTERNALCALL), + MAKE_HRESULT_ENTRY(RPC_E_CANTCALLOUT_ININPUTSYNCCALL), + MAKE_HRESULT_ENTRY(RPC_E_CANTPOST_INSENDCALL), + MAKE_HRESULT_ENTRY(RPC_E_CANTTRANSMIT_CALL), + MAKE_HRESULT_ENTRY(RPC_E_CHANGED_MODE), + MAKE_HRESULT_ENTRY(RPC_E_CLIENT_CANTMARSHAL_DATA), + MAKE_HRESULT_ENTRY(RPC_E_CLIENT_CANTUNMARSHAL_DATA), + MAKE_HRESULT_ENTRY(RPC_E_CLIENT_DIED), + MAKE_HRESULT_ENTRY(RPC_E_CONNECTION_TERMINATED), + MAKE_HRESULT_ENTRY(RPC_E_DISCONNECTED), + MAKE_HRESULT_ENTRY(RPC_E_FAULT), + MAKE_HRESULT_ENTRY(RPC_E_INVALID_CALLDATA), + MAKE_HRESULT_ENTRY(RPC_E_INVALID_DATA), + MAKE_HRESULT_ENTRY(RPC_E_INVALID_DATAPACKET), + MAKE_HRESULT_ENTRY(RPC_E_INVALID_PARAMETER), + MAKE_HRESULT_ENTRY(RPC_E_INVALIDMETHOD), + MAKE_HRESULT_ENTRY(RPC_E_NOT_REGISTERED), + MAKE_HRESULT_ENTRY(RPC_E_OUT_OF_RESOURCES), + MAKE_HRESULT_ENTRY(RPC_E_RETRY), + MAKE_HRESULT_ENTRY(RPC_E_SERVER_CANTMARSHAL_DATA), + MAKE_HRESULT_ENTRY(RPC_E_SERVER_CANTUNMARSHAL_DATA), + MAKE_HRESULT_ENTRY(RPC_E_SERVER_DIED), + MAKE_HRESULT_ENTRY(RPC_E_SERVER_DIED_DNE), + MAKE_HRESULT_ENTRY(RPC_E_SERVERCALL_REJECTED), + MAKE_HRESULT_ENTRY(RPC_E_SERVERCALL_RETRYLATER), + MAKE_HRESULT_ENTRY(RPC_E_SERVERFAULT), + MAKE_HRESULT_ENTRY(RPC_E_SYS_CALL_FAILED), + MAKE_HRESULT_ENTRY(RPC_E_THREAD_NOT_INIT), + MAKE_HRESULT_ENTRY(RPC_E_UNEXPECTED), + MAKE_HRESULT_ENTRY(RPC_E_WRONG_THREAD), + MAKE_HRESULT_ENTRY(STG_E_ABNORMALAPIEXIT), + MAKE_HRESULT_ENTRY(STG_E_ACCESSDENIED), + MAKE_HRESULT_ENTRY(STG_E_CANTSAVE), + MAKE_HRESULT_ENTRY(STG_E_DISKISWRITEPROTECTED), + MAKE_HRESULT_ENTRY(STG_E_EXTANTMARSHALLINGS), + MAKE_HRESULT_ENTRY(STG_E_FILEALREADYEXISTS), + MAKE_HRESULT_ENTRY(STG_E_FILENOTFOUND), + MAKE_HRESULT_ENTRY(STG_E_INSUFFICIENTMEMORY), + MAKE_HRESULT_ENTRY(STG_E_INUSE), + MAKE_HRESULT_ENTRY(STG_E_INVALIDFLAG), + MAKE_HRESULT_ENTRY(STG_E_INVALIDFUNCTION), + MAKE_HRESULT_ENTRY(STG_E_INVALIDHANDLE), + MAKE_HRESULT_ENTRY(STG_E_INVALIDHEADER), + MAKE_HRESULT_ENTRY(STG_E_INVALIDNAME), + MAKE_HRESULT_ENTRY(STG_E_INVALIDPARAMETER), + MAKE_HRESULT_ENTRY(STG_E_INVALIDPOINTER), + MAKE_HRESULT_ENTRY(STG_E_LOCKVIOLATION), + MAKE_HRESULT_ENTRY(STG_E_MEDIUMFULL), + MAKE_HRESULT_ENTRY(STG_E_NOMOREFILES), + MAKE_HRESULT_ENTRY(STG_E_NOTCURRENT), + MAKE_HRESULT_ENTRY(STG_E_NOTFILEBASEDSTORAGE), + MAKE_HRESULT_ENTRY(STG_E_OLDDLL), + MAKE_HRESULT_ENTRY(STG_E_OLDFORMAT), + MAKE_HRESULT_ENTRY(STG_E_PATHNOTFOUND), + MAKE_HRESULT_ENTRY(STG_E_READFAULT), + MAKE_HRESULT_ENTRY(STG_E_REVERTED), + MAKE_HRESULT_ENTRY(STG_E_SEEKERROR), + MAKE_HRESULT_ENTRY(STG_E_SHAREREQUIRED), + MAKE_HRESULT_ENTRY(STG_E_SHAREVIOLATION), + MAKE_HRESULT_ENTRY(STG_E_TOOMANYOPENFILES), + MAKE_HRESULT_ENTRY(STG_E_UNIMPLEMENTEDFUNCTION), + MAKE_HRESULT_ENTRY(STG_E_UNKNOWN), + MAKE_HRESULT_ENTRY(STG_E_WRITEFAULT), + MAKE_HRESULT_ENTRY(TYPE_E_AMBIGUOUSNAME), + MAKE_HRESULT_ENTRY(TYPE_E_BADMODULEKIND), + MAKE_HRESULT_ENTRY(TYPE_E_BUFFERTOOSMALL), + MAKE_HRESULT_ENTRY(TYPE_E_CANTCREATETMPFILE), + MAKE_HRESULT_ENTRY(TYPE_E_CANTLOADLIBRARY), + MAKE_HRESULT_ENTRY(TYPE_E_CIRCULARTYPE), + MAKE_HRESULT_ENTRY(TYPE_E_DLLFUNCTIONNOTFOUND), + MAKE_HRESULT_ENTRY(TYPE_E_DUPLICATEID), + MAKE_HRESULT_ENTRY(TYPE_E_ELEMENTNOTFOUND), + MAKE_HRESULT_ENTRY(TYPE_E_INCONSISTENTPROPFUNCS), + MAKE_HRESULT_ENTRY(TYPE_E_INVALIDSTATE), + MAKE_HRESULT_ENTRY(TYPE_E_INVDATAREAD), + MAKE_HRESULT_ENTRY(TYPE_E_IOERROR), + MAKE_HRESULT_ENTRY(TYPE_E_LIBNOTREGISTERED), + MAKE_HRESULT_ENTRY(TYPE_E_NAMECONFLICT), + MAKE_HRESULT_ENTRY(TYPE_E_OUTOFBOUNDS), + MAKE_HRESULT_ENTRY(TYPE_E_QUALIFIEDNAMEDISALLOWED), + MAKE_HRESULT_ENTRY(TYPE_E_REGISTRYACCESS), + MAKE_HRESULT_ENTRY(TYPE_E_SIZETOOBIG), + MAKE_HRESULT_ENTRY(TYPE_E_TYPEMISMATCH), + MAKE_HRESULT_ENTRY(TYPE_E_UNDEFINEDTYPE), + MAKE_HRESULT_ENTRY(TYPE_E_UNKNOWNLCID), + MAKE_HRESULT_ENTRY(TYPE_E_UNSUPFORMAT), + MAKE_HRESULT_ENTRY(TYPE_E_WRONGTYPEKIND), + MAKE_HRESULT_ENTRY(VIEW_E_DRAW), + + MAKE_HRESULT_ENTRY(CONNECT_E_NOCONNECTION), + MAKE_HRESULT_ENTRY(CONNECT_E_ADVISELIMIT), + MAKE_HRESULT_ENTRY(CONNECT_E_CANNOTCONNECT), + MAKE_HRESULT_ENTRY(CONNECT_E_OVERRIDDEN), + + MAKE_HRESULT_ENTRY(CLASS_E_NOTLICENSED), + MAKE_HRESULT_ENTRY(CLASS_E_NOAGGREGATION), + MAKE_HRESULT_ENTRY(CLASS_E_CLASSNOTAVAILABLE), + + MAKE_HRESULT_ENTRY(CTL_E_ILLEGALFUNCTIONCALL), + MAKE_HRESULT_ENTRY(CTL_E_OVERFLOW), + MAKE_HRESULT_ENTRY(CTL_E_OUTOFMEMORY), + MAKE_HRESULT_ENTRY(CTL_E_DIVISIONBYZERO), + MAKE_HRESULT_ENTRY(CTL_E_OUTOFSTRINGSPACE), + MAKE_HRESULT_ENTRY(CTL_E_OUTOFSTACKSPACE), + MAKE_HRESULT_ENTRY(CTL_E_BADFILENAMEORNUMBER), + MAKE_HRESULT_ENTRY(CTL_E_FILENOTFOUND), + MAKE_HRESULT_ENTRY(CTL_E_BADFILEMODE), + MAKE_HRESULT_ENTRY(CTL_E_FILEALREADYOPEN), + MAKE_HRESULT_ENTRY(CTL_E_DEVICEIOERROR), + MAKE_HRESULT_ENTRY(CTL_E_FILEALREADYEXISTS), + MAKE_HRESULT_ENTRY(CTL_E_BADRECORDLENGTH), + MAKE_HRESULT_ENTRY(CTL_E_DISKFULL), + MAKE_HRESULT_ENTRY(CTL_E_BADRECORDNUMBER), + MAKE_HRESULT_ENTRY(CTL_E_BADFILENAME), + MAKE_HRESULT_ENTRY(CTL_E_TOOMANYFILES), + MAKE_HRESULT_ENTRY(CTL_E_DEVICEUNAVAILABLE), + MAKE_HRESULT_ENTRY(CTL_E_PERMISSIONDENIED), + MAKE_HRESULT_ENTRY(CTL_E_DISKNOTREADY), + MAKE_HRESULT_ENTRY(CTL_E_PATHFILEACCESSERROR), + MAKE_HRESULT_ENTRY(CTL_E_PATHNOTFOUND), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDPATTERNSTRING), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDUSEOFNULL), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDFILEFORMAT), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDPROPERTYVALUE), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDPROPERTYARRAYINDEX), + MAKE_HRESULT_ENTRY(CTL_E_SETNOTSUPPORTEDATRUNTIME), + MAKE_HRESULT_ENTRY(CTL_E_SETNOTSUPPORTED), + MAKE_HRESULT_ENTRY(CTL_E_NEEDPROPERTYARRAYINDEX), + MAKE_HRESULT_ENTRY(CTL_E_SETNOTPERMITTED), + MAKE_HRESULT_ENTRY(CTL_E_GETNOTSUPPORTEDATRUNTIME), + MAKE_HRESULT_ENTRY(CTL_E_GETNOTSUPPORTED), + MAKE_HRESULT_ENTRY(CTL_E_PROPERTYNOTFOUND), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDCLIPBOARDFORMAT), + MAKE_HRESULT_ENTRY(CTL_E_INVALIDPICTURE), + MAKE_HRESULT_ENTRY(CTL_E_PRINTERERROR), + MAKE_HRESULT_ENTRY(CTL_E_CANTSAVEFILETOTEMP), + MAKE_HRESULT_ENTRY(CTL_E_SEARCHTEXTNOTFOUND), + MAKE_HRESULT_ENTRY(CTL_E_REPLACEMENTSTOOLONG), + }; + + // look for scode in the table + for (int i = 0; i < sizeof(hrNameTable) / sizeof(hrNameTable[0]); i++) + { + if (hr == hrNameTable[i].hr) { + swprintf_s(buf, (size_t)(bufSize - 1), hrNameTable[i].lpszName); + return; + } + } + // not found - make one up + swprintf_s(buf, (size_t)(bufSize - 1), L"OLE error 0x%08x", hr); +} + + +uint16_t *GetWin32ErrorMessage(uint16_t *buf, size_t buflen, Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { uint16_t *bufptr = buf; size_t len; if (msg) { @@ -63,18 +385,18 @@ uint16_t *GetWin32ErroroMessage(uint16_t *buf, size_t buflen, Isolate *isolate, return buf; } -char *GetWin32ErroroMessage(char *buf, size_t buflen, Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { +char *GetWin32ErrorMessage(char *buf, size_t buflen, Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { uint16_t buf_wide[ERROR_MESSAGE_WIDE_MAXSIZE]; - GetWin32ErroroMessage(buf_wide, ERROR_MESSAGE_WIDE_MAXSIZE, isolate, hrcode, msg, msg2, desc); + GetWin32ErrorMessage(buf_wide, ERROR_MESSAGE_WIDE_MAXSIZE, isolate, hrcode, msg, msg2, desc); int rcode = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf_wide, -1, buf, buflen, NULL, NULL); if (rcode < 0) rcode = 0; buf[rcode] = 0; return buf; } -Local GetWin32ErroroMessage(Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { +Local GetWin32ErrorMessage(Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2, LPCOLESTR desc) { uint16_t buf_wide[ERROR_MESSAGE_WIDE_MAXSIZE]; - return v8str(isolate, GetWin32ErroroMessage(buf_wide, ERROR_MESSAGE_WIDE_MAXSIZE, isolate, hrcode, msg, msg2, desc)); + return v8str(isolate, GetWin32ErrorMessage(buf_wide, ERROR_MESSAGE_WIDE_MAXSIZE, isolate, hrcode, msg, msg2, desc)); } //------------------------------------------------------------------------------------------------------- @@ -186,14 +508,22 @@ Local Variant2Value(Isolate *isolate, const VARIANT &v, bool allow_disp) return v8str(isolate, "[Dispatch]"); } case VT_UNKNOWN: { - CComPtr disp; - if (allow_disp && UnknownDispGet(by_ref ? *v.ppunkVal : v.punkVal, &disp)) { - return DispObject::NodeCreate(isolate, disp, L"Unknown", option_auto); + if (allow_disp) + { + CComPtr disp; + if (UnknownDispGet(by_ref ? *v.ppunkVal : v.punkVal, &disp)) { + return DispObject::NodeCreate(isolate, disp, L"Unknown", option_auto); + } } // Check for NULL value if ((by_ref && *v.ppunkVal) || v.punkVal) { - return VariantObject::NodeCreate(isolate, v); + if (allow_disp) { + return VariantObject::NodeCreate(isolate, v); + } + else { + return v8str(isolate, "[Unknown]"); + } } else if (!v.punkVal) { return Null(isolate); @@ -751,6 +1081,58 @@ void NodeMethods::add(Isolate* isolate, Local& clazz, const ch //------------------------------------------------------------------------------------------------------- +/* Message loop. Just like with WScript it is executed while the script is waiting. + So if you have something showing, for example, a popup message, then you will only + see it when you do WScript.Sleep. +*/ + +void DoEvents() +{ + MSG msg; + BOOL result; + + if (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + result = ::GetMessage(&msg, NULL, 0, 0); + if (result == 0) // WM_QUIT + { + ::PostQuitMessage(msg.wParam); + } + else if (result == -1) + { + // Handle errors/exit application, etc. + } + else + { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } +} + +/* Returns the amount of milliseconds elapsed since the UNIX epoch. Works on both + * windows and linux. */ + +long long GetTimeMs64() +{ + /* Windows */ + FILETIME ft; + LARGE_INTEGER li; + + /* Get the amount of 100 nano seconds intervals elapsed since January 1, 1601 (UTC) and copy it + * to a LARGE_INTEGER structure. */ + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + + long long ret = li.QuadPart; + ret -= 116444736000000000LL; /* Convert from file time to UNIX epoch time. */ + ret /= 10000; /* From 100 nano seconds (10^-7) to 1 millisecond (10^-3) intervals */ + + return ret; + +} + // Sleep is essential to have proper WScript emulation void WinaxSleep(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); @@ -761,7 +1143,12 @@ void WinaxSleep(const FunctionCallbackInfo& args) { return; } uint32_t ms = (args[0]->Uint32Value(ctx)).FromMaybe(0); - Sleep(ms); + long long start = GetTimeMs64(); + do + { + DoEvents(); + Sleep(1); + } while (GetTimeMs64() - start < ms); args.GetReturnValue().SetUndefined(); } diff --git a/src/utils.h b/src/utils.h index caae938..b743760 100644 --- a/src/utils.h +++ b/src/utils.h @@ -210,29 +210,48 @@ class CComPtr { #endif //------------------------------------------------------------------------------------------------------- -Local GetWin32ErroroMessage(Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2 = 0, LPCOLESTR desc = 0); +Local GetWin32ErrorMessage(Isolate *isolate, HRESULT hrcode, LPCOLESTR msg, LPCOLESTR msg2 = 0, LPCOLESTR desc = 0); inline Local Win32Error(Isolate *isolate, HRESULT hrcode, LPCOLESTR id = 0, LPCOLESTR msg = 0) { - auto err = Exception::Error(GetWin32ErroroMessage(isolate, hrcode, id, msg)); + auto err = Exception::Error(GetWin32ErrorMessage(isolate, hrcode, id, msg)); auto obj = Local::Cast(err); obj->Set(isolate->GetCurrentContext(), v8str(isolate, "errno"), Integer::New(isolate, hrcode)); return err; } +void GetScodeString(HRESULT hr, wchar_t* buf, int bufSize); + inline Local DispError(Isolate *isolate, HRESULT hrcode, LPCOLESTR id = 0, LPCOLESTR msg = 0, EXCEPINFO *except = 0) { Local ctx = isolate->GetCurrentContext(); CComBSTR desc; - CComPtr errinfo; + CComPtr errinfo; + + std::wstring emsg; + emsg.reserve(1024); + if (except && except->scode) { + wchar_t wc[1024]; + GetScodeString(except->scode, wc, sizeof(wc) / sizeof(wc[0])); + emsg += msg; + emsg += L": "; + emsg += wc; + } + else { + emsg = std::wstring(msg); + } + HRESULT hr = GetErrorInfo(0, &errinfo); if (hr == S_OK) errinfo->GetDescription(&desc); - auto err = Exception::Error(GetWin32ErroroMessage(isolate, hrcode, id, msg, desc)); + auto err = Exception::Error(GetWin32ErrorMessage(isolate, hrcode, id, emsg.c_str(), desc)); auto obj = Local::Cast(err); obj->Set(ctx, v8str(isolate, "errno"), Integer::New(isolate, hrcode)); if (except) { if (except->scode != 0) obj->Set(ctx, v8str(isolate, "code"), Integer::New(isolate, except->scode)); else if (except->wCode != 0) obj->Set(ctx, v8str(isolate, "code"), Integer::New(isolate, except->wCode)); if (except->bstrSource != 0) obj->Set(ctx, v8str(isolate, "source"), v8str(isolate, except->bstrSource)); - if (except->bstrDescription != 0) obj->Set(ctx, v8str(isolate, "description"), v8str(isolate, except->bstrDescription)); + if (except->bstrDescription != 0) { + obj->Set(ctx, v8str(isolate, "message"), v8str(isolate, except->bstrDescription)); + obj->Set(ctx, v8str(isolate, "description"), v8str(isolate, except->bstrDescription)); + } } return err; } diff --git a/test/excel.js b/test/excel.js index f30dabb..f5c0851 100644 --- a/test/excel.js +++ b/test/excel.js @@ -70,6 +70,15 @@ describe("COM from JS object", function() { it("call method with object argument", function() { if (com_obj) assert.equal(com_obj.func2(com_obj), js_obj.text); }); + + it("COM error message", function() { + var fso = new ActiveXObject("Scripting.FileSystemObject"); + try { + fso.DeleteFile("c:\\noexist.txt"); + } catch(e) { + assert.equal(e.message, "DispInvoke: DeleteFile: CTL_E_FILENOTFOUND Exception occurred.\r\n"); + } + }); }); describe("Excel with JS object", function() { From 4a13e2db9bf2c0b8a29c061c5686911f85732e91 Mon Sep 17 00:00:00 2001 From: durs Date: Tue, 26 Sep 2023 11:59:58 +0300 Subject: [PATCH 7/9] version 3.4.1 --- package.json | 2 +- test/excel.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9959a41..f4a932a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "winax", - "version": "3.3.7", + "version": "3.4.1", "description": "Windows COM bindings", "homepage": "https://github.com/durs/node-activex", "keywords": [ diff --git a/test/excel.js b/test/excel.js index f5c0851..642f3b9 100644 --- a/test/excel.js +++ b/test/excel.js @@ -76,7 +76,8 @@ describe("COM from JS object", function() { try { fso.DeleteFile("c:\\noexist.txt"); } catch(e) { - assert.equal(e.message, "DispInvoke: DeleteFile: CTL_E_FILENOTFOUND Exception occurred.\r\n"); + // assert.equal(e.message, "DispInvoke: DeleteFile: CTL_E_FILENOTFOUND Exception occurred.\r\n"); + assert(e.message.startsWith("DispInvoke: DeleteFile: CTL_E_FILENOTFOUND")); } }); }); From ea7ff0afba3225b60b2b3ec1aafcadd301665f5d Mon Sep 17 00:00:00 2001 From: Manuel Leclerc Date: Tue, 6 Feb 2024 14:54:07 +0100 Subject: [PATCH 8/9] FIX Build for Electron 28.2 --- src/stdafx.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/stdafx.h b/src/stdafx.h index 94da098..a4a046f 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -1,5 +1,7 @@ #pragma once +#define NOMINMAX // To remove conflicts with recent v8 code std::numeric_limits::max() + #include // Windows Header Files: From c792997baed642685610528f08c36198e76a6d8c Mon Sep 17 00:00:00 2001 From: durs Date: Wed, 7 Feb 2024 13:18:37 +0300 Subject: [PATCH 9/9] version 3.4.2, fix build for Electron 28.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fd638ef..f60f817 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "winax", - "version": "3.3.7", + "version": "3.4.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "winax", - "version": "3.3.7", + "version": "3.4.2", "license": "MIT", "os": [ "win32" diff --git a/package.json b/package.json index f4a932a..95bbad0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "winax", - "version": "3.4.1", + "version": "3.4.2", "description": "Windows COM bindings", "homepage": "https://github.com/durs/node-activex", "keywords": [