error_status_t nvdaInProcUtils_getActiveObject(handle_t bindingHandle, const wchar_t* progid, IUnknown** ppUnknown) { if(!progid) { LOG_DEBUGWARNING(L"NULL progid"); return E_FAIL; } IID clsid; HRESULT res=CLSIDFromString(progid,&clsid); if(res!=NOERROR) { LOG_DEBUGWARNING(L"CLSIDFromString for "<<progid<<L" returned "<<res); return res; } return GetActiveObject(clsid,NULL,ppUnknown); }
BOOL installIA2Support() { LPFNGETCLASSOBJECT IA2Dll_DllGetClassObject; int i; int res; if(isIA2Installed) return TRUE; if((IA2DllHandle=CoLoadLibrary(IA2DllPath,FALSE))==NULL) { LOG_ERROR(L"CoLoadLibrary failed"); return FALSE; } IA2Dll_DllGetClassObject=(LPFNGETCLASSOBJECT)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllGetClassObject"); assert(IA2Dll_DllGetClassObject); //IAccessible2 proxy dll must have this function IUnknown* ia2ClassObjPunk=NULL; if((res=IA2Dll_DllGetClassObject(IAccessible2ProxyIID,IID_IUnknown,(LPVOID*)&ia2ClassObjPunk))!=S_OK) { LOG_ERROR(L"Error calling DllGetClassObject, code "<<res); CoFreeLibrary(IA2DllHandle); IA2DllHandle=0; return FALSE; } if((res=CoRegisterClassObject(IAccessible2ProxyIID,ia2ClassObjPunk,CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE,(LPDWORD)&IA2RegCooky))!=S_OK) { LOG_DEBUGWARNING(L"Error registering class object, code "<<res); ia2ClassObjPunk->Release(); CoFreeLibrary(IA2DllHandle); IA2DllHandle=0; return FALSE; } ia2ClassObjPunk->Release(); for(i=0;i<ARRAYSIZE(ia2Iids);++i) { CoGetPSClsid(ia2Iids[i],&(_ia2PSClsidBackups[i])); CoRegisterPSClsid(ia2Iids[i],IAccessible2ProxyIID); } isIA2Installed=TRUE; return TRUE; }
PROPERTYID registerUIAProperty(GUID* guid, LPCWSTR programmaticName, UIAutomationType propertyType) { HRESULT res; IUIAutomationRegistrar* registrar=NULL; if(CoCreateInstance(CLSID_CUIAutomationRegistrar,NULL,CLSCTX_INPROC_SERVER,IID_IUIAutomationRegistrar,(void**)®istrar)!=S_OK) { LOG_DEBUGWARNING(L"Could not create instance of IUIAutomationRegistrar"); return 0; } UIAutomationPropertyInfo info={*guid,programmaticName,propertyType}; PROPERTYID propertyId=0; res=registrar->RegisterProperty(&info,&propertyId); if(res!=S_OK) { LOG_DEBUGWARNING(L"IUIAutomationRegistrar::RegisterProperty failed with "<<res); return 0; } registrar->Release(); return propertyId; }
error_status_t nvdaInProcUtils_sysListView32_getGroupInfo(handle_t bindingHandle, long windowHandle, int groupIndex, BSTR* header, BSTR* footer, int* state) { LVGROUP group={0}; group.cbSize=sizeof(group); group.mask=LVGF_HEADER|LVGF_FOOTER|LVGF_STATE; group.stateMask=0xffffffff; if(!SendMessage((HWND)windowHandle,LVM_GETGROUPINFOBYINDEX,(WPARAM)groupIndex,(LPARAM)&group)) { LOG_DEBUGWARNING(L"LVM_GETGROUPINFOBYINDEX failed"); return 1; } if(group.pszHeader) *header=SysAllocString(group.pszHeader); if(group.pszFooter) *footer=SysAllocString(group.pszFooter); *state=group.state; return 0; }
/* Overview of the structures being accessed: pRange.Fields property pRange.Fields.Count property pRange.Fields.Item method - takes an int (starting at 1) to give item 1 up to item Count. Returns a Field Field.Type property Field.Result property - the range for the ref / hyperlink object. This is the displayed range. Field.Code property - Not used, but gives the hidden part of the ref / hyperlink. Field.Result.Start property Field.Result.End property */ Fields::Fields(IDispatch* pRange) { IDispatchPtr pDispatchFields = nullptr; auto res = _com_dispatch_raw_propget( pRange, wdDISPID_RANGE_FIELDS, VT_DISPATCH, &pDispatchFields); if( res != S_OK || !pDispatchFields ) { LOG_DEBUGWARNING(L"error getting fields from range"); return; } int count = 0; res = _com_dispatch_raw_propget( pDispatchFields, wdDISPID_FIELDS_COUNT, VT_I4, &count); if( res != S_OK || count <= 0 ) { return; } for(int i = 1; i <= count; ++i) { IDispatchPtr pDispatchItem = nullptr; res = _com_dispatch_raw_method( pDispatchFields, wdDISPID_FIELDS_ITEM, DISPATCH_METHOD, VT_DISPATCH, &pDispatchItem, L"\x0003", i); if( res != S_OK || !pDispatchItem) { LOG_DEBUGWARNING(L"error getting field item"); continue; } /* Fields can be of many types, to get this we look at Type property. We care about: Ref - a Reference to some other part of the file Hyperlink - a link to another part of the file or to an external URL The following are defined on msdn (WdFieldType Enumeration - https://msdn.microsoft.com/en-us/library/office/ff192211.aspx) */ const int CROSS_REFERENCE_TYPE_VALUE = 3; // wdFieldRef const int HYPERLINK_TYPE_VALUE = 88; // wdFieldHyperlink const int PAGE_NUMBER_TYPE_VALUE = 33; // wdFieldPage int type = -1; res = _com_dispatch_raw_propget( pDispatchItem, wdDISPID_FIELDS_ITEM_TYPE, VT_I4, &type); if( res != S_OK || !(type == CROSS_REFERENCE_TYPE_VALUE || type == HYPERLINK_TYPE_VALUE || type == PAGE_NUMBER_TYPE_VALUE) ) { continue; } IDispatchPtr pDispatchFieldResult = nullptr; res = _com_dispatch_raw_propget( pDispatchItem, wdDISPID_FIELDS_ITEM_RESULT, VT_DISPATCH, &pDispatchFieldResult); if( res != S_OK || !pDispatchFieldResult) { LOG_DEBUGWARNING(L"error getting the result from the field item."); continue; } long resultStart = 0, resultEnd = 0; auto ok = S_OK == _com_dispatch_raw_propget( pDispatchFieldResult, wdDISPID_RANGE_START, VT_I4, &resultStart) && S_OK == _com_dispatch_raw_propget( pDispatchFieldResult, wdDISPID_RANGE_END, VT_I4, &resultEnd); if(!ok) { LOG_DEBUGWARNING(L"error getting range start and end points"); continue; } auto itemRange = std::make_pair(resultStart, resultEnd); switch(type) { case CROSS_REFERENCE_TYPE_VALUE: // intentional fall through to hyperlink case case HYPERLINK_TYPE_VALUE: m_links.push_back(itemRange); break; case PAGE_NUMBER_TYPE_VALUE: m_pageNumbers.push_back(itemRange); break; } } }