11/*
22This file is a part of the NVDA project.
33URL: http://www.nvda-project.org/
4- Copyright 2006-2010 NVDA contributers.
4+ Copyright 2006-2021 NV Access Limited
55 This program is free software: you can redistribute it and/or modify
66 it under the terms of the GNU General Public License version 2.0, as published by
77 the Free Software Foundation.
@@ -26,6 +26,8 @@ This license can be found at:
2626#include < remote/nvdaInProcUtils.h>
2727#include " COMProxyRegistration.h"
2828#include " IA2Support.h"
29+ #include < atlcomcli.h>
30+ #include " textFromIAccessible.h"
2931
3032using namespace std ;
3133
@@ -251,26 +253,107 @@ bool findContentDescendant(IAccessible2* pacc2, long what, long* descendantID, l
251253 return foundDescendant;
252254}
253255
256+
257+ CComPtr<IAccessible2> getIA2 (const HWND hwnd, const long parentID) {
258+ VARIANT varChild;
259+ CComPtr<IAccessible> pacc;
260+ AccessibleObjectFromEvent (
261+ hwnd,
262+ OBJID_CLIENT ,
263+ parentID,
264+ &pacc.p ,
265+ &varChild
266+ );
267+
268+ if (!pacc) {
269+ return nullptr ;
270+ };
271+
272+ CComQIPtr<IServiceProvider, &IID_IServiceProvider> pserv (pacc);
273+ if (!pserv) {
274+ return nullptr ;
275+ }
276+
277+ CComPtr<IAccessible2> pacc2;
278+ { // scoping for: ppvObject
279+ void ** ppvObject = reinterpret_cast <void **>(&pacc2.p );
280+ pserv->QueryService (IID_IAccessible, IID_IAccessible2, ppvObject);
281+ }
282+
283+ return pacc2;
284+ }
285+
254286error_status_t nvdaInProcUtils_IA2Text_findContentDescendant (handle_t bindingHandle, const unsigned long windowHandle, long parentID, long what, long * descendantID, long * descendantOffset) {
255- HWND hwnd=( HWND ) UlongToHandle (windowHandle);
287+ HWND hwnd = static_cast < HWND >( UlongToHandle (windowHandle) );
256288 auto func=[&] {
257- IAccessible* pacc=NULL ;
258- VARIANT varChild;
259- AccessibleObjectFromEvent ((HWND )hwnd,OBJID_CLIENT ,parentID,&pacc,&varChild);
260- if (!pacc) return ;
261- IAccessible2* pacc2=NULL ;
262- IServiceProvider* pserv=NULL ;
263- pacc->QueryInterface (IID_IServiceProvider,(void **)&pserv);
264- pacc->Release ();
265- if (!pserv) return ;
266- pserv->QueryService (IID_IAccessible,IID_IAccessible2,(void **)&pacc2);
267- pserv->Release ();
268- if (!pacc2) return ;
269- findContentDescendant (pacc2,what,descendantID,descendantOffset);
270- pacc2->Release ();
289+ auto pacc2 = getIA2 (hwnd, parentID);
290+ if (!pacc2) {
291+ return ;
292+ }
293+ findContentDescendant (pacc2, what, descendantID, descendantOffset);
271294 };
272- if (!execInThread (GetWindowThreadProcessId (hwnd,NULL ),func)) {
273- LOG_DEBUGWARNING (L" Could not execute findContentDescendant in UI thread" );
295+
296+ auto windowThreadProcId = GetWindowThreadProcessId (hwnd, nullptr );
297+ auto res = execInThread (windowThreadProcId, func);
298+ if (!res) {
299+ LOG_DEBUGWARNING (L" Could not execute findContentDescendant in UI thread" );
274300 }
275301 return 0 ;
276302}
303+
304+
305+ error_status_t nvdaInProcUtils_getTextFromIAccessible (
306+ handle_t bindingHandle,
307+ const unsigned long windowHandle,
308+ long parentID,
309+ // Params for getTextFromIAccessible
310+ BSTR * outBuf,
311+ const boolean useNewText,
312+ const boolean recurse,
313+ const boolean includeTopLevelText
314+ ) {
315+ LOG_DEBUG (L" Called nvdaInProcUtils_getTextFromIAccessible" );
316+ if (outBuf == nullptr ) {
317+ LOG_ERROR (L" outBuff is null." );
318+ return 0 ;
319+ }
320+ HWND hwnd = static_cast <HWND >(UlongToHandle (windowHandle));
321+ auto func = [&] () -> void {
322+ auto pacc2 = getIA2 (hwnd, parentID);
323+ if (!pacc2) {
324+ return ;
325+ }
326+ wstring textBuf;
327+ const auto gotText = getTextFromIAccessible (
328+ textBuf,
329+ pacc2,
330+ useNewText,
331+ recurse,
332+ includeTopLevelText
333+ );
334+ if (!gotText) {
335+ LOG_DEBUGWARNING (L" Unable to get text." );
336+ return ;
337+ }
338+ if (textBuf.empty ()) {
339+ LOG_DEBUGWARNING (L" textBuf empty." );
340+ return ;
341+ }
342+ auto copySize = size_t (std::numeric_limits<UINT >::max);
343+ if (copySize < textBuf.size ()) {
344+ LOG_ERROR (L" Size of buffer larger than can be allocated with SysAllocStringLen, buffer will be truncated." );
345+ }
346+ else {
347+ copySize = textBuf.size ();
348+ }
349+ *outBuf = SysAllocStringLen (textBuf.data (), UINT (copySize));
350+ return ;
351+ };
352+
353+ auto windowThreadProcId = GetWindowThreadProcessId (hwnd, nullptr );
354+ auto res = execInThread (windowThreadProcId, func);
355+ if (!res) {
356+ LOG_DEBUGWARNING (L" Could not execute getTextFromIAccessible in UI thread" );
357+ }
358+ return 0 ;
359+ }
0 commit comments