1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #include "stdafx.h"
23 #include "UAccCOM2.h"
24 #include "MAccessible.h"
25
26 #include <algorithm>
27 #include "AccAction.h"
28
29 #include <com/sun/star/accessibility/XAccessibleText.hpp>
30 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
31 #include <com/sun/star/accessibility/XAccessibleImage.hpp>
32 #include <com/sun/star/accessibility/XAccessibleTable.hpp>
33 #include <com/sun/star/accessibility/XAccessibleExtendedComponent.hpp>
34 #include <com/sun/star/accessibility/XAccessibleAction.hpp>
35 #include <com/sun/star/accessibility/XAccessibleKeyBinding.hpp>
36 #include <com/sun/star/accessibility/XAccessibleHyperText.hpp>
37 #include <com/sun/star/accessibility/XAccessibleHyperlink.hpp>
38 #include <com/sun/star/accessibility/XAccessibleRelationSet.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <com/sun/star/accessibility/AccessibleRole.hpp>
41 #include <com/sun/star/accessibility/XAccessibleGroupPosition.hpp>
42 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
43 #include <com/sun/star/accessibility/XAccessibleExtendedAttributes.hpp>
44 #include <com/sun/star/style/LineSpacing.hpp>
45 #include <com/sun/star/style/TabStop.hpp>
46 #include <com/sun/star/container/XIndexReplace.hpp>
47
48 #include "act.hxx"
49
50 using namespace com::sun::star::accessibility::AccessibleStateType;
51
52 // IA2 states mapping, and name
53 // maintenance the consistency, change one array, change the three all
54 long IA2_STATES[] =
55 {
56 IA2_STATE_ACTIVE, // = 0x1;
57 IA2_STATE_ARMED, // = 0x2;
58 IA2_STATE_DEFUNCT, // = 0x4;
59 IA2_STATE_EDITABLE, // = 0x8;
60 IA2_STATE_HORIZONTAL, // = 0x10;
61 IA2_STATE_ICONIFIED, // = 0x20;
62 IA2_STATE_INVALID_ENTRY, // = 0x80;
63 IA2_STATE_MANAGES_DESCENDANTS, // = 0x100;
64 IA2_STATE_MODAL, // = 0x200;
65 IA2_STATE_MULTI_LINE, // = 0x400;
66 IA2_STATE_OPAQUE, // = 0x800;
67 IA2_STATE_REQUIRED, // = 0x2000;
68 IA2_STATE_SELECTABLE_TEXT, // = 0x3000;
69 IA2_STATE_SINGLE_LINE, // = 0x4000;
70 IA2_STATE_STALE, // = 0x8000;
71 IA2_STATE_SUPPORTS_AUTOCOMPLETION, // = 0x10000;
72 IA2_STATE_TRANSIENT, //= 0x20000;
73 IA2_STATE_VERTICAL // = 0x40000;
74 };
75 /*
76
77 <=== map ===>
78
79 */
80 short UNO_STATES[] =
81 {
82 ACTIVE, // = (sal_Int16)1;
83 ARMED, // = (sal_Int16)2;
84 DEFUNC, // = (sal_Int16)5;
85 EDITABLE, // = (sal_Int16)6;
86 HORIZONTAL, // = (sal_Int16)12;
87 ICONIFIED, // = (sal_Int16)13;
88 -1, //IA2_STATE_INVALID_ENTRY
89 MANAGES_DESCENDANTS, // = (sal_Int16)15;
90 MODAL, // = (sal_Int16)16;
91 MULTI_LINE, // = (sal_Int16)17;
92 OPAQUE, // = (sal_Int16)19;
93 -1, //IA2_STATE_REQUIRED
94 -1, //IA2_STATE_SELECTABLE_TEXT
95 SINGLE_LINE, // = (sal_Int16)26;
96 STALE, // = (sal_Int16)27;
97 -1, //IA2_STATE_SUPPORTS_AUTOCOMPLETION
98 TRANSIENT, //IA2_STATE_TRANSIENT
99 VERTICAL // = (sal_Int16)29;
100 };
101
102 // <=== map ===>
103
104 BSTR IA2_STATES_NAME[] =
105 {
106 _T("Active"),
107 _T("Armed"),
108 _T("Defunct"),
109 _T("Editable"),
110 _T("Horizontal"),
111 _T("Iconified"),
112 _T("Invalid Entry"),
113 _T("Manages Decendents"),
114 _T("Modal"),
115 _T("Multi Line"),
116 _T("Opaque"),
117 _T("Required"),
118 _T("Selectable Text"),
119 _T("Single Line"),
120 _T("Stale"),
121 _T("Supports Autocompletion"),
122 _T("Transient"),
123 _T("Vertical")
124 };
125
126 // IA2 states mapping, and name
127 // maintenance the consistency. change one, change them all
128
129 BSTR UNO_ALL_STATES[] =
130 {
131 _T("INVALID"), // INVALID ( 0 )
132 _T("ACTIVE"), // ACTIVE ( 1 )
133 _T("ARMED"), // ARMED ( 2 )
134 _T("BUSY"), // BUSY ( 3 )
135 _T("CHECKED"), // CHECKED ( 4 )
136 _T("DEFUNC"), // DEFUNC ( 5 )
137 _T("EDITABLE"), // EDITABLE ( 6 )
138 _T("ENABLED"), // ENABLED ( 7 )
139 _T("EXPANDABLE"), // EXPANDABLE ( 8 )
140 _T("EXPANDED"), // EXPANDED ( 9 )
141 _T("FOCUSABLE"), // FOCUSABLE ( 10 )
142 _T("FOCUSED"), // FOCUSED ( 11 )
143 _T("HORIZONTAL"), // HORIZONTAL ( 12 )
144 _T("ICONIFIED"), // ICONIFIED ( 13 )
145 _T("INDETERMINATE"), // INDETERMINATE ( 14 )
146 _T("MANAGES_DESCENDANTS"),// MANAGES_DESCENDANTS ( 15 )
147 _T("MODAL"), // MODAL ( 16 )
148 _T("MULTI_LINE"), // MULTI_LINE ( 17 )
149 _T("MULTI_SELECTABLE"), // MULTI_SELECTABLE ( 18 )
150 _T("OPAQUE"), // OPAQUE ( 19 )
151 _T("PRESSED"), // PRESSED ( 20 )
152 _T("RESIZABLE"), // RESIZABLE ( 21 )
153 _T("SELECTABLE"), // SELECTABLE ( 22 )
154 _T("SELECTED"), // SELECTED ( 23 )
155 _T("SENSITIVE"), // SENSITIVE ( 24 )
156 _T("SHOWING"), // SHOWING ( 25 )
157 _T("SINGLE_LINE"), // SINGLE_LINE ( 26 )
158 _T("STALE"), // STALE ( 27 )
159 _T("TRANSIENT"), // TRANSIENT ( 28 )
160 _T("VERTICAL"), // VERTICAL ( 29 )
161 _T("VISIBLE"), // VISIBLE ( 30 )
162 _T("MOVEABLE"), // MOVEABLE ( 31 )
163 _T("OFFSCREEN"), // OFFSCREEN ( 32 )
164 _T("COLLAPSE"), // COLLAPSE ( 33 )
165 _T("DEFAULT") // DEFAULT ( 34 )
166 };
167
168
169 using namespace com::sun::star::accessibility::AccessibleRole;
170
171
172
173 #define QUERYXINTERFACE(ainterface) \
174 { \
175 if(pXAcc == NULL) \
176 return FALSE; \
177 pRContext = pXAcc->getAccessibleContext(); \
178 if( !pRContext.is() ) \
179 { \
180 return FALSE; \
181 } \
182 Reference<X##ainterface> pRXI(pRContext,UNO_QUERY);\
183 if( !pRXI.is() ) \
184 { \
185 return FALSE; \
186 } \
187 *ppXI = (XInterface*)pRXI.get(); \
188 return TRUE; \
189 }
190
191 #define ISDESTROY() \
192 if(m_isDestroy) \
193 return S_FALSE;
194
195
196 AccObjectManagerAgent* CMAccessible::g_pAgent = NULL;
197
CMAccessible()198 CMAccessible::CMAccessible():
199 m_iRole(0x00),
200 m_dState(0x00),
201 m_dChildID(0x00),
202 m_dFocusChildID(UACC_NO_FOCUS),
203 m_hwnd(NULL),
204 m_pIParent(NULL),
205 m_pszName(NULL),
206 m_pszValue(NULL),
207 m_pszDescription(NULL),
208 m_isDestroy(FALSE),
209 m_pszActionDescription(NULL),
210 m_pXAction(NULL),
211 m_bRequiresSave(FALSE),
212 pUNOInterface(NULL)
213 {
214 m_sLocation.m_dLeft=0;
215 m_sLocation.m_dTop = 0;
216 m_sLocation.m_dWidth=0;
217 m_sLocation.m_dHeight=0;
218 CEnumVariant::Create(&m_pEnumVar);
219 m_containedObjects.clear();
220 }
221
~CMAccessible()222 CMAccessible::~CMAccessible()
223 {
224 if(m_pszName!=NULL)
225 {
226 SAFE_SYSFREESTRING(m_pszName);
227 m_pszName=NULL;
228 }
229 if(m_pszValue!=NULL)
230 {
231 SAFE_SYSFREESTRING(m_pszValue);
232 m_pszValue=NULL;
233 }
234 if(m_pszDescription!=NULL)
235 {
236 SAFE_SYSFREESTRING(m_pszDescription);
237 m_pszDescription=NULL;
238 }
239
240 if(m_pszActionDescription!=NULL)
241 {
242 SAFE_SYSFREESTRING(m_pszActionDescription);
243 m_pszActionDescription=NULL;
244 }
245
246 if(m_pIParent)
247 {
248 m_pIParent->Release();
249 m_pIParent=NULL;
250 }
251 pRef = NULL;
252 m_pEnumVar->Release();
253 m_containedObjects.clear();
254 pRContext = NULL;
255 }
256
257 /**
258 * Returns the Parent IAccessible interface pointer to AT.
259 * It should add reference, and the client should release the component.
260 * It should return E_FAIL when the parent point is null.
261 * @param ppdispParent [in,out] used to return the parent interface point.
262 * when the point is null, should return null.
263 * @return S_OK if successful and E_FAIL if the m_pIParent is NULL.
264 */
get_accParent(IDispatch ** ppdispParent)265 STDMETHODIMP CMAccessible::get_accParent(IDispatch **ppdispParent)
266 {
267
268 CHECK_ENABLE_INF
269 ENTER_PROTECTED_BLOCK
270 ISDESTROY()
271 // #CHECK#
272 if(ppdispParent == NULL)
273 {
274 return E_INVALIDARG;
275 }
276
277 if(m_pIParent)
278 {
279 *ppdispParent = m_pIParent;
280 (*ppdispParent)->AddRef();
281 return S_OK;
282 }
283 else if(m_hwnd)
284 {
285 HRESULT hr = AccessibleObjectFromWindow(m_hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent);
286 if( ! SUCCEEDED( hr ) || ! ppdispParent )
287 {
288 return S_FALSE;
289 }
290 return S_OK;
291 }
292 return S_FALSE;
293
294 LEAVE_PROTECTED_BLOCK
295 }
296
297 /**
298 * Returns child count of current COM object.
299 * @param pcountChildren [in,out] used to return the children count.
300 * @return S_OK if successful.
301 */
get_accChildCount(long * pcountChildren)302 STDMETHODIMP CMAccessible::get_accChildCount(long *pcountChildren)
303 {
304
305 CHECK_ENABLE_INF
306 ENTER_PROTECTED_BLOCK
307 ISDESTROY()
308 // #CHECK#
309 if(pcountChildren == NULL)
310 {
311 return E_INVALIDARG;
312 }
313
314 if(!pUNOInterface)
315 return S_FALSE;
316
317 Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
318 if( pRContext.is() )
319 {
320 *pcountChildren = pRContext->getAccessibleChildCount();
321 }
322
323 return S_OK;
324
325 LEAVE_PROTECTED_BLOCK
326 }
327
328 /**
329 * Returns child interface pointer for AT according to input child ID.
330 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
331 * the child ID specify child index from 0 to children count, 0 stands for object self.
332 * @param ppdispChild, [in,out] use to return the child interface point.
333 * @return S_OK if successful and S_FALSE if failure.
334 */
get_accChild(VARIANT varChild,IDispatch ** ppdispChild)335 STDMETHODIMP CMAccessible::get_accChild(VARIANT varChild, IDispatch **ppdispChild)
336 {
337
338 CHECK_ENABLE_INF
339 ENTER_PROTECTED_BLOCK
340 ISDESTROY()
341 // #CHECK#
342 if(ppdispChild == NULL)
343 {
344 return E_INVALIDARG;
345 }
346 if(varChild.vt==VT_I4)
347 {
348 //get child interface pointer due to child ID
349 if(varChild.lVal==CHILDID_SELF)
350 {
351 AddRef();
352 *ppdispChild = this;
353 return S_OK;
354 }
355 *ppdispChild = GetChildInterface(varChild.lVal);
356 if((*ppdispChild) == NULL)
357 return E_FAIL;
358 (*ppdispChild)->AddRef();
359 return S_OK;
360 }
361 return S_FALSE;
362
363 LEAVE_PROTECTED_BLOCK
364 }
365
366 /**
367 * Returns the accessible name of the current COM object self or its one child to AT.
368 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
369 * the child ID specify child index from 0 to children count, 0 stands for object self.
370 * @param pszName, [in,out] use to return the name of the proper object.
371 * @return S_OK if successful and S_FALSE if failure.
372 */
get_accName(VARIANT varChild,BSTR * pszName)373 STDMETHODIMP CMAccessible::get_accName(VARIANT varChild, BSTR *pszName)
374 {
375
376 CHECK_ENABLE_INF
377 ENTER_PROTECTED_BLOCK
378 ISDESTROY()
379 // #CHECK#
380 if(pszName == NULL)
381 {
382 return E_INVALIDARG;
383 }
384 if(varChild.vt==VT_I4)
385 {
386 if(varChild.lVal==CHILDID_SELF)
387 {
388 SAFE_SYSFREESTRING(*pszName);
389 *pszName = SysAllocString(m_pszName);
390 return S_OK;
391 }
392
393 long lVal = varChild.lVal;
394 varChild.lVal = CHILDID_SELF;
395 IMAccessible *pChild = this->GetChildInterface(lVal);
396 if(!pChild)
397 return E_FAIL;
398 return pChild->get_accName(varChild,pszName);
399 }
400 return S_FALSE;
401
402 LEAVE_PROTECTED_BLOCK
403 }
404
405 /**
406 * Returns the accessible value of the current COM object self or its one child to AT.
407 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
408 * the child ID specify child index from 0 to children count, 0 stands for object self.
409 * @param pszValue, [in,out] use to return the value of the proper object.
410 * @return S_OK if successful and S_FALSE if failure.
411 */
get_accValue(VARIANT varChild,BSTR * pszValue)412 STDMETHODIMP CMAccessible::get_accValue(VARIANT varChild, BSTR *pszValue)
413 {
414
415 CHECK_ENABLE_INF
416 ENTER_PROTECTED_BLOCK
417 ISDESTROY()
418 // #CHECK#
419 if( pszValue == NULL )
420 {
421 return E_INVALIDARG;
422 }
423 if( varChild.vt==VT_I4 )
424 {
425 if(varChild.lVal==CHILDID_SELF)
426 {
427 if(m_dState & STATE_SYSTEM_PROTECTED)
428 return E_ACCESSDENIED;
429
430 if ( m_pszValue !=NULL && wcslen(m_pszValue) == 0 )
431 return S_OK;
432
433 SAFE_SYSFREESTRING(*pszValue);
434 *pszValue = SysAllocString(m_pszValue);
435 return S_OK;
436 }
437
438 long lVal = varChild.lVal;
439 varChild.lVal = CHILDID_SELF;
440 IMAccessible *pChild = this->GetChildInterface(lVal);
441 if(!pChild)
442 return E_FAIL;
443 return pChild->get_accValue(varChild,pszValue);
444 }
445 return S_FALSE;
446
447 LEAVE_PROTECTED_BLOCK
448 }
449
450 /**
451 * Returns the accessible description of the current COM object self or its one child to AT.
452 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
453 * the child ID specify child index from 0 to children count, 0 stands for object self.
454 * @param pszDescription, [in,out] use to return the description of the proper object.
455 * @return S_OK if successful and E_FAIL if failure.
456 */
get_accDescription(VARIANT varChild,BSTR * pszDescription)457 STDMETHODIMP CMAccessible::get_accDescription(VARIANT varChild, BSTR *pszDescription)
458 {
459
460 CHECK_ENABLE_INF
461 ENTER_PROTECTED_BLOCK
462 ISDESTROY()
463 // #CHECK#
464 if(pszDescription == NULL)
465 {
466 return E_INVALIDARG;
467 }
468 if(varChild.vt==VT_I4)
469 {
470 if(varChild.lVal==CHILDID_SELF)
471 {
472 SAFE_SYSFREESTRING(*pszDescription);
473 *pszDescription = SysAllocString(m_pszDescription);
474 return S_OK;
475 }
476
477 long lVal = varChild.lVal;
478 varChild.lVal = CHILDID_SELF;
479 IMAccessible *pChild = this->GetChildInterface(lVal);
480 if(!pChild)
481 return E_FAIL;
482 return pChild->get_accDescription(varChild,pszDescription);
483 }
484 return S_FALSE;
485
486 LEAVE_PROTECTED_BLOCK
487 }
488
489 /**
490 * Returns the accessible role of the current COM object self or its one child to AT.
491 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
492 * the child ID specify child index from 0 to children count, 0 stands for object self.
493 * @param pvarRole, [in,out] use to return the role of the proper object.
494 * @return S_OK if successful and S_FALSE if failure.
495 */
get_accRole(VARIANT varChild,VARIANT * pvarRole)496 STDMETHODIMP CMAccessible::get_accRole(VARIANT varChild, VARIANT *pvarRole)
497 {
498
499 CHECK_ENABLE_INF
500 ENTER_PROTECTED_BLOCK
501 ISDESTROY()
502 // #CHECK#
503 if(pvarRole == NULL)
504 {
505 return E_INVALIDARG;
506 }
507 if(varChild.vt == VT_I4)
508 {
509
510 if(varChild.lVal == CHILDID_SELF)
511 {
512 if( m_iRole < IA2_ROLE_CAPTION )
513 {
514 VariantInit(pvarRole);
515 pvarRole->vt = VT_I4;
516 pvarRole->lVal = m_iRole;
517 }
518 else
519 {
520 VariantInit(pvarRole);
521 pvarRole->vt = VT_I4;
522 pvarRole->lVal = ROLE_SYSTEM_CLIENT;
523 }
524 return S_OK;
525 }
526
527
528 long lVal = varChild.lVal;
529 varChild.lVal = CHILDID_SELF;
530 IMAccessible *pChild = this->GetChildInterface(lVal);
531 if(!pChild)
532 return E_FAIL;
533 return pChild->get_accRole(varChild,pvarRole);
534 }
535 return S_FALSE;
536
537 LEAVE_PROTECTED_BLOCK
538 }
539
540 /**
541 * Returns the accessible state of the current COM object self or its one child to AT.
542 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
543 * the child ID specify child index from 0 to children count, 0 stands for object self.
544 * @param pvarState, [in,out] use to return the state of the proper object.
545 * @return S_OK if successful and S_FALSE if failure.
546 */
get_accState(VARIANT varChild,VARIANT * pvarState)547 STDMETHODIMP CMAccessible::get_accState(VARIANT varChild, VARIANT *pvarState)
548 {
549
550 CHECK_ENABLE_INF
551 ENTER_PROTECTED_BLOCK
552 ISDESTROY()
553 // #CHECK#
554 if(pvarState == NULL)
555 {
556 return E_INVALIDARG;
557 }
558 if(varChild.vt==VT_I4)
559 {
560 if(varChild.lVal == CHILDID_SELF)
561 {
562 if(pUNOInterface)
563 {
564 Reference< XAccessibleContext > pContext = pUNOInterface->getAccessibleContext();
565 if(pContext.is())
566 {
567 // add the STATE_SYSTEM_LINKED state
568 Reference< XAccessibleHypertext > pRHypertext(pContext,UNO_QUERY);
569 if(pRHypertext.is())
570 {
571 if( pRHypertext->getHyperLinkCount() > 0 )
572 m_dState |= STATE_SYSTEM_LINKED;
573 else
574 m_dState &= ~STATE_SYSTEM_LINKED;
575 }
576 else
577 m_dState &= ~STATE_SYSTEM_LINKED;
578 }
579 }
580
581 VariantInit(pvarState);
582 pvarState->vt = VT_I4;
583 pvarState->lVal = m_dState;
584 return S_OK;
585 }
586
587 long lVal = varChild.lVal;
588 varChild.lVal = CHILDID_SELF;
589 IMAccessible *pChild = this->GetChildInterface(lVal);
590 if(!pChild)
591 return E_FAIL;
592 return pChild->get_accState(varChild,pvarState);
593 }
594 return S_FALSE;
595
596 LEAVE_PROTECTED_BLOCK
597 }
598
599 /**
600 * Returns the accessible helpString of the current COM object self or its one child to AT.
601 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
602 * the child ID specify child index from 0 to children count, 0 stands for object self.
603 * @param pszHelp, [in,out] use to return the helpString of the proper object.
604 * @return S_OK if successful and E_FAIL if failure.
605 */
get_accHelp(VARIANT,BSTR *)606 STDMETHODIMP CMAccessible::get_accHelp(VARIANT, BSTR *)
607 {
608 return E_NOTIMPL;
609 }
610
611 /**
612 * Returns the accessible HelpTopic of the current COM object self or its one child to AT.
613 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
614 * the child ID specify child index from 0 to children count, 0 stands for object self.
615 * @param pszHelpFile, [in,out] use to return the HelpTopic of the proper object.
616 * @param pidTopic, use to return the HelpTopic ID of the proper object.
617 * @return S_OK if successful and E_FAIL if failure.
618 * Not implemented yet
619 */
get_accHelpTopic(BSTR *,VARIANT,long *)620 STDMETHODIMP CMAccessible::get_accHelpTopic(BSTR *, VARIANT, long *)
621 {
622 return E_NOTIMPL;
623 }
624
GetMnemonicChar(const::rtl::OUString & aStr,WCHAR * wStr)625 static void GetMnemonicChar( const ::rtl::OUString& aStr, WCHAR* wStr)
626 {
627 int nLen = aStr.pData->length;
628 int i = 0;
629 WCHAR* text = aStr.pData->buffer;
630
631 while ( i < nLen )
632 {
633 if ( text[i] == L'~' )
634 if ( text[i+1] != L'~' )
635 {
636 wStr[0] = text[i+1];
637 break;
638 }
639 i++;
640 }
641 }
642
643 /**
644 * Returns the accessible keyboard shortcut of the current COM object self or its one child to AT.
645 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
646 * the child ID specify child index from 0 to children count, 0 stands for object self.
647 * @param pszKeyboardShortcut, [in,out] use to return the kbshortcut of the proper object.
648 * @return S_OK if successful and E_FAIL if failure.
649 */
get_accKeyboardShortcut(VARIANT varChild,BSTR * pszKeyboardShortcut)650 STDMETHODIMP CMAccessible::get_accKeyboardShortcut(VARIANT varChild, BSTR *pszKeyboardShortcut)
651 {
652
653 CHECK_ENABLE_INF
654 ENTER_PROTECTED_BLOCK
655
656 ISDESTROY()
657 // #CHECK#
658 if(pszKeyboardShortcut == NULL)
659 {
660 return E_INVALIDARG;
661 }
662
663 if(varChild.vt==VT_I4)
664 {
665 if(varChild.lVal == CHILDID_SELF)
666 {
667 if( pUNOInterface )
668 {
669 Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
670 if( !pRContext.is() )
671 return S_FALSE;
672
673 Reference<XAccessibleAction> pRXI(pRContext,UNO_QUERY);
674
675 OLECHAR wString[64]={0};
676
677 if( pRXI.is() && pRXI->getAccessibleActionCount() >= 1)
678 {
679 Reference< XAccessibleKeyBinding > binding = pRXI->getAccessibleActionKeyBinding(0);
680 if( binding.is() )
681 {
682 long nCount = binding->getAccessibleKeyBindingCount();
683 if(nCount >= 1)
684 {
685 CAccAction::GetkeyBindingStrByXkeyBinding( binding->getAccessibleKeyBinding(0),wString );
686 }
687 }
688 }
689 if(wString[0] == 0)
690 {
691 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
692 if(!pRrelationSet.is())
693 {
694 return S_FALSE;
695 }
696
697 long nRelCount = pRrelationSet->getRelationCount();
698
699 // Modified by Steve Yin, for SODC_1552
700 if( /*nRelCount <= 0 &&*/ m_iRole == ROLE_SYSTEM_TEXT )
701 {
702 VARIANT varParentRole;
703 VariantInit( &varParentRole );
704
705 m_pIParent->get_accRole(varChild, &varParentRole);
706
707 if( m_pIParent && varParentRole.lVal == ROLE_SYSTEM_COMBOBOX ) // edit in comoboBox
708 {
709 m_pIParent->get_accKeyboardShortcut(varChild, pszKeyboardShortcut);
710 return S_OK;
711 }
712 }
713
714 AccessibleRelation *paccRelation = NULL;
715 AccessibleRelation accRelation;
716 for(int i=0; i<nRelCount ; i++)
717 {
718 if( pRrelationSet->getRelation(i).RelationType == 6 )
719 {
720 accRelation = pRrelationSet->getRelation(i);
721 paccRelation = &accRelation;
722 }
723 }
724
725 if(paccRelation == NULL)
726 return S_FALSE;
727
728 Sequence< Reference< XInterface > > xTargets = paccRelation->TargetSet;
729 Reference<XInterface> pRAcc = xTargets[0];
730
731 XAccessible* pXAcc = (XAccessible*)pRAcc.get();
732
733 Reference<XAccessibleContext> pRLebelContext = pXAcc->getAccessibleContext();
734 if(!pRLebelContext.is())
735 return S_FALSE;
736
737 pRrelationSet = pRLebelContext->getAccessibleRelationSet();
738 nRelCount = pRrelationSet->getRelationCount();
739
740 paccRelation = NULL;
741 for(int j=0; j<nRelCount ; j++)
742 {
743 if( pRrelationSet->getRelation(j).RelationType == 5 )
744 {
745 accRelation = pRrelationSet->getRelation(j);
746 paccRelation = &accRelation;
747 }
748 }
749
750 if(paccRelation)
751 {
752 xTargets = paccRelation->TargetSet;
753 pRAcc = xTargets[0];
754 if(pUNOInterface != (XAccessible*)pRAcc.get())
755 return S_FALSE;
756 }
757
758 Reference<XAccessibleExtendedComponent> pRXIE(pRLebelContext,UNO_QUERY);
759 if(!pRXIE.is())
760 return S_FALSE;
761
762 ::rtl::OUString ouStr = pRXIE->getTitledBorderText();
763 WCHAR key[2] = {NULL};
764 GetMnemonicChar(ouStr, key);
765 if(key[0] != 0)
766 {
767 wcscat(wString, L"Alt+");
768 wcscat(wString, key);
769 }
770 else
771 return S_FALSE;
772 }
773
774 SAFE_SYSFREESTRING(*pszKeyboardShortcut);
775 *pszKeyboardShortcut = SysAllocString(wString);
776
777 return S_OK;
778 }
779 else
780 {
781 return S_FALSE;
782 }
783 }
784
785 long lVal = varChild.lVal;
786 varChild.lVal = CHILDID_SELF;
787 IMAccessible *pChild = this->GetChildInterface(lVal);
788 if(!pChild)
789 return E_FAIL;
790
791 return pChild->get_accKeyboardShortcut(varChild,pszKeyboardShortcut);
792 }
793 return S_FALSE;
794
795 LEAVE_PROTECTED_BLOCK
796 }
797
798 /**
799 * Returns the current focused child to AT.
800 * @param pvarChild, [in,out] vt member of pvarChild must be VT_I4,and lVal member stores the child ID,
801 * the child ID specify child index from 0 to children count, 0 stands for object self.
802 * @return S_OK if successful and E_FAIL if failure.
803 */
get_accFocus(VARIANT * pvarChild)804 STDMETHODIMP CMAccessible::get_accFocus(VARIANT *pvarChild)
805 {
806
807 CHECK_ENABLE_INF
808 ENTER_PROTECTED_BLOCK
809 ISDESTROY()
810 // #CHECK#
811 if(pvarChild == NULL)
812 {
813 return E_INVALIDARG;
814 }
815 if( m_dFocusChildID==UACC_NO_FOCUS )
816 {
817 pvarChild->vt = VT_EMPTY;//no focus on the object and its children
818 return S_OK;
819 }
820 //if the descendant of current object has focus indicated by m_dFocusChildID, return the IDispatch of this focused object
821 else
822 {
823 IMAccessible* pIMAcc = NULL;
824 g_pAgent->GetIAccessibleFromResID(m_dFocusChildID,&pIMAcc);
825 pIMAcc->AddRef();
826 pvarChild->vt = VT_DISPATCH;
827 pvarChild->pdispVal = pIMAcc;
828
829 }
830 return S_OK;
831
832 LEAVE_PROTECTED_BLOCK
833 }
834
835 /**
836 * Returns the selection of the current COM object to AT.
837 * @param pvarChildren,[in,out]
838 * if selection num is 0,return VT_EMPTY for vt,
839 * if selection num is 1,return VT_I4 for vt,and child index for lVal
840 * if selection num >1,return VT_UNKNOWN for vt, and IEnumVariant* for punkVal
841 * @return S_OK if successful and S_FALSE if failure.
842 */
get_accSelection(VARIANT * pvarChildren)843 STDMETHODIMP CMAccessible::get_accSelection(VARIANT *pvarChildren)
844 {
845
846 CHECK_ENABLE_INF
847 ENTER_PROTECTED_BLOCK
848 ISDESTROY()
849 // #CHECK#
850 if(pvarChildren == NULL)
851 {
852 return E_INVALIDARG;
853 }
854 switch(m_pEnumVar->GetCountOfElements())
855 {
856 case 0:
857 pvarChildren->vt = VT_EMPTY;
858 break;
859 case 1:
860 VARIANT varTmp[1];
861 ULONG count;
862 VariantInit(&varTmp[0]);
863 m_pEnumVar->Next(1,varTmp,&count);
864 if(count!=1)
865 return S_FALSE;
866 pvarChildren->vt = VT_I4;
867 pvarChildren->lVal = varTmp[0].lVal;
868 VariantClear(&varTmp[0]);
869 m_pEnumVar->Reset();
870 break;
871 default:
872 pvarChildren->vt = VT_UNKNOWN;
873 m_pEnumVar->AddRef();
874 pvarChildren->punkVal = m_pEnumVar;
875 break;
876 }
877 return S_OK;
878
879 LEAVE_PROTECTED_BLOCK
880 }
881
882 /**
883 * Returns the location of the current COM object self or its one child to AT.
884 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
885 * the child ID specify child index from 0 to children count, 0 stands for object self.
886 * @param pxLeft, [in,out] use to return the x-coordination of the proper object.
887 * @param pyTop, [in,out] use to return the y-coordination of the proper object.
888 * @param pcxWidth, [in,out] use to return the x-coordination width of the proper object.
889 * @param pcyHeight, [in,out] use to return the y-coordination height of the proper object.
890 * @return S_OK if successful and S_FALSE if failure.
891 */
accLocation(long * pxLeft,long * pyTop,long * pcxWidth,long * pcyHeight,VARIANT varChild)892 STDMETHODIMP CMAccessible::accLocation(long *pxLeft, long *pyTop, long *pcxWidth, long *pcyHeight, VARIANT varChild)
893 {
894
895 CHECK_ENABLE_INF
896 ENTER_PROTECTED_BLOCK
897 ISDESTROY()
898 // #CHECK#
899 if(pxLeft == NULL || pyTop == NULL || pcxWidth == NULL || pcyHeight == NULL)
900 {
901 return E_INVALIDARG;
902 }
903
904 if(varChild.vt==VT_I4)
905 {
906 if(varChild.lVal==CHILDID_SELF)
907 {
908
909 if(pUNOInterface)
910 {
911 Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
912 if( !pRContext.is() )
913 return S_FALSE;
914 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
915 if( !pRComponent.is() )
916 return S_FALSE;
917
918 ::com::sun::star::awt::Point pCPoint = pRComponent->getLocationOnScreen();
919 ::com::sun::star::awt::Size pCSize = pRComponent->getSize();
920 *pxLeft = pCPoint.X;
921 *pyTop = pCPoint.Y;
922 *pcxWidth = pCSize.Width;
923 *pcyHeight = pCSize.Height;
924 return S_OK;
925 }
926 else
927 {
928 *pxLeft = m_sLocation.m_dLeft;
929 *pyTop = m_sLocation.m_dTop;
930 *pcxWidth = m_sLocation.m_dWidth;
931 *pcyHeight = m_sLocation.m_dHeight;
932 return S_OK;
933 }
934 }
935
936 }
937 return S_FALSE;
938
939 LEAVE_PROTECTED_BLOCK
940 }
941
942 /**
943 * Returns the current focused child to AT.
944 * @param navDir, the direction flag of the navigation.
945 * @param varStart, the start child id of this navigation action.
946 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
947 * @return S_OK if successful and E_FAIL if failure.
948 */
accNavigate(long navDir,VARIANT varStart,VARIANT * pvarEndUpAt)949 STDMETHODIMP CMAccessible::accNavigate(long navDir, VARIANT varStart, VARIANT *pvarEndUpAt)
950 {
951
952 CHECK_ENABLE_INF
953 ENTER_PROTECTED_BLOCK
954 ISDESTROY()
955 // #CHECK#
956 if(pvarEndUpAt == NULL)
957 {
958 return E_INVALIDARG;
959 }
960 HRESULT ret = E_FAIL;
961 switch (navDir)
962 {
963 case NAVDIR_FIRSTCHILD:
964 ret = GetFirstChild(varStart,pvarEndUpAt);
965 break;
966 case NAVDIR_LASTCHILD:
967 ret = GetLastChild(varStart,pvarEndUpAt);
968 break;
969 case NAVDIR_NEXT:
970 ret = GetNextSibling(varStart,pvarEndUpAt);
971 break;
972 case NAVDIR_PREVIOUS:
973 ret = GetPreSibling(varStart,pvarEndUpAt);
974 break;
975 case NAVDIR_DOWN://do not implement temporarily
976 break;
977 case NAVDIR_UP://do not implement temporarily
978 break;
979 case NAVDIR_LEFT://do not implement temporarily
980 break;
981 case NAVDIR_RIGHT://do not implement temporarily
982 break;
983 default:
984 break;
985 };
986 return ret;
987
988 LEAVE_PROTECTED_BLOCK
989 }
990
accHitTest(long xLeft,long yTop,VARIANT * pvarChild)991 STDMETHODIMP CMAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarChild)
992 {
993
994 CHECK_ENABLE_INF
995 ENTER_PROTECTED_BLOCK
996 ISDESTROY()
997 // #CHECK#
998 if(pvarChild == NULL)
999 {
1000 return E_INVALIDARG;
1001 }
1002 long x, y, w, h;
1003 VARIANT varSelf;
1004 VariantInit(&varSelf);
1005 varSelf.vt = VT_I4;
1006 varSelf.lVal = CHILDID_SELF;
1007 accLocation(&x,&y,&w,&h,varSelf);
1008 if( (x < xLeft && (x + w) >xLeft) && (y < yTop && (y + h) >yTop) )
1009 {
1010 int i, nCount;
1011 pvarChild->vt = VT_EMPTY;
1012 Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1013 nCount = pRContext->getAccessibleChildCount();
1014 if(nCount > 256)
1015 return E_FAIL;
1016 IMAccessible* child = NULL;
1017 for( i = 0; i<nCount; i++)
1018 {
1019
1020 child = GetChildInterface(i + 1);
1021 if(child && child->accHitTest(xLeft,yTop,pvarChild) == S_OK)
1022 break;
1023 }
1024
1025 if(pvarChild->vt == VT_DISPATCH)
1026 return S_OK;
1027
1028 if( i < nCount)
1029 {
1030 pvarChild->vt = VT_DISPATCH;
1031 pvarChild->pdispVal = child;
1032 child->AddRef();
1033 }
1034 else
1035 {
1036 pvarChild->vt = VT_I4;
1037 pvarChild->lVal = CHILDID_SELF;
1038 }
1039 return S_OK;
1040 }
1041 return S_FALSE;
1042
1043 LEAVE_PROTECTED_BLOCK
1044 }
1045
1046 /**
1047 * Get The other Interface from CMAccessible.
1048 * @param guidService, must be IID_IAccessible here.
1049 * @param riid, the IID interface .
1050 * @return S_OK if successful and S_FALSE if failure.
1051 */
QueryService(REFGUID guidService,REFIID riid,void ** ppvObject)1052 STDMETHODIMP CMAccessible::QueryService(REFGUID guidService, REFIID riid, void** ppvObject)
1053 {
1054 if( InlineIsEqualGUID(guidService, IID_IAccessible) )
1055 return QueryInterface(riid, ppvObject);
1056 return S_FALSE;
1057 }
1058
1059 /**
1060 * Set the accessible name of the current COM object self or its one child from UNO.
1061 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1062 * the child ID specify child index from 0 to children count, 0 stands for object self.
1063 * @param szName, the name used to set the name of the proper object.
1064 * @return S_OK if successful and E_FAIL if failure.
1065 */
put_accName(VARIANT varChild,BSTR szName)1066 STDMETHODIMP CMAccessible::put_accName(VARIANT varChild, BSTR szName)
1067 {
1068
1069 ENTER_PROTECTED_BLOCK
1070 ISDESTROY()
1071 if(varChild.vt==VT_I4)
1072 {
1073 if(varChild.lVal==CHILDID_SELF)
1074 {
1075 SAFE_SYSFREESTRING(m_pszName);
1076 m_pszName=SysAllocString(szName);
1077 return S_OK;
1078 }
1079
1080 long lVal = varChild.lVal;
1081 varChild.lVal = CHILDID_SELF;
1082 IMAccessible *pChild = this->GetChildInterface(lVal);
1083 if(!pChild)
1084 return E_FAIL;
1085 return pChild->put_accName(varChild,szName);
1086 }
1087 return E_FAIL;
1088
1089 LEAVE_PROTECTED_BLOCK
1090 }
1091
1092 /**
1093 * Set the accessible value of the current COM object self or its one child from UNO.
1094 * @param varChild, vt member of varChild must be VT_I4,and lVal member stores the child ID,
1095 * the child ID specify child index from 0 to children count, 0 stands for object self.
1096 * @param szValue, the value used to set the value of the proper object.
1097 * @return S_OK if successful and E_FAIL if failure.
1098 */
put_accValue(VARIANT varChild,BSTR szValue)1099 STDMETHODIMP CMAccessible::put_accValue(VARIANT varChild, BSTR szValue)
1100 {
1101
1102 ENTER_PROTECTED_BLOCK
1103 ISDESTROY()
1104 if(varChild.vt==VT_I4)
1105 {
1106 if(varChild.lVal==CHILDID_SELF)
1107 {
1108 SysAllocString(m_pszValue);
1109 m_pszValue=SysAllocString(szValue);
1110 return S_OK;
1111 }
1112
1113 long lVal = varChild.lVal;
1114 varChild.lVal = CHILDID_SELF;
1115 IMAccessible *pChild = this->GetChildInterface(lVal);
1116 if(!pChild)
1117 return E_FAIL;
1118 return pChild->put_accValue(varChild,szValue);
1119 }
1120 return E_FAIL;
1121
1122 LEAVE_PROTECTED_BLOCK
1123 }
1124
1125 /**
1126 * Set the accessible name of the current COM object self from UNO.
1127 * @param pszName, the name value used to set the name of the current object.
1128 * @return S_OK if successful and E_FAIL if failure.
1129 */
Put_XAccName(const OLECHAR __RPC_FAR * pszName)1130 STDMETHODIMP CMAccessible::Put_XAccName(const OLECHAR __RPC_FAR *pszName)
1131 {
1132
1133 ENTER_PROTECTED_BLOCK
1134 ISDESTROY()
1135 // #CHECK#
1136 if(pszName == NULL)
1137 {
1138 return E_INVALIDARG;
1139 }
1140
1141 SAFE_SYSFREESTRING(m_pszName);//??
1142 m_pszName = SysAllocString(pszName);
1143 if(m_pszName==NULL)
1144 return E_FAIL;
1145 return S_OK;
1146
1147 LEAVE_PROTECTED_BLOCK
1148 }
1149
1150 /**
1151 * Set the accessible role of the current COM object self from UNO.
1152 * @param pRole, the role value used to set the role of the current object.
1153 * @return S_OK if successful and E_FAIL if failure.
1154 */
Put_XAccRole(unsigned short pRole)1155 STDMETHODIMP CMAccessible::Put_XAccRole(unsigned short pRole)
1156 {
1157 m_iRole = pRole;
1158 return S_OK;
1159 }
1160
1161 /**
1162 * Add one state into the current state set for the current COM object from UNO.
1163 * @param pXSate, the state used to set the name of the current object.
1164 * @return S_OK if successful and E_FAIL if failure.
1165 */
DecreaseState(DWORD pXSate)1166 STDMETHODIMP CMAccessible::DecreaseState(DWORD pXSate)
1167 {
1168 m_dState &= (~pXSate);
1169 return S_OK;
1170 }
1171
1172 /**
1173 * Delete one state into the current state set for the current COM object from UNO.
1174 * @param pXSate, the state used to set the name of the current object.
1175 * @return S_OK if successful and E_FAIL if failure.
1176 */
IncreaseState(DWORD pXSate)1177 STDMETHODIMP CMAccessible::IncreaseState(DWORD pXSate)
1178 {
1179 m_dState |= pXSate;
1180 return S_OK;
1181 }
1182
1183 /**
1184 * Set state into the current state set for the current COM object from UNO.
1185 * @param pXSate, the state used to set the name of the current object.
1186 * @return S_OK if successful and E_FAIL if failure.
1187 */
SetState(DWORD pXSate)1188 STDMETHODIMP CMAccessible::SetState(DWORD pXSate)
1189 {
1190 m_dState = pXSate;
1191 return S_OK;
1192 }
1193
1194
1195
1196 /**
1197 * Set the accessible description of the current COM object self from UNO.
1198 * @param pszDescription, the name used to set the description of the current object.
1199 * @return S_OK if successful and E_FAIL if failure.
1200 */
Put_XAccDescription(const OLECHAR __RPC_FAR * pszDescription)1201 STDMETHODIMP CMAccessible::Put_XAccDescription(const OLECHAR __RPC_FAR *pszDescription)
1202 {
1203
1204 ENTER_PROTECTED_BLOCK
1205 ISDESTROY()
1206 // #CHECK#
1207 if(pszDescription == NULL)
1208 {
1209 return E_INVALIDARG;
1210 }
1211
1212 SAFE_SYSFREESTRING(m_pszDescription);
1213 m_pszDescription = SysAllocString(pszDescription);
1214
1215 if(m_pszDescription==NULL)
1216 return E_FAIL;
1217 return S_OK;
1218
1219 LEAVE_PROTECTED_BLOCK
1220 }
1221
1222 /**
1223 * Set the accessible value of the current COM object self from UNO.
1224 * @param pszAccValue, the name used to set the value of the current object.
1225 * @return S_OK if successful and E_FAIL if failure.
1226 */
Put_XAccValue(const OLECHAR __RPC_FAR * pszAccValue)1227 STDMETHODIMP CMAccessible::Put_XAccValue(const OLECHAR __RPC_FAR *pszAccValue)
1228 {
1229
1230 ENTER_PROTECTED_BLOCK
1231 ISDESTROY()
1232 // #CHECK#
1233 if(pszAccValue == NULL)
1234 {
1235 return E_INVALIDARG;
1236 }
1237 SAFE_SYSFREESTRING(m_pszValue);
1238 m_pszValue = SysAllocString(pszAccValue);
1239 if(m_pszValue==NULL)
1240 return E_FAIL;
1241 return S_OK;
1242
1243 LEAVE_PROTECTED_BLOCK
1244 }
1245
1246 /**
1247 * Set the HWND value of the current COM object self from UNO. It should set the parent IAccessible
1248 * Object through the method AccessibleObjectFromWindow(...).
1249 * @param hwnd, the HWND used to set the value of the current object.
1250 * @return S_OK if successful and E_FAIL if failure.
1251 */
Put_XAccWindowHandle(HWND hwnd)1252 STDMETHODIMP CMAccessible::Put_XAccWindowHandle(HWND hwnd)
1253 {
1254
1255 ENTER_PROTECTED_BLOCK
1256 ISDESTROY()
1257 m_hwnd = hwnd;
1258 return S_OK;
1259
1260 LEAVE_PROTECTED_BLOCK
1261 }
1262
1263 /**
1264 * Set accessible focus by specifying child ID
1265 * @param dChildID, the child id identifies the focus child.
1266 * @return S_OK if successful and E_FAIL if failure.
1267 */
Put_XAccFocus(long dChildID)1268 STDMETHODIMP CMAccessible::Put_XAccFocus(long dChildID)
1269 {
1270
1271 ENTER_PROTECTED_BLOCK
1272 ISDESTROY()
1273
1274 if(dChildID==CHILDID_SELF)
1275 {
1276 if(m_pIParent)
1277 {
1278 m_pIParent->Put_XAccFocus(m_dChildID);
1279 }
1280 }
1281 else
1282 {
1283 m_dFocusChildID = dChildID;
1284 //traverse all ancestors to set the focused child ID so that when the get_accFocus is called on
1285 //any of the ancestors, this id can be used to get the IAccessible of focused object.
1286 if(m_pIParent)
1287 {
1288 m_pIParent->Put_XAccFocus(dChildID);
1289 }
1290 }
1291 return S_OK;
1292
1293 LEAVE_PROTECTED_BLOCK
1294 }
1295
1296 /**
1297 *Set accessible object location for the current COM object
1298 * @param sLocation, the location of the current object.
1299 * @return S_OK if successful and E_FAIL if failure.
1300 */
Put_XAccLocation(const Location sLocation)1301 STDMETHODIMP CMAccessible::Put_XAccLocation(const Location sLocation)
1302 {
1303
1304 this->m_sLocation = sLocation;
1305 return S_OK;
1306 }
1307
1308 /**
1309 * Set accessible parent object for the current COM object if
1310 * the current object is a child of some COM object
1311 * @param pIParent, the parent of the current object.
1312 * @return S_OK if successful and E_FAIL if failure.
1313 */
Put_XAccParent(IMAccessible __RPC_FAR * pIParent)1314 STDMETHODIMP CMAccessible::Put_XAccParent(IMAccessible __RPC_FAR *pIParent)
1315 {
1316 this->m_pIParent = pIParent;
1317
1318 if(pIParent)
1319 m_pIParent->AddRef();
1320
1321 return S_OK;
1322 }
1323
1324 /**
1325 * Set unique child id to COM
1326 * @param dChildID, the id of the current object.
1327 * @return S_OK if successful and E_FAIL if failure.
1328 */
Put_XAccChildID(long dChildID)1329 STDMETHODIMP CMAccessible::Put_XAccChildID(long dChildID)
1330 {
1331
1332 this->m_dChildID = dChildID;
1333 return S_OK;
1334 }
1335
1336 /**
1337 * Set AccObjectManagerAgent object pointer to COM
1338 * @param pAgent, the AccObjectManagerAgent point.
1339 * @return S_OK if successful and E_FAIL if failure.
1340 */
Put_XAccAgent(long pAgent)1341 STDMETHODIMP CMAccessible::Put_XAccAgent(long pAgent)
1342 {
1343 g_pAgent = (AccObjectManagerAgent*)pAgent;
1344 return S_OK;
1345 }
1346
1347 /**
1348 * When a UNO control disposing, it disposes its listeners,
1349 * then notify AccObject in bridge management, then notify
1350 * COM that the XAccessible is invalid,so set pUNOInterface as NULL
1351 * @param isDestroy, true is it need to be destroyed.
1352 * @return S_OK if successful and E_FAIL if failure.
1353 */
NotifyDestroy(BOOL isDestroy)1354 STDMETHODIMP CMAccessible::NotifyDestroy(BOOL isDestroy)
1355 {
1356
1357 m_isDestroy = isDestroy;
1358 pUNOInterface = NULL;
1359 return S_OK;
1360 }
1361
1362 /**
1363 *private methods that help implement public functions
1364 */
1365
1366 /**
1367 * Return child interface pointer by child ID,note: need to call AddRef()
1368 * @param lChildID, specify child index,which AT(such as Inspect32) gives.
1369 * @return IMAccessible*, pointer to the corresponding child object.
1370 */
GetChildInterface(long dChildID)1371 IMAccessible* CMAccessible::GetChildInterface(long dChildID)//for test
1372 {
1373
1374 long dChildIndex = 0;
1375 if(dChildID<0)
1376 {
1377 if(g_pAgent)
1378 {
1379 IMAccessible* pIMAcc = NULL;
1380 g_pAgent->GetIAccessibleFromResID(dChildID,&pIMAcc);
1381 return pIMAcc;
1382 }
1383 return NULL;
1384 }
1385 else
1386 {
1387 Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
1388 if( !pRContext.is() )
1389 return NULL;
1390
1391 if(dChildID<1 || dChildID>pRContext->getAccessibleChildCount())
1392 return NULL;
1393
1394 IAccessible* pChild = NULL;
1395 Reference< XAccessible > pXChild = pRContext->getAccessibleChild(dChildID-1);
1396 BOOL isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
1397
1398 if(!isGet)
1399 {
1400 g_pAgent->InsertAccObj(pXChild.get(),pUNOInterface,(long)m_hwnd);
1401 isGet = get_IAccessibleFromXAccessible((long)pXChild.get(),&pChild);
1402 }
1403
1404 if(isGet)
1405 {
1406 IMAccessible* pIMAcc = (IMAccessible*)pChild;
1407 return pIMAcc;
1408 }
1409 }
1410
1411 return NULL;
1412 }
1413
1414 /**
1415 * For List, tree and table,these roles belong to manage_decendant in UNO,
1416 * need to process specifically when navigate
1417 * @return BOOL, if it is decendantmanager, return true.
1418 */
IsDecendantManage()1419 BOOL CMAccessible::IsDecendantManage()
1420 {
1421
1422 return (m_iRole==ROLE_SYSTEM_LIST)||(m_iRole==ROLE_SYSTEM_OUTLINE)||(m_iRole==ROLE_SYSTEM_TABLE);
1423 }
1424
1425 /**
1426 * for decendantmanager circumstance,provide child interface when navigate
1427 * @param varCur, the current child.
1428 * @param flags, the navigation direction.
1429 * @return IMAccessible*, the child of the end up node.
1430 */
GetNavigateChildForDM(VARIANT varCur,short flags)1431 IMAccessible* CMAccessible::GetNavigateChildForDM(VARIANT varCur, short flags)
1432 {
1433
1434 XAccessibleContext* pXContext = GetContextByXAcc(pUNOInterface);
1435 if(pXContext==NULL)
1436 {
1437 return NULL;
1438 }
1439
1440 int count = pXContext->getAccessibleChildCount();
1441 if(count<1)
1442 {
1443 return NULL;
1444 }
1445
1446 IMAccessible* pCurChild = NULL;
1447 XAccessible* pChildXAcc = NULL;
1448 Reference<XAccessible> pRChildXAcc;
1449 XAccessibleContext* pChildContext = NULL;
1450 int index = 0,delta=0;
1451 switch(flags)
1452 {
1453 case DM_FIRSTCHILD:
1454 pRChildXAcc = pXContext->getAccessibleChild(0);
1455 break;
1456 case DM_LASTCHILD:
1457 pRChildXAcc = pXContext->getAccessibleChild(count-1);
1458 break;
1459 case DM_NEXTCHILD:
1460 case DM_PREVCHILD:
1461 pCurChild = GetChildInterface(varCur.lVal);
1462 if(pCurChild==NULL)
1463 {
1464 return NULL;
1465 }
1466 pCurChild->GetUNOInterface((long*)&pChildXAcc);
1467 if(pChildXAcc==NULL)
1468 {
1469 return NULL;
1470 }
1471 pChildContext = GetContextByXAcc(pChildXAcc);
1472 if(pChildContext == NULL)
1473 {
1474 return NULL;
1475 }
1476 delta = (flags==DM_NEXTCHILD)?1:-1;
1477 //currently, getAccessibleIndexInParent is error in UNO for
1478 //some kind of List,such as ValueSet, the index will be less 1 than
1479 //what should be, need to fix UNO code
1480 index = pChildContext->getAccessibleIndexInParent()+delta;
1481 if((index>=0)&&(index<=count-1))
1482 {
1483 pRChildXAcc = pXContext->getAccessibleChild(index);
1484 }
1485 break;
1486 default:
1487 break;
1488 }
1489
1490 if(!pRChildXAcc.is())
1491 {
1492 return NULL;
1493 }
1494 pChildXAcc = pRChildXAcc.get();
1495 g_pAgent->InsertAccObj(pChildXAcc,pUNOInterface);
1496 return g_pAgent->GetIMAccByXAcc(pChildXAcc);
1497 }
1498
1499 /**
1500 *the following 4 private methods are for accNavigate implementation
1501 */
1502
1503 /**
1504 * Return first child for parent container, process differently according
1505 * to whether it is decendant manage
1506 * @param varStart, the start child id of this navigation action.
1507 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1508 * @return S_OK if successful and E_FAIL if failure.
1509 */
GetFirstChild(VARIANT varStart,VARIANT * pvarEndUpAt)1510 HRESULT CMAccessible::GetFirstChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1511 {
1512
1513 ENTER_PROTECTED_BLOCK
1514 ISDESTROY()
1515 // #CHECK#
1516 if(pvarEndUpAt == NULL)
1517 {
1518 return E_INVALIDARG;
1519 }
1520 if(varStart.vt != VT_I4)
1521 {
1522 pvarEndUpAt->vt = VT_EMPTY;
1523 return E_INVALIDARG;
1524 }
1525
1526 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_FIRSTCHILD);
1527 if(pvarEndUpAt->pdispVal)
1528 {
1529 pvarEndUpAt->pdispVal->AddRef();
1530 pvarEndUpAt->vt = VT_DISPATCH;
1531 return S_OK;
1532 }
1533
1534 pvarEndUpAt->vt = VT_EMPTY;
1535 return E_FAIL;
1536
1537 LEAVE_PROTECTED_BLOCK
1538 }
1539
1540 /**
1541 * Return last child for parent container, process differently according
1542 * to whether it is decendant manage
1543 * @param varStart, the start child id of this navigation action.
1544 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1545 * @return S_OK if successful and E_FAIL if failure.
1546 */
GetLastChild(VARIANT varStart,VARIANT * pvarEndUpAt)1547 HRESULT CMAccessible::GetLastChild(VARIANT varStart,VARIANT* pvarEndUpAt)
1548 {
1549
1550 ENTER_PROTECTED_BLOCK
1551 ISDESTROY()
1552 // #CHECK#
1553 if(pvarEndUpAt == NULL)
1554 {
1555 return E_INVALIDARG;
1556 }
1557 if(varStart.vt != VT_I4)
1558 {
1559 pvarEndUpAt->vt = VT_EMPTY;
1560 return E_INVALIDARG;
1561 }
1562
1563 pvarEndUpAt->pdispVal = GetNavigateChildForDM(varStart, DM_LASTCHILD);
1564 if(pvarEndUpAt->pdispVal)
1565 {
1566 pvarEndUpAt->pdispVal->AddRef();
1567 pvarEndUpAt->vt = VT_DISPATCH;
1568 return S_OK;
1569 }
1570 pvarEndUpAt->vt = VT_EMPTY;
1571 return E_FAIL;
1572
1573 LEAVE_PROTECTED_BLOCK
1574 }
1575
1576 /**
1577 * The method GetNextSibling is general, whatever it is decendant manage or not
1578 * Get the next sibling object.
1579 * @param varStart, the start child id of this navigation action.
1580 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1581 * @return S_OK if successful and E_FAIL if failure.
1582 */
GetNextSibling(VARIANT varStart,VARIANT * pvarEndUpAt)1583 HRESULT CMAccessible::GetNextSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1584 {
1585
1586 ENTER_PROTECTED_BLOCK
1587 ISDESTROY()
1588 if(varStart.vt != VT_I4)
1589 {
1590 pvarEndUpAt->vt = VT_EMPTY;
1591 return E_INVALIDARG;
1592 }
1593
1594 Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1595 if(pRContext.is())
1596 {
1597 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent() + 2);
1598 if(m_pIParent)
1599 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1600 {
1601 pvarEndUpAt->vt = VT_DISPATCH;
1602 return S_OK;
1603 }
1604 }
1605 pvarEndUpAt->vt = VT_EMPTY;
1606 return E_FAIL;
1607
1608 LEAVE_PROTECTED_BLOCK
1609 }
1610
1611 /**
1612 *the method GetPreSibling is general, whatever it is decendant manage or not
1613 * @param varStart, the start child id of this navigation action.
1614 * @param pvarEndUpAt, [in,out] the end up child of this navigation action.
1615 * @return S_OK if successful and E_FAIL if failure.
1616 */
GetPreSibling(VARIANT varStart,VARIANT * pvarEndUpAt)1617 HRESULT CMAccessible::GetPreSibling(VARIANT varStart,VARIANT* pvarEndUpAt)
1618 {
1619
1620 ENTER_PROTECTED_BLOCK
1621 ISDESTROY()
1622 // #CHECK#
1623 if(pvarEndUpAt == NULL)
1624 {
1625 return E_INVALIDARG;
1626 }
1627 if(varStart.vt != VT_I4)
1628 {
1629 pvarEndUpAt->vt = VT_EMPTY;
1630 return E_INVALIDARG;
1631 }
1632
1633 Reference< XAccessibleContext > pRContext = GetContextByXAcc(pUNOInterface);
1634 if(pRContext.is())
1635 {
1636 varStart.iVal = sal_Int16(pRContext->getAccessibleIndexInParent());
1637 if(m_pIParent && varStart.iVal > 0)
1638 if( m_pIParent->get_accChild(varStart,&pvarEndUpAt->pdispVal) == S_OK)
1639 {
1640 pvarEndUpAt->vt = VT_DISPATCH;
1641 return S_OK;
1642 }
1643 }
1644 pvarEndUpAt->vt = VT_EMPTY;
1645 return E_FAIL;
1646
1647 LEAVE_PROTECTED_BLOCK
1648 }
1649
1650 /**
1651 * For IAccessible2 implementation methods
1652 */
get_nRelations(long __RPC_FAR * nRelations)1653 STDMETHODIMP CMAccessible::get_nRelations( long __RPC_FAR *nRelations)
1654 {
1655
1656 CHECK_ENABLE_INF
1657 ENTER_PROTECTED_BLOCK
1658 ISDESTROY()
1659
1660 // #CHECK#
1661 if(nRelations == NULL)
1662 {
1663 return E_INVALIDARG;
1664 }
1665
1666 *nRelations = 0;
1667
1668 if( !pRContext.is() )
1669 return E_FAIL;
1670 Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1671 if(!pRrelationSet.is())
1672 {
1673 *nRelations = 0;
1674 return S_OK;
1675 }
1676
1677 *nRelations = pRrelationSet->getRelationCount();
1678 return S_OK;
1679
1680 LEAVE_PROTECTED_BLOCK
1681 }
1682
get_relation(long relationIndex,IAccessibleRelation __RPC_FAR * __RPC_FAR * relation)1683 STDMETHODIMP CMAccessible::get_relation( long relationIndex, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation)
1684 {
1685
1686 CHECK_ENABLE_INF
1687 ENTER_PROTECTED_BLOCK
1688 ISDESTROY()
1689 // #CHECK#
1690 if(relation == NULL)
1691 {
1692 return E_INVALIDARG;
1693 }
1694
1695 if( !pRContext.is() )
1696 return E_FAIL;
1697
1698
1699 long nMax = 0;
1700 long nReal = 0;
1701 get_nRelations(&nMax);
1702
1703 *relation = (IAccessibleRelation*)::CoTaskMemAlloc(sizeof(IAccessibleRelation));
1704
1705 // #CHECK Memory Allocation#
1706 if(*relation == NULL)
1707 {
1708 return E_FAIL;
1709 }
1710
1711 if( relationIndex < nMax )
1712 {
1713
1714
1715 Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1716 if(!pRrelationSet.is())
1717 {
1718
1719 return E_FAIL;
1720 }
1721
1722 IAccessibleRelation* pRelation = NULL;
1723 ActivateActContext();
1724 HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
1725 IID_IAccessibleRelation,
1726 (void **)&pRelation);
1727 DeactivateActContext();
1728 if(SUCCEEDED(hr))
1729 {
1730 IUNOXWrapper* wrapper = NULL;
1731 hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1732 if(SUCCEEDED(hr))
1733 {
1734 AccessibleRelation accRelation = pRrelationSet->getRelation(relationIndex);
1735 wrapper->put_XSubInterface((long)&accRelation);
1736 wrapper->Release();
1737 *relation = pRelation;
1738 return S_OK;
1739 }
1740
1741 }
1742 }
1743
1744 return E_FAIL;
1745
1746 LEAVE_PROTECTED_BLOCK
1747 }
1748
get_relations(long,IAccessibleRelation __RPC_FAR * __RPC_FAR * relation,long __RPC_FAR * nRelations)1749 STDMETHODIMP CMAccessible::get_relations( long, IAccessibleRelation __RPC_FAR *__RPC_FAR *relation, long __RPC_FAR *nRelations)
1750 {
1751
1752 CHECK_ENABLE_INF
1753 ENTER_PROTECTED_BLOCK
1754 ISDESTROY()
1755
1756 // #CHECK#
1757 if(relation == NULL || nRelations == NULL)
1758 {
1759 return E_INVALIDARG;
1760 }
1761 // #CHECK XInterface#
1762
1763 if( !pRContext.is() )
1764 return E_FAIL;
1765
1766 Reference<XAccessibleRelationSet> pRrelationSet = pRContext.get()->getAccessibleRelationSet();
1767 if(!pRrelationSet.is())
1768 {
1769 *nRelations = 0;
1770 return S_OK;
1771 }
1772
1773 long nCount = pRrelationSet->getRelationCount();
1774
1775 *relation = (IAccessibleRelation*)::CoTaskMemAlloc(nCount*sizeof(IAccessibleRelation));
1776
1777 // #CHECK Memory Allocation#
1778 if(*relation == NULL)
1779 {
1780 return E_FAIL;
1781 }
1782
1783 for(int i=0; i<nCount ; i++)
1784 {
1785 IAccessibleRelation* pRelation = NULL;
1786 ActivateActContext();
1787 HRESULT hr = CoCreateInstance( CLSID_AccRelation, NULL, CLSCTX_SERVER ,
1788 IID_IAccessibleRelation,
1789 (void **)&pRelation);
1790 DeactivateActContext();
1791 if(SUCCEEDED(hr))
1792 {
1793 IUNOXWrapper* wrapper = NULL;
1794 hr = pRelation->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
1795 if(SUCCEEDED(hr))
1796 {
1797 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1798 wrapper->put_XSubInterface((long)&accRelation);
1799 wrapper->Release();
1800 }
1801 (relation)[i] = pRelation;
1802 }
1803 }
1804
1805 *nRelations = nCount;
1806 return S_OK;
1807
1808 LEAVE_PROTECTED_BLOCK
1809 }
1810
role(long __RPC_FAR * role)1811 STDMETHODIMP CMAccessible::role(long __RPC_FAR *role)
1812 {
1813 ENTER_PROTECTED_BLOCK
1814
1815 (*role) = m_iRole;
1816
1817 return S_OK;
1818
1819 LEAVE_PROTECTED_BLOCK
1820 }
1821
1822
get_nActions(long __RPC_FAR * nActions)1823 STDMETHODIMP CMAccessible:: get_nActions(long __RPC_FAR *nActions)
1824 {
1825
1826 try
1827 {
1828 ISDESTROY()
1829 // #CHECK#
1830 if(nActions == NULL)
1831 {
1832 return E_INVALIDARG;
1833 }
1834 *nActions = 0L;
1835 IAccessibleAction* pAcc = NULL;
1836 HRESULT hr = QueryInterface(IID_IAccessibleAction, (void**)&pAcc);
1837 if( hr == S_OK )
1838 {
1839 pAcc->nActions(nActions);
1840 pAcc->Release();
1841 }
1842
1843 return S_OK;
1844 }
1845 catch(...)
1846 {
1847 *nActions = 0L;
1848 return S_OK;
1849 }
1850 }
1851
1852
scrollToPoint(enum IA2CoordinateType,long,long)1853 STDMETHODIMP CMAccessible:: scrollToPoint(enum IA2CoordinateType, long, long)
1854 {
1855
1856 ENTER_PROTECTED_BLOCK
1857 ISDESTROY()
1858 return E_NOTIMPL;
1859 LEAVE_PROTECTED_BLOCK
1860
1861 }
scrollTo(enum IA2ScrollType)1862 STDMETHODIMP CMAccessible:: scrollTo(enum IA2ScrollType)
1863 {
1864
1865 ENTER_PROTECTED_BLOCK
1866 ISDESTROY()
1867
1868 return E_NOTIMPL;
1869
1870 LEAVE_PROTECTED_BLOCK
1871 }
1872
getTheParentOfMember(XAccessible * pXAcc)1873 static XAccessible* getTheParentOfMember(XAccessible* pXAcc)
1874 {
1875 // #CHECK#
1876 if(pXAcc == NULL)
1877 {
1878 return NULL;
1879 }
1880 Reference<XAccessibleContext> pRContext = pXAcc->getAccessibleContext();
1881 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1882 long nRelations = pRrelationSet->getRelationCount();
1883 for(int i=0 ; i<nRelations ; i++)
1884 {
1885 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1886 if(accRelation.RelationType == 7)
1887 {
1888 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1889 return (XAccessible*)xTargets[0].get();
1890 }
1891 }
1892 return NULL;
1893 }
1894
get_groupPosition(long __RPC_FAR * groupLevel,long __RPC_FAR * similarItemsInGroup,long __RPC_FAR * positionInGroup)1895 STDMETHODIMP CMAccessible:: get_groupPosition(long __RPC_FAR *groupLevel,long __RPC_FAR *similarItemsInGroup,long __RPC_FAR *positionInGroup)
1896 {
1897
1898 CHECK_ENABLE_INF
1899 ENTER_PROTECTED_BLOCK
1900 ISDESTROY()
1901 // #CHECK#
1902 if(groupLevel == NULL || similarItemsInGroup == NULL || positionInGroup == NULL)
1903 {
1904 return E_INVALIDARG;
1905 }
1906
1907 Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
1908 if(!pRContext.is())
1909 return E_FAIL;
1910 long Role = pRContext->getAccessibleRole();
1911
1912 *groupLevel = 0;
1913 *similarItemsInGroup = 0;
1914 *positionInGroup = 0;
1915
1916 if (Role != AccessibleRole::DOCUMENT)
1917 {
1918 Reference< XAccessibleGroupPosition > xGroupPosition( pRContext, UNO_QUERY );
1919 if ( xGroupPosition.is() )
1920 {
1921 Sequence< sal_Int32 > rSeq = xGroupPosition->getGroupPosition( makeAny( pRContext ) );
1922 sal_Int32* pSeq = rSeq.getArray();
1923 if ( pSeq )
1924 {
1925 *groupLevel = pSeq[0];
1926 *similarItemsInGroup = pSeq[1];
1927 *positionInGroup = pSeq[2];
1928 return S_OK;
1929 }
1930 return S_OK;
1931 }
1932 }
1933
1934 Reference< XAccessible> pParentAcc = pRContext->getAccessibleParent();
1935 if( !pParentAcc.is() )
1936 {
1937 return S_OK;
1938 }
1939
1940 Reference<XAccessibleContext> pRParentContext = pParentAcc->getAccessibleContext();
1941
1942 int level = 0;
1943 int index = 0;
1944 int number = 0;
1945
1946 if( Role == RADIO_BUTTON )
1947 {
1948 Reference<XAccessibleRelationSet> pRrelationSet = pRContext->getAccessibleRelationSet();
1949 long nRel = pRrelationSet->getRelationCount();
1950 for(int i=0 ; i<nRel ; i++)
1951 {
1952 AccessibleRelation accRelation = pRrelationSet->getRelation(i);
1953 if(accRelation.RelationType == 7)
1954 {
1955 Sequence< Reference< XInterface > > xTargets = accRelation.TargetSet;
1956 int nCount = xTargets.getLength();
1957
1958 Reference<XInterface> pRAcc = xTargets[0];
1959 for(int j=0; j<pRParentContext->getAccessibleChildCount(); j++)
1960 {
1961 if( getTheParentOfMember(pRParentContext->getAccessibleChild(j).get())
1962 == (XAccessible*)pRAcc.get() &&
1963 pRParentContext->getAccessibleChild(j)->getAccessibleContext()->getAccessibleRole() == RADIO_BUTTON)
1964 number++;
1965 if(pRParentContext->getAccessibleChild(j).get() == pUNOInterface)
1966 index = number;
1967 }
1968 }
1969 }
1970 *groupLevel = 1;
1971 *similarItemsInGroup = number;
1972 *positionInGroup = index;
1973 return S_OK;
1974 }
1975
1976 else if ( COMBO_BOX == Role )
1977 {
1978 *groupLevel = 1;
1979 *similarItemsInGroup = 0;
1980 *positionInGroup = -1;
1981
1982 long nCount = pRContext->getAccessibleChildCount();
1983 if( 2 != nCount)
1984 {
1985 return S_OK;
1986 }
1987 Reference<XAccessible> xList=pRContext->getAccessibleChild(1);
1988 if (!xList.is())
1989 {
1990 return S_OK;
1991 }
1992 Reference<XAccessibleContext> xListContext(xList,UNO_QUERY);
1993 if (!xListContext.is())
1994 {
1995 return S_OK;
1996 }
1997 Reference<XAccessibleSelection> xListSel(xList,UNO_QUERY);
1998 if (!xListSel.is())
1999 {
2000 return S_OK;
2001 }
2002 *similarItemsInGroup = xListContext->getAccessibleChildCount();
2003 if (*similarItemsInGroup > 0 )
2004 {
2005 try
2006 {
2007 Reference<XAccessible> xChild = xListSel->getSelectedAccessibleChild(0);
2008 if (xChild.is())
2009 {
2010 Reference<XAccessibleContext> xChildContext(xChild,UNO_QUERY);
2011 if (xChildContext.is())
2012 {
2013 *positionInGroup=xChildContext->getAccessibleIndexInParent() + 1 ;
2014 return S_OK;
2015 }
2016 }
2017 }
2018 catch(...)
2019 {}
2020 }
2021 return S_OK;
2022 }
2023 else if ( PAGE_TAB == Role )
2024 {
2025 *groupLevel = 1;
2026 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2027
2028 if (*similarItemsInGroup > 0 )
2029 {
2030 *positionInGroup=pRContext->getAccessibleIndexInParent() + 1 ;
2031 }
2032 else
2033 {
2034 *positionInGroup = -1;
2035 }
2036 return S_OK;
2037 }
2038
2039
2040 BOOL isFound = FALSE;
2041 while( pParentAcc.is() && !isFound)
2042 {
2043 level++;
2044 pRParentContext = pParentAcc->getAccessibleContext();
2045 Role = pRParentContext->getAccessibleRole();
2046 if( (Role == TREE) || (Role == LIST) )
2047 isFound = TRUE;
2048 pParentAcc = pRParentContext->getAccessibleParent();
2049 }
2050
2051 if( isFound )
2052 {
2053 Reference< XAccessible> pTempAcc = pRContext->getAccessibleParent();
2054 pRParentContext = pTempAcc->getAccessibleContext();
2055 *groupLevel = level;
2056 *similarItemsInGroup = pRParentContext->getAccessibleChildCount();
2057 *positionInGroup = pRContext->getAccessibleIndexInParent() + 1;
2058 }
2059 else
2060 {
2061 *groupLevel = 0;
2062 *similarItemsInGroup = 0;
2063 *positionInGroup = 0;
2064 }
2065 return S_OK;
2066
2067 LEAVE_PROTECTED_BLOCK
2068 }
2069
get_extendedStates(long,BSTR __RPC_FAR * __RPC_FAR *,long __RPC_FAR *)2070 STDMETHODIMP CMAccessible:: get_extendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
2071 {
2072
2073 CHECK_ENABLE_INF
2074 ENTER_PROTECTED_BLOCK
2075 ISDESTROY()
2076
2077 return E_NOTIMPL;
2078
2079 LEAVE_PROTECTED_BLOCK
2080 }
2081
2082
get_uniqueID(long __RPC_FAR * uniqueID)2083 STDMETHODIMP CMAccessible:: get_uniqueID(long __RPC_FAR *uniqueID)
2084 {
2085
2086 ENTER_PROTECTED_BLOCK
2087 ISDESTROY()
2088 // #CHECK#
2089 if(uniqueID == NULL)
2090 {
2091 return E_INVALIDARG;
2092 }
2093 *uniqueID = m_dChildID;
2094 return S_OK;
2095
2096 LEAVE_PROTECTED_BLOCK
2097 }
2098
get_windowHandle(HWND __RPC_FAR * windowHandle)2099 STDMETHODIMP CMAccessible:: get_windowHandle(HWND __RPC_FAR *windowHandle)
2100 {
2101
2102 ENTER_PROTECTED_BLOCK
2103 ISDESTROY()
2104 // #CHECK#
2105 if(windowHandle == NULL)
2106 {
2107 return E_INVALIDARG;
2108 }
2109
2110 HWND nHwnd = m_hwnd;
2111 IAccessible* pParent = m_pIParent;
2112 CMAccessible* pChild = this;
2113 while((nHwnd==0) && pParent)
2114 {
2115 pChild = (CMAccessible*)pParent;
2116 if(pChild)
2117 {
2118 pParent = (IAccessible*)pChild->m_pIParent;
2119 nHwnd = (HWND)pChild->m_hwnd;
2120 }
2121 else
2122 pParent = NULL;
2123 }
2124
2125 *windowHandle = nHwnd;
2126 return S_OK;
2127
2128 LEAVE_PROTECTED_BLOCK
2129 }
2130
2131 /**
2132 * Get XAccessibleContext directly from UNO by the stored XAccessible pointer
2133 * @param pXAcc, UNO XAccessible object point.
2134 * @return XAccessibleContext*, the context of the pXAcc.
2135 */
GetContextByXAcc(XAccessible * pXAcc)2136 XAccessibleContext* CMAccessible::GetContextByXAcc( XAccessible* pXAcc )
2137 {
2138 Reference< XAccessibleContext > pRContext;
2139 if( pXAcc == NULL)
2140 return NULL;
2141
2142 pRContext = pXAcc->getAccessibleContext();
2143 if( !pRContext.is() )
2144 return NULL;
2145 return pRContext.get();
2146 }
2147
2148 /**
2149 * Return the member variable m_pXAccessibleSelection, instead of
2150 * get XAccessibleSelection according to XAccessibleContext because if so,it will
2151 * depend on the UNO implementation code,so when COM is created, put XAccessibleSelection
2152 * by bridge management system
2153 * @return XAccessibleSelection*, the selection of the current object.
2154 */
GetSelection()2155 Reference< XAccessibleSelection > CMAccessible::GetSelection()
2156 {
2157 if( pUNOInterface == NULL )
2158 return NULL;
2159 Reference< XAccessibleContext > pRContext = pUNOInterface->getAccessibleContext();
2160 if(pRContext.is())
2161 {
2162 Reference< XAccessibleSelection > pRSelection(pRContext,UNO_QUERY);
2163 return pRSelection;
2164 }
2165 return NULL;
2166 }
2167
2168 /**
2169 * Select one XAccessible item, for accSelect implementation
2170 * @param pItem, the item should be selected.
2171 * @return S_OK if successful.
2172 */
SelectChild(XAccessible * pItem)2173 HRESULT CMAccessible::SelectChild(XAccessible* pItem)
2174 {
2175
2176 ENTER_PROTECTED_BLOCK
2177 ISDESTROY()
2178 XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
2179 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2180 if( pParentContext == NULL || pContext == NULL )
2181 return E_FAIL;
2182
2183 Reference< XAccessibleSelection > pRSelection = GetSelection();
2184 if( !pRSelection.is() )
2185 return E_FAIL;
2186 long Index = pContext->getAccessibleIndexInParent();
2187 pRSelection->selectAccessibleChild( Index );
2188 return S_OK;
2189
2190 LEAVE_PROTECTED_BLOCK
2191 }
2192
2193 /**
2194 * Deselect one XAccessible item, for accSelect implimentation
2195 * @param pItem, the item should be deselected.
2196 * @return S_OK if successful.
2197 */
DeSelectChild(XAccessible * pItem)2198 HRESULT CMAccessible::DeSelectChild(XAccessible* pItem)
2199 {
2200
2201 ENTER_PROTECTED_BLOCK
2202 ISDESTROY()
2203 XAccessibleContext* pParentContext = GetContextByXAcc( pUNOInterface );
2204 ;
2205 XAccessibleContext* pContext = GetContextByXAcc( pItem );
2206 if( pParentContext == NULL || pContext == NULL )
2207 return E_INVALIDARG;
2208
2209 Reference< XAccessibleSelection > pRSelection = GetSelection();
2210 if( !pRSelection.is() )
2211 return E_FAIL;
2212 long Index = pContext->getAccessibleIndexInParent();
2213 pRSelection->deselectAccessibleChild( Index );
2214
2215 return S_OK;
2216
2217 LEAVE_PROTECTED_BLOCK
2218 }
2219
2220 /**
2221 * Select multiple XAccessible items,for implementation of accSelect
2222 * @param pItem, the items should be selected.
2223 * @param size, the size of the items.
2224 * @return S_OK if successful.
2225 */
SelectMutipleChidren(XAccessible ** pItem,int size)2226 HRESULT CMAccessible::SelectMutipleChidren( XAccessible** pItem,int size )
2227 {
2228
2229 ENTER_PROTECTED_BLOCK
2230 ISDESTROY()
2231 // #CHECK#
2232 if(pItem == NULL)
2233 {
2234 return E_INVALIDARG;
2235 }
2236 for(int index = 0;index < size;index++)
2237 {
2238 SelectChild( pItem[index] );
2239 }
2240 return S_OK;
2241
2242 LEAVE_PROTECTED_BLOCK
2243 }
2244
2245 /**
2246 * Deselect multiple XAccessible items,for implementation of accSelect
2247 * @param pItem, the items should be selected.
2248 * @param size, the size of the items.
2249 * @return S_OK if successful.
2250 */
DeSelectMutipleChildren(XAccessible ** pItem,int size)2251 HRESULT CMAccessible::DeSelectMutipleChildren( XAccessible** pItem,int size )
2252 {
2253
2254 ENTER_PROTECTED_BLOCK
2255 ISDESTROY()
2256 // #CHECK#
2257 if(pItem == NULL)
2258 {
2259 return E_INVALIDARG;
2260 }
2261 for(int index = 0;index < size;index++)
2262 {
2263 DeSelectChild( pItem[index] );
2264 }
2265 return S_OK;
2266
2267 LEAVE_PROTECTED_BLOCK
2268 }
2269
2270 /**
2271 * When COM is created, UNO set XAccessible pointer to it
2272 * in order to COM can operate UNO information
2273 * @param pXAcc, the XAccessible object of current object.
2274 * @return S_OK if successful.
2275 */
SetXAccessible(long pXAcc)2276 STDMETHODIMP CMAccessible::SetXAccessible(long pXAcc)
2277 {
2278 pUNOInterface = (XAccessible*)pXAcc;
2279 pRef = pUNOInterface;
2280 m_pEnumVar->PutSelection(/*XAccessibleSelection*/(long)pUNOInterface);
2281
2282 pRContext = pUNOInterface->getAccessibleContext();
2283 pRContextInterface = (XAccessibleContext*)pRContext.is();
2284
2285 return S_OK;
2286 }
2287
2288 /**
2289 * accSelect method has many optional flags, needs to process comprehensively
2290 * Mozilla and Microsoft do not implement SELFLAG_EXTENDSELECTION flag.
2291 * The implementation of this flag is a little trouble-shooting,so we also
2292 * do not implement it now
2293 * @param flagsSelect, the selection flag of the select action.
2294 * @param varChild, the child object pointer of current action.
2295 * @return S_OK if successful.
2296 */
accSelect(long flagsSelect,VARIANT varChild)2297 STDMETHODIMP CMAccessible::accSelect(long flagsSelect, VARIANT varChild)
2298 {
2299
2300 CHECK_ENABLE_INF
2301 ENTER_PROTECTED_BLOCK
2302 ISDESTROY()
2303 if( (flagsSelect&SELFLAG_ADDSELECTION) &&
2304 (SELFLAG_REMOVESELECTION&flagsSelect) )
2305 return E_INVALIDARG;
2306
2307 if ( (flagsSelect&SELFLAG_TAKESELECTION) &&
2308 (
2309 (flagsSelect&SELFLAG_ADDSELECTION) ||
2310 (flagsSelect&SELFLAG_REMOVESELECTION) ||
2311 (flagsSelect&SELFLAG_EXTENDSELECTION )
2312 )
2313 )
2314 return E_INVALIDARG;
2315
2316 if ( varChild.vt != VT_I4 )
2317 return E_INVALIDARG;
2318
2319 IMAccessible* pSelectAcc;
2320 if( varChild.lVal == CHILDID_SELF )
2321 {
2322 pSelectAcc = this;
2323 pSelectAcc->AddRef();
2324 }
2325 else
2326 {
2327 pSelectAcc = GetChildInterface(varChild.lVal);
2328 }
2329
2330 if( pSelectAcc == NULL )
2331 return E_INVALIDARG;
2332
2333 if( flagsSelect&SELFLAG_TAKEFOCUS )
2334 {
2335 long pTempUNO = 0;
2336 pSelectAcc->GetUNOInterface( &pTempUNO);
2337
2338 if( pTempUNO == NULL )
2339 return NULL;
2340
2341 Reference< XAccessibleContext > pRContext = ( (XAccessible*)pTempUNO)->getAccessibleContext();
2342 Reference< XAccessibleComponent > pRComponent(pRContext,UNO_QUERY);
2343 Reference< XAccessible > pRParentXAcc = pRContext->getAccessibleParent();
2344 Reference< XAccessibleContext > pRParentContext = pRParentXAcc->getAccessibleContext();
2345 Reference< XAccessibleComponent > pRParentComponent(pRParentContext,UNO_QUERY);
2346 Reference< XAccessibleSelection > pRParentSelection(pRParentContext,UNO_QUERY);
2347
2348
2349 pRComponent->grabFocus();
2350
2351 if( flagsSelect & SELFLAG_TAKESELECTION )
2352 {
2353 pRParentSelection->clearAccessibleSelection();
2354 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2355 }
2356
2357 if( flagsSelect & SELFLAG_ADDSELECTION )
2358 {
2359 pRParentSelection->selectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2360 }
2361
2362 if( flagsSelect & SELFLAG_REMOVESELECTION )
2363 {
2364 pRParentSelection->deselectAccessibleChild( pRContext->getAccessibleIndexInParent() );
2365 }
2366
2367 if( flagsSelect & SELFLAG_EXTENDSELECTION )
2368 {
2369 long indexInParrent = pRContext->getAccessibleIndexInParent();
2370
2371 if( pRParentSelection->isAccessibleChildSelected( indexInParrent + 1 ) ||
2372 pRParentSelection->isAccessibleChildSelected( indexInParrent - 1 ) )
2373 {
2374 pRParentSelection->selectAccessibleChild( indexInParrent );
2375 }
2376 }
2377
2378 }
2379
2380 pSelectAcc->Release();
2381 return S_OK;
2382
2383 LEAVE_PROTECTED_BLOCK
2384 }
2385
2386 /**
2387 * Return XAccessible interface pointer when needed
2388 * @param pXAcc, [in, out] the Uno interface of the current object.
2389 * @return S_OK if successful.
2390 */
GetUNOInterface(long * pXAcc)2391 STDMETHODIMP CMAccessible::GetUNOInterface(long* pXAcc)
2392 {
2393 // #CHECK#
2394 if(pXAcc == NULL)
2395 return E_INVALIDARG;
2396
2397 *pXAcc = (long)pUNOInterface;
2398 return S_OK;
2399 }
2400
2401 /**
2402 * Helper method for Implementation of get_accDefaultAction
2403 * @param pAction, the default action point of the current object.
2404 * @return S_OK if successful.
2405 */
SetDefaultAction(long pAction)2406 STDMETHODIMP CMAccessible::SetDefaultAction(long pAction)
2407 {
2408 m_pXAction = (XAccessibleAction*)pAction;
2409 return S_OK;
2410 }
2411
2412 /**
2413 * This method is called when AT open some UI elements initially
2414 * the UI element takes the default action defined here
2415 * @param varChild, the child id of the defaultaction.
2416 * @param pszDefaultAction,[in/out] the description of the current action.
2417 * @return S_OK if successful.
2418 */
get_accDefaultAction(VARIANT varChild,BSTR * pszDefaultAction)2419 HRESULT STDMETHODCALLTYPE CMAccessible::get_accDefaultAction(VARIANT varChild, BSTR *pszDefaultAction)
2420 {
2421
2422 ENTER_PROTECTED_BLOCK
2423 ISDESTROY()
2424 // #CHECK#
2425 if(pszDefaultAction == NULL)
2426 {
2427 return E_INVALIDARG;
2428 }
2429 if(varChild.vt==VT_I4)
2430 {
2431 if(varChild.lVal==CHILDID_SELF)
2432 {
2433 if( m_pXAction == NULL )
2434 return DISP_E_MEMBERNOTFOUND;
2435 SAFE_SYSFREESTRING(*pszDefaultAction);
2436 *pszDefaultAction = SysAllocString(m_pszActionDescription);
2437 return S_OK;
2438 }
2439
2440 long lVal = varChild.lVal;
2441 varChild.lVal = CHILDID_SELF;
2442 IMAccessible *pChild = this->GetChildInterface(lVal);
2443 if(!pChild)
2444 return E_FAIL;
2445 return pChild->get_accDefaultAction(varChild,pszDefaultAction);
2446 }
2447 return S_FALSE;
2448
2449 LEAVE_PROTECTED_BLOCK
2450 }
2451
2452 /**
2453 * AT call this method to operate application
2454 * @param varChild, the child id of the action object.
2455 * @return S_OK if successful.
2456 */
accDoDefaultAction(VARIANT varChild)2457 HRESULT STDMETHODCALLTYPE CMAccessible::accDoDefaultAction(VARIANT varChild)
2458 {
2459
2460 ENTER_PROTECTED_BLOCK
2461 ISDESTROY()
2462 if( varChild.vt != VT_I4 )
2463 return E_INVALIDARG;
2464 if( m_pXAction == NULL )
2465 return E_FAIL;
2466 if( m_pXAction->getAccessibleActionCount() == 0 )
2467 return E_FAIL;
2468
2469 if(varChild.lVal==CHILDID_SELF)
2470 {
2471 if(m_pXAction->getAccessibleActionCount() > 0)
2472 m_pXAction->doAccessibleAction(0);
2473 return S_OK;
2474 }
2475
2476 long lVal = varChild.lVal;
2477 varChild.lVal = CHILDID_SELF;
2478 IMAccessible *pChild = this->GetChildInterface(lVal);
2479 if(!pChild)
2480 return E_FAIL;
2481 return pChild->accDoDefaultAction( varChild );
2482
2483 LEAVE_PROTECTED_BLOCK
2484 }
2485
2486 /**
2487 * UNO set description information for action to COM.
2488 * @param szAction, the action description of the current object.
2489 * @return S_OK if successful.
2490 */
Put_ActionDescription(const OLECHAR * szAction)2491 STDMETHODIMP CMAccessible::Put_ActionDescription( const OLECHAR* szAction)
2492 {
2493
2494 ENTER_PROTECTED_BLOCK
2495 ISDESTROY()
2496 // #CHECK#
2497 if(szAction == NULL)
2498 {
2499 return E_INVALIDARG;
2500 }
2501 SAFE_SYSFREESTRING(m_pszActionDescription );
2502 m_pszActionDescription = SysAllocString( szAction );
2503 return S_OK;
2504
2505 LEAVE_PROTECTED_BLOCK
2506 }
2507
GetXInterfaceFromXAccessible(XAccessible * pXAcc,XInterface ** ppXI,int index)2508 BOOL CMAccessible::GetXInterfaceFromXAccessible(XAccessible* pXAcc, XInterface** ppXI, int index)
2509 {
2510 Reference< XAccessibleContext > pRContext;
2511
2512 switch(index)
2513 {
2514 case XI_COMPONENT:
2515 QUERYXINTERFACE(AccessibleComponent)
2516 break;
2517 case XI_TEXT:
2518 QUERYXINTERFACE(AccessibleText)
2519 break;
2520 case XI_EDITABLETEXT:
2521 QUERYXINTERFACE(AccessibleEditableText)
2522 break;
2523 case XI_TABLE:
2524 QUERYXINTERFACE(AccessibleTable)
2525 break;
2526 case XI_SELECTION:
2527 QUERYXINTERFACE(AccessibleSelection)
2528 break;
2529 case XI_EXTENDEDCOMP:
2530 QUERYXINTERFACE(AccessibleExtendedComponent)
2531 break;
2532 case XI_KEYBINDING:
2533 QUERYXINTERFACE(AccessibleKeyBinding)
2534 break;
2535 case XI_ACTION:
2536 QUERYXINTERFACE(AccessibleAction)
2537 break;
2538 case XI_VALUE:
2539 QUERYXINTERFACE(AccessibleValue)
2540 break;
2541 case XI_HYPERTEXT:
2542 QUERYXINTERFACE(AccessibleHypertext)
2543 break;
2544 case XI_HYPERLINK:
2545 QUERYXINTERFACE(AccessibleHyperlink)
2546 break;
2547 case XI_IMAGE:
2548 QUERYXINTERFACE(AccessibleImage)
2549 break;
2550 default:
2551 break;
2552 }
2553
2554 return FALSE;
2555 }
2556
SmartQI(void * pv,REFIID iid,void ** ppvObject)2557 HRESULT WINAPI CMAccessible::SmartQI(void* pv, REFIID iid, void** ppvObject)
2558 {
2559 ENTER_PROTECTED_BLOCK
2560 ISDESTROY()
2561 if( ImplIsEqualGUID(iid,IID_IAccIdentity) ||
2562 ImplIsEqualGUID(iid,IID_IStdMarshalInfo) ||
2563 ImplIsEqualGUID(iid,IID_IMarshal) ||
2564 ImplIsEqualGUID(iid,IID_IExternalConnection)||
2565 ImplIsEqualGUID(iid,IID_IOleWindow))
2566 return E_FAIL;
2567
2568
2569 _UNO_AGGMAP_ENTRY* pMap = _GetAggEntries();
2570 while(pMap && pMap->piid)
2571 {
2572 if(ImplIsEqualGUID(iid, *pMap->piid))
2573 {
2574 XInterface* pXI = NULL;
2575 BOOL bFound = GetXInterfaceFromXAccessible(pUNOInterface,&pXI,pMap->XIFIndex);
2576 if(!bFound)
2577 {
2578 return E_FAIL;
2579 }
2580
2581 XGUIDToComObjHash::iterator pIndTemp = m_containedObjects.find( iid );
2582 if ( pIndTemp != m_containedObjects.end() )
2583 {
2584 return pIndTemp->second.p->QueryInterface( iid, ppvObject );
2585 }
2586 else
2587 {
2588 ActivateActContext();
2589 HRESULT hr = pMap->pfnCreateInstance(pv, iid, ppvObject);
2590 DeactivateActContext();
2591 if(hr == S_OK)
2592 {
2593 m_containedObjects.insert(XGUIDToComObjHash::value_type(*pMap->piid,(IUnknown*)*ppvObject));
2594 IUNOXWrapper* wrapper = NULL;
2595 ((IUnknown*)*ppvObject)->QueryInterface(IID_IUNOXWrapper, (void**)&wrapper);
2596 if(wrapper)
2597 {
2598 wrapper->put_XInterface((long)pUNOInterface);
2599 wrapper->Release();
2600 }
2601 return S_OK;
2602 }
2603 }
2604 return E_FAIL;
2605 }
2606 pMap++;
2607 }
2608 return E_FAIL;
2609
2610 LEAVE_PROTECTED_BLOCK
2611 }
2612
get_IAccessibleFromXAccessible(long pXAcc,IAccessible ** ppIA)2613 BOOL CMAccessible::get_IAccessibleFromXAccessible(long pXAcc, IAccessible **ppIA)
2614 {
2615
2616 ENTER_PROTECTED_BLOCK
2617
2618 // #CHECK#
2619 if(ppIA == NULL)
2620 {
2621 return E_INVALIDARG;
2622 }
2623 BOOL isGet = FALSE;
2624 if(g_pAgent)
2625 isGet = g_pAgent->GetIAccessibleFromXAccessible((XAccessible*)pXAcc,ppIA);
2626
2627 if(isGet)
2628 return TRUE;
2629 else
2630 return FALSE;
2631
2632 LEAVE_PROTECTED_BLOCK
2633 }
2634
get_OLECHARFromAny(Any & pAny,OLECHAR * pChar)2635 void CMAccessible::get_OLECHARFromAny(Any& pAny, OLECHAR* pChar)
2636 {
2637 // #CHECK#
2638 if(pChar == NULL)
2639 return;
2640
2641 switch(pAny.getValueTypeClass())
2642 {
2643 case TypeClass_CHAR:
2644 {
2645 sal_Int8 val;
2646 pAny >>= val;
2647 swprintf( pChar, L"%d", val);
2648 break;
2649 }
2650 case TypeClass_BOOLEAN:
2651 {
2652 sal_Bool val;
2653 pAny >>= val;
2654 swprintf( pChar, L"%d", val);
2655 break;
2656 }
2657 case TypeClass_BYTE:
2658 {
2659 sal_Int8 val;
2660 pAny >>= val;
2661 swprintf( pChar, L"%d", val);
2662 break;
2663 }
2664 case TypeClass_SHORT:
2665 {
2666 SHORT val;
2667 pAny >>= val;
2668 swprintf( pChar, L"%d", val);
2669 break;
2670 }
2671 case TypeClass_UNSIGNED_SHORT:
2672 {
2673 USHORT val;
2674 pAny >>= val;
2675 swprintf( pChar, L"%d", val);
2676 break;
2677 }
2678 case TypeClass_LONG:
2679 {
2680 LONG val;
2681 pAny >>= val;
2682 swprintf( pChar, L"%ld", val);
2683 break;
2684 }
2685 case TypeClass_UNSIGNED_LONG:
2686 {
2687 ULONG val;
2688 pAny >>= val;
2689 swprintf( pChar, L"%ld", val);
2690 break;
2691 }
2692 case TypeClass_FLOAT:
2693 {
2694 FLOAT val;
2695 pAny >>= val;
2696 swprintf( pChar, L"%.3f", val);
2697 break;
2698 }
2699 case TypeClass_DOUBLE:
2700 {
2701 DOUBLE val;
2702 pAny >>= val;
2703 swprintf( pChar, L"%.6lf", val);
2704 break;
2705 }
2706 case TypeClass_STRING:
2707 {
2708 ::rtl::OUString val;
2709 pAny >>= val;
2710 wcscpy(pChar, val.getStr());
2711 break;
2712 }
2713 case TypeClass_SEQUENCE:
2714 {
2715 if(pAny.getValueType() == getCppuType( (Sequence< ::rtl::OUString > *)0 ) )
2716 {
2717 Sequence < ::rtl::OUString > val;
2718 pAny >>= val;
2719
2720 ::rtl::OUString pString;
2721
2722 int count = val.getLength();
2723
2724 for( int iIndex = 0;iIndex < count;iIndex++ )
2725 {
2726 pString += val[iIndex];
2727 }
2728 wcscpy(pChar, pString.getStr());
2729 }
2730 else if (pAny.getValueType() == getCppuType( (Sequence< ::com::sun::star::style::TabStop >* )0 ) )
2731 {
2732 Sequence < ::com::sun::star::style::TabStop > val;
2733 pAny >>= val;
2734 int count = val.getLength();
2735
2736 for( int iIndex = 0;iIndex < count;iIndex++ )
2737 {
2738 OLECHAR pAttrs[512] = {NULL};
2739
2740 OLECHAR pAttrsPosition[512] = {NULL};
2741 OLECHAR pAttrsDescimalChar[512] = {NULL};
2742 OLECHAR pAttrsFillChar[512] = {NULL};
2743
2744 ::com::sun::star::style::TabStop sigleVal = val[iIndex];
2745
2746 swprintf( pAttrsPosition, L"Position=%ld,TabAlign=%ld",
2747 sigleVal.Position, sigleVal.Alignment);
2748
2749 if(sigleVal.DecimalChar==';' || sigleVal.DecimalChar == ':' || sigleVal.DecimalChar == ',' ||
2750 sigleVal.DecimalChar == '=' || sigleVal.DecimalChar == '\\')
2751 swprintf( pAttrsDescimalChar, L"DecimalChar=\\%c",sigleVal.DecimalChar);
2752 else
2753 swprintf( pAttrsDescimalChar, L"DecimalChar=%c",sigleVal.DecimalChar);
2754
2755 if(sigleVal.FillChar==';' || sigleVal.FillChar == ':' || sigleVal.FillChar == ',' ||
2756 sigleVal.FillChar == '=' || sigleVal.FillChar == '\\')
2757 swprintf( pAttrsFillChar, L"FillChar=\\%c",sigleVal.FillChar);
2758 else
2759 swprintf( pAttrsFillChar, L"FillChar=%c",sigleVal.FillChar);
2760
2761 swprintf( pAttrs, L"%s,%s,%s,",pAttrsPosition,pAttrsDescimalChar,pAttrsFillChar);
2762
2763 wcscat(pChar,pAttrs);
2764 }
2765 }
2766 break;
2767 }
2768 case TypeClass_ENUM:
2769 {
2770 if (pAny.getValueType() == getCppuType( (::com::sun::star::awt::FontSlant* )0 ) )
2771 {
2772 com::sun::star::awt::FontSlant val;
2773 pAny >>= val;
2774 swprintf( pChar, L"%d", val);
2775 }
2776 }
2777 case TypeClass_STRUCT:
2778 {
2779 if (pAny.getValueType() == getCppuType( (::com::sun::star::style::LineSpacing* )0 ) )
2780 {
2781 com::sun::star::style::LineSpacing val;
2782 pAny >>= val;
2783 swprintf( pChar, L"Mode=%ld,Height=%ld,", val.Mode, val.Height);
2784 }
2785 else if (pAny.getValueType() == getCppuType( (com::sun::star::accessibility::TextSegment *)0 ) )
2786 {
2787 com::sun::star::accessibility::TextSegment val;
2788 pAny >>= val;
2789 ::rtl::OUString realVal(val.SegmentText);
2790 wcscpy(pChar, realVal.getStr());
2791 }
2792 break;
2793 }
2794 case TypeClass_VOID:
2795 case TypeClass_HYPER:
2796 case TypeClass_UNSIGNED_HYPER:
2797 case TypeClass_TYPE:
2798 case TypeClass_ANY:
2799 case TypeClass_TYPEDEF:
2800 case TypeClass_UNION:
2801 case TypeClass_EXCEPTION:
2802 case TypeClass_ARRAY:
2803 case TypeClass_INTERFACE:
2804 case TypeClass_SERVICE:
2805 case TypeClass_MODULE:
2806 case TypeClass_INTERFACE_METHOD:
2807 case TypeClass_INTERFACE_ATTRIBUTE:
2808 case TypeClass_UNKNOWN:
2809 case TypeClass_PROPERTY:
2810 case TypeClass_CONSTANT:
2811 case TypeClass_CONSTANTS:
2812 case TypeClass_SINGLETON:
2813 case TypeClass_MAKE_FIXED_SIZE:
2814 break;
2815 default:
2816 break;
2817 }
2818 }
2819
get_OLECHAR4Numbering(const Any & pAny,short numberingLevel,const OUString & numberingPrefix,OLECHAR * pChar)2820 void CMAccessible::get_OLECHAR4Numbering(const Any& pAny, short numberingLevel,const OUString& numberingPrefix,OLECHAR* pChar)
2821 {
2822 if(pChar == NULL)
2823 return;
2824 Reference< ::com::sun::star::container::XIndexReplace > pXIndex;
2825 if((pAny>>=pXIndex) && (numberingLevel !=-1))//numbering level is -1,means invalid value
2826 {
2827 Any aAny = pXIndex->getByIndex(numberingLevel);
2828 Sequence< ::com::sun::star::beans::PropertyValue > aProps;
2829 aAny >>= aProps;
2830 const ::com::sun::star::beans::PropertyValue* pPropArray = aProps.getConstArray();
2831 sal_Int32 nCount = aProps.getLength();
2832 swprintf(pChar,L"Numbering:NumberingLevel=%d,",numberingLevel);
2833 for( sal_Int32 i=0; i<nCount; i++ )
2834 {
2835 ::com::sun::star::beans::PropertyValue rProp = pPropArray[i];
2836 if( (rProp.Name.compareTo(OUString::createFromAscii("BulletChar"))==0)||
2837 (rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)||
2838 (rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0))
2839 {
2840 OLECHAR propStr[512] = {NULL};
2841 swprintf(propStr,L"%s=",rProp.Name.getStr());
2842 OLECHAR pTemp[256] = {NULL};
2843 CMAccessible::get_OLECHARFromAny(rProp.Value,pTemp);
2844 if(rProp.Name.compareTo(OUString::createFromAscii("GraphicURL"))==0)
2845 {
2846 OLECHAR* pOccur = wcschr(pTemp,':');
2847 if(pOccur)
2848 *pOccur = '.';
2849 }
2850 wcscat(propStr,pTemp);
2851 wcscat(pChar,propStr);
2852 wcscat(pChar,L",");
2853
2854 if(rProp.Name.compareTo(OUString::createFromAscii("NumberingType"))==0)
2855 {
2856 if(numberingPrefix.getLength()!=0)
2857 {
2858 swprintf(pTemp,L"NumberingPrefix=%s,",numberingPrefix.getStr());
2859 wcscat(pChar,pTemp);
2860 }
2861 }
2862 }
2863 }
2864 }
2865
2866 //Because now have three types numbering level:
2867 //1.real numbering list,numbering level>=0 and numbering Rule !=NULL;
2868 //2.common paragraph, numbering level >=0, and numbering Rule == NULL;
2869 //3.TOC paragraph, numbering level >0, and numbering Rule ==NULL;
2870 // IAText:numberinglevel base on 0, but TOC's level base on 1,
2871 // so NumberingLevel value will be decreased 1 in bridge code.
2872 else if(numberingLevel >0)
2873 {
2874 swprintf(pChar,L"Numbering:NumberingLevel=%d,NumberingType=4,NumberingPrefix=,",numberingLevel-1);
2875 }
2876 else
2877 {
2878 swprintf(pChar,L"Numbering:");
2879 }
2880 }
2881
ConvertAnyToVariant(const::com::sun::star::uno::Any & rAnyVal,VARIANT * pvData)2882 void CMAccessible::ConvertAnyToVariant(const ::com::sun::star::uno::Any &rAnyVal, VARIANT *pvData)
2883 {
2884 if(rAnyVal.hasValue())
2885 {
2886 // Clear VARIANT variable.
2887 VariantClear(pvData);
2888
2889 // Set value according to value type.
2890 switch(rAnyVal.getValueTypeClass())
2891 {
2892 case TypeClass_CHAR:
2893 pvData->vt = VT_UI1;
2894 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Char));
2895 break;
2896
2897 case TypeClass_BOOLEAN:
2898 pvData->vt = VT_BOOL;
2899 memcpy(&pvData->boolVal, rAnyVal.getValue(), sizeof(sal_Bool));
2900 break;
2901
2902 case TypeClass_BYTE:
2903 pvData->vt = VT_UI1;
2904 memcpy(&pvData->bVal, rAnyVal.getValue(), sizeof(sal_Int8));
2905 break;
2906
2907 case TypeClass_SHORT:
2908 pvData->vt = VT_I2;
2909 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_Int16));
2910 break;
2911
2912 case TypeClass_UNSIGNED_SHORT:
2913 pvData->vt = VT_I2;
2914 memcpy(&pvData->iVal, rAnyVal.getValue(), sizeof(sal_uInt16));
2915 break;
2916
2917 case TypeClass_LONG:
2918 pvData->vt = VT_I4;
2919 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_Int32));
2920 break;
2921
2922 case TypeClass_UNSIGNED_LONG:
2923 pvData->vt = VT_I4;
2924 memcpy(&pvData->lVal, rAnyVal.getValue(), sizeof(sal_uInt32));
2925 break;
2926
2927 case TypeClass_FLOAT:
2928 pvData->vt = VT_R4;
2929 memcpy(&pvData->fltVal, rAnyVal.getValue(), sizeof(float));
2930 break;
2931
2932 case TypeClass_DOUBLE:
2933 pvData->vt = VT_R8;
2934 memcpy(&pvData->dblVal, rAnyVal.getValue(), sizeof(double));
2935 break;
2936
2937 case TypeClass_STRING:
2938 {
2939 pvData->vt = VT_BSTR;
2940 ::rtl::OUString val;
2941 rAnyVal >>= val;
2942 pvData->bstrVal = SysAllocString((OLECHAR *)val.getStr());
2943 break;
2944 }
2945
2946 case TypeClass_VOID:
2947 case TypeClass_HYPER:
2948 case TypeClass_UNSIGNED_HYPER:
2949 case TypeClass_TYPE:
2950 case TypeClass_ANY:
2951 case TypeClass_ENUM:
2952 case TypeClass_TYPEDEF:
2953 case TypeClass_STRUCT:
2954 case TypeClass_UNION:
2955 case TypeClass_EXCEPTION:
2956 case TypeClass_SEQUENCE:
2957 case TypeClass_ARRAY:
2958 case TypeClass_INTERFACE:
2959 {
2960 Reference< XAccessible > pXAcc;
2961 if(rAnyVal >>= pXAcc)
2962 {
2963 if(pXAcc.is())
2964 {
2965 IAccessible* pIAcc = NULL;
2966 get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
2967 if(pIAcc == NULL)
2968 {
2969 Reference< XAccessibleContext > pXAccContext = pXAcc->getAccessibleContext();
2970 g_pAgent->InsertAccObj(pXAcc.get(),pXAccContext->getAccessibleParent().get());
2971 get_IAccessibleFromXAccessible((long)pXAcc.get(), &pIAcc);
2972 }
2973 if(pIAcc)
2974 {
2975 pIAcc->AddRef();
2976
2977 pvData->vt = VT_UNKNOWN;
2978 pvData->pdispVal = (IAccessible2*)pIAcc;
2979 break;
2980 }
2981 }
2982 }
2983 }
2984 case TypeClass_SERVICE:
2985 case TypeClass_MODULE:
2986 case TypeClass_INTERFACE_METHOD:
2987 case TypeClass_INTERFACE_ATTRIBUTE:
2988 case TypeClass_UNKNOWN:
2989 case TypeClass_PROPERTY:
2990 case TypeClass_CONSTANT:
2991 case TypeClass_CONSTANTS:
2992 case TypeClass_SINGLETON:
2993 case TypeClass_MAKE_FIXED_SIZE:
2994 // Output the type string, if there is other uno value type.
2995 pvData->vt = VT_BSTR;
2996 pvData->bstrVal = SysAllocString(rAnyVal.getValueTypeName().getStr());
2997 break;
2998
2999 default:
3000 break;
3001 }
3002 }
3003 else
3004 {
3005 VariantClear(pvData);
3006 }
3007 }
3008
Get_XAccChildID(long * childID)3009 STDMETHODIMP CMAccessible::Get_XAccChildID(long* childID)
3010 {
3011 // #CHECK#
3012 if(childID == NULL)
3013 {
3014 return E_FAIL;
3015 }
3016 *childID = m_dChildID;
3017 return S_OK;
3018 }
get_states(AccessibleStates __RPC_FAR * states)3019 STDMETHODIMP CMAccessible:: get_states(AccessibleStates __RPC_FAR *states )
3020 {
3021
3022 CHECK_ENABLE_INF
3023 ENTER_PROTECTED_BLOCK
3024 ISDESTROY()
3025 // #CHECK XInterface#
3026 if( !pRContext.is() )
3027 return E_FAIL;
3028
3029 Reference<XAccessibleStateSet> pRStateSet = pRContext.get()->getAccessibleStateSet();
3030 if(!pRStateSet.is())
3031 {
3032 return S_OK;
3033 }
3034 Sequence<short> pStates = pRStateSet->getStates();
3035
3036
3037 long count = pStates.getLength() ;
3038 *states = 0x0;
3039 for( int i = 0; i < count; i++ )
3040 {
3041 for( int j = 0; j < sizeof(UNO_STATES) / sizeof(UNO_STATES[0]); j++ )
3042 {
3043 if( pStates[i] == UNO_STATES[j] )
3044 {
3045 *states |= IA2_STATES[j];
3046 break;
3047 }
3048 }
3049 }
3050 return S_OK;
3051
3052
3053 LEAVE_PROTECTED_BLOCK
3054 }
3055
3056 // return the UNO roles
get_extendedRole(BSTR __RPC_FAR *)3057 STDMETHODIMP CMAccessible:: get_extendedRole( BSTR __RPC_FAR * )
3058 {
3059
3060 CHECK_ENABLE_INF
3061 ENTER_PROTECTED_BLOCK
3062 ISDESTROY()
3063
3064 return E_NOTIMPL;
3065
3066 LEAVE_PROTECTED_BLOCK
3067 }
3068
get_localizedExtendedRole(BSTR __RPC_FAR *)3069 STDMETHODIMP CMAccessible:: get_localizedExtendedRole( BSTR __RPC_FAR * )
3070 {
3071
3072 ENTER_PROTECTED_BLOCK
3073 ISDESTROY()
3074 return E_NOTIMPL;
3075
3076 LEAVE_PROTECTED_BLOCK
3077 }
get_nExtendedStates(long __RPC_FAR *)3078 STDMETHODIMP CMAccessible:: get_nExtendedStates( long __RPC_FAR * )
3079 {
3080
3081 CHECK_ENABLE_INF
3082 ENTER_PROTECTED_BLOCK
3083 ISDESTROY()
3084
3085 return E_NOTIMPL;
3086
3087 LEAVE_PROTECTED_BLOCK
3088 }
3089
3090
get_localizedExtendedStates(long,BSTR __RPC_FAR * __RPC_FAR *,long __RPC_FAR *)3091 STDMETHODIMP CMAccessible:: get_localizedExtendedStates( long, BSTR __RPC_FAR *__RPC_FAR *, long __RPC_FAR *)
3092 {
3093
3094 ENTER_PROTECTED_BLOCK
3095 ISDESTROY()
3096 return E_NOTIMPL;
3097
3098 LEAVE_PROTECTED_BLOCK
3099 }
3100
3101
get_indexInParent(long __RPC_FAR * accParentIndex)3102 STDMETHODIMP CMAccessible:: get_indexInParent( long __RPC_FAR *accParentIndex)
3103 {
3104
3105 CHECK_ENABLE_INF
3106 ENTER_PROTECTED_BLOCK
3107 ISDESTROY()
3108 // #CHECK#
3109 if(accParentIndex == NULL)
3110 return E_INVALIDARG;
3111
3112 // #CHECK XInterface#
3113 if( !pRContext.is() )
3114 return E_FAIL;
3115
3116 *accParentIndex = pRContext.get()->getAccessibleIndexInParent();
3117 return S_OK;
3118
3119
3120 LEAVE_PROTECTED_BLOCK
3121 }
get_locale(IA2Locale __RPC_FAR * locale)3122 STDMETHODIMP CMAccessible:: get_locale( IA2Locale __RPC_FAR *locale )
3123 {
3124
3125 CHECK_ENABLE_INF
3126 ENTER_PROTECTED_BLOCK
3127 ISDESTROY()
3128 if(locale == NULL)
3129 return E_INVALIDARG;
3130 // #CHECK XInterface#
3131
3132 if( !pRContext.is() )
3133 return E_FAIL;
3134
3135 ::com::sun::star::lang::Locale unoLoc = pRContext.get()->getLocale();
3136 locale->language = SysAllocString((OLECHAR*)unoLoc.Language.getStr());
3137 locale->country = SysAllocString((OLECHAR*)unoLoc.Country.getStr());
3138 locale->variant = SysAllocString((OLECHAR*)unoLoc.Variant.getStr());
3139
3140 return S_OK;
3141
3142 LEAVE_PROTECTED_BLOCK
3143 }
3144
GetMSAAStateFromUNO(short xState)3145 DWORD GetMSAAStateFromUNO(short xState)
3146 {
3147 DWORD IState = STATE_SYSTEM_UNAVAILABLE;
3148 switch( xState )
3149 {
3150 case /*AccessibleStateType::*/AccessibleStateType::BUSY:
3151 IState = STATE_SYSTEM_BUSY;
3152 break;
3153 case /*AccessibleStateType::*/AccessibleStateType::CHECKED:
3154 IState = STATE_SYSTEM_CHECKED;
3155 break;
3156 case /*AccessibleStateType::*/AccessibleStateType::DEFUNC:
3157 IState = STATE_SYSTEM_UNAVAILABLE;
3158 break;
3159 case /*AccessibleStateType::*/AccessibleStateType::EXPANDED:
3160 IState = STATE_SYSTEM_EXPANDED;
3161 break;
3162 case /*AccessibleStateType::*/AccessibleStateType::FOCUSABLE:
3163 IState = STATE_SYSTEM_FOCUSABLE;
3164 break;
3165 case /*AccessibleStateType::*/AccessibleStateType::FOCUSED:
3166 IState = STATE_SYSTEM_FOCUSED;
3167 break;
3168 case /*AccessibleStateType::*/AccessibleStateType::INDETERMINATE:
3169 IState = STATE_SYSTEM_MIXED;
3170 break;
3171 case /*AccessibleStateType::*/AccessibleStateType::MULTI_SELECTABLE:
3172 IState = STATE_SYSTEM_MULTISELECTABLE;
3173 break;
3174 case /*AccessibleStateType::*/AccessibleStateType::PRESSED:
3175 IState = STATE_SYSTEM_PRESSED;
3176 break;
3177 case /*AccessibleStateType::*/AccessibleStateType::RESIZABLE:
3178 IState = STATE_SYSTEM_SIZEABLE;
3179 break;
3180 case /*AccessibleStateType::*/AccessibleStateType::SELECTABLE:
3181 IState = STATE_SYSTEM_SELECTABLE;
3182 break;
3183 case /*AccessibleStateType::*/AccessibleStateType::SELECTED:
3184 IState = STATE_SYSTEM_SELECTED;
3185 break;
3186 case /*AccessibleStateType::*/AccessibleStateType::ARMED:
3187 IState = STATE_SYSTEM_FOCUSED;
3188 break;
3189 case /*AccessibleStateType::*/AccessibleStateType::EXPANDABLE:
3190 IState = STATE_SYSTEM_COLLAPSED;
3191 break;
3192 default:
3193 break;
3194 }
3195 return IState;
3196 }
3197
get_appName(BSTR __RPC_FAR * name)3198 STDMETHODIMP CMAccessible:: get_appName( BSTR __RPC_FAR *name)
3199 {
3200
3201 ENTER_PROTECTED_BLOCK
3202 ISDESTROY()
3203 if(name == NULL)
3204 return E_INVALIDARG;
3205
3206 *name = SysAllocString(OLESTR("Hannover"));
3207 return S_OK;
3208 LEAVE_PROTECTED_BLOCK
3209 }
get_appVersion(BSTR __RPC_FAR * version)3210 STDMETHODIMP CMAccessible:: get_appVersion(BSTR __RPC_FAR *version)
3211 {
3212
3213 ENTER_PROTECTED_BLOCK
3214 ISDESTROY()
3215 if(version == NULL)
3216 return E_INVALIDARG;
3217 *version=SysAllocString(OLESTR("3.0"));
3218 return S_OK;
3219 LEAVE_PROTECTED_BLOCK
3220 }
get_toolkitName(BSTR __RPC_FAR * name)3221 STDMETHODIMP CMAccessible:: get_toolkitName(BSTR __RPC_FAR *name)
3222 {
3223
3224 ENTER_PROTECTED_BLOCK
3225 ISDESTROY()
3226 if(name == NULL)
3227 return E_INVALIDARG;
3228 *name = SysAllocString(OLESTR(" "));
3229 return S_OK;
3230 LEAVE_PROTECTED_BLOCK
3231 }
get_toolkitVersion(BSTR __RPC_FAR * version)3232 STDMETHODIMP CMAccessible:: get_toolkitVersion(BSTR __RPC_FAR *version)
3233 {
3234
3235 ENTER_PROTECTED_BLOCK
3236 ISDESTROY()
3237 if(version == NULL)
3238 return E_INVALIDARG;
3239 *version = SysAllocString(OLESTR(" "));
3240 return S_OK;
3241 LEAVE_PROTECTED_BLOCK
3242 }
3243
3244
get_attributes(BSTR * pAttr)3245 STDMETHODIMP CMAccessible::get_attributes(/*[out]*/ BSTR *pAttr)
3246 {
3247 ENTER_PROTECTED_BLOCK
3248 ISDESTROY()
3249 CHECK_ENABLE_INF
3250 Reference<XAccessibleContext> pRContext = pUNOInterface->getAccessibleContext();
3251 if( !pRContext.is() )
3252 {
3253 return E_FAIL;
3254 }
3255 Reference<XAccessibleExtendedAttributes> pRXI(pRContext,UNO_QUERY);
3256 if( !pRXI.is() )
3257 return E_FAIL;
3258 else
3259 {
3260 com::sun::star::uno::Reference<com::sun::star::accessibility::XAccessibleExtendedAttributes> pRXAttr;
3261 pRXAttr = pRXI.get();
3262 ::com::sun::star::uno::Any anyVal = pRXAttr->getExtendedAttributes();
3263
3264 ::rtl::OUString val;
3265 anyVal >>= val;
3266
3267 if(*pAttr)
3268 SAFE_SYSFREESTRING(*pAttr);
3269 *pAttr = SysAllocString((OLECHAR *)val.getStr());
3270
3271 return S_OK;
3272 }
3273 LEAVE_PROTECTED_BLOCK
3274 }
3275
3276