~stomato463/+junk/nvdajp

« back to all changes in this revision

Viewing changes to nvdaHelper/remote/IA2Support.cpp

  • Committer: Masataka Shinke
  • Date: 2011-10-25 12:35:26 UTC
  • mfrom: (4185 jpmain)
  • mto: This revision was merged to the branch mainline in revision 4211.
  • Revision ID: mshinke@users.sourceforge.jp-20111025123526-ze527a2rl3z0g2ky
lp:~nishimotz/nvdajp/main : 4185 をマージ

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//IA2Support.cpp
2
 
//Copyright (c) 2007 Michael Curran <mick@kulgan.net>
3
 
//This file is covered by the GNU General Public Licence
4
 
//See the file Copying for details.
 
1
/*
 
2
This file is a part of the NVDA project.
 
3
URL: http://www.nvda-project.org/
 
4
Copyright 2006-2010 NVDA contributers.
 
5
    This program is free software: you can redistribute it and/or modify
 
6
    it under the terms of the GNU General Public License version 2.0, as published by
 
7
    the Free Software Foundation.
 
8
    This program is distributed in the hope that it will be useful,
 
9
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
11
This license can be found at:
 
12
http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 
13
*/
5
14
 
6
15
#include <cstdio>
7
 
#include <cassert>
8
16
#include <cwchar>
 
17
#define WIN32_LEAN_AND_MEAN 
9
18
#include <windows.h>
10
19
#include <objbase.h>
11
 
#include "ia2/ia2.h"
 
20
#include <ia2.h>
 
21
#include "nvdaControllerInternal.h"
 
22
#include "log.h"
12
23
#include "nvdaHelperRemote.h"
 
24
#include "dllmain.h"
13
25
#include "IA2Support.h"
14
26
 
15
27
typedef ULONG(*LPFNDLLCANUNLOADNOW)();
27
39
        IID_IAccessibleImage,
28
40
        IID_IAccessibleRelation,
29
41
        IID_IAccessibleTable,
 
42
        IID_IAccessibleTable2,
 
43
        IID_IAccessibleTableCell,
30
44
        IID_IAccessibleText,
31
45
        IID_IAccessibleValue,
32
46
};
36
50
#define IAccessible2ProxyIID IID_IAccessible2
37
51
 
38
52
IID _ia2PSClsidBackups[ARRAYSIZE(ia2Iids)]={0};
39
 
BOOL isIA2Installed=FALSE;
 
53
bool isIA2Installed=FALSE;
40
54
HINSTANCE IA2DllHandle=0;
41
55
DWORD IA2RegCooky=0;
42
 
BOOL isIA2Initialized=FALSE;
 
56
HANDLE IA2UIThreadHandle=NULL;
 
57
DWORD IA2UIThreadID=0;
 
58
HANDLE IA2UIThreadUninstalledEvent=NULL;
 
59
UINT wm_uninstallIA2Support=0;
 
60
bool isIA2Initialized=FALSE;
43
61
 
44
 
BOOL installIA2Support() {
 
62
bool installIA2Support() {
45
63
        LPFNGETCLASSOBJECT IA2Dll_DllGetClassObject;
46
64
        int i;
47
65
        int res;
48
 
        if(isIA2Installed) return TRUE;
 
66
        if(isIA2Installed) return FALSE;
49
67
        if((IA2DllHandle=CoLoadLibrary(IA2DllPath,FALSE))==NULL) {
50
 
                fprintf(stderr,"Error loading IAccessible2 proxy dll\n");
 
68
                LOG_ERROR(L"CoLoadLibrary failed");
51
69
                return FALSE;
52
70
        }
53
71
        IA2Dll_DllGetClassObject=(LPFNGETCLASSOBJECT)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllGetClassObject");
54
 
        assert(IA2Dll_DllGetClassObject); //IAccessible2 proxy dll must have this function
 
72
        nhAssert(IA2Dll_DllGetClassObject); //IAccessible2 proxy dll must have this function
55
73
        IUnknown* ia2ClassObjPunk=NULL;
56
74
        if((res=IA2Dll_DllGetClassObject(IAccessible2ProxyIID,IID_IUnknown,(LPVOID*)&ia2ClassObjPunk))!=S_OK) {
57
 
                fprintf(stderr,"Error calling DllGetClassObject, code %d\n",res);
 
75
                LOG_ERROR(L"Error calling DllGetClassObject, code "<<res);
58
76
                CoFreeLibrary(IA2DllHandle);
59
77
                IA2DllHandle=0;
60
78
                return FALSE;
61
79
        }
62
80
        if((res=CoRegisterClassObject(IAccessible2ProxyIID,ia2ClassObjPunk,CLSCTX_INPROC_SERVER,REGCLS_MULTIPLEUSE,(LPDWORD)&IA2RegCooky))!=S_OK) {
63
 
                fprintf(stderr,"Error registering class object, code %d\n",res);
 
81
                LOG_DEBUGWARNING(L"Error registering class object, code "<<res);
64
82
                ia2ClassObjPunk->Release();
65
83
                CoFreeLibrary(IA2DllHandle);
66
84
                IA2DllHandle=0;
67
85
                return FALSE;
68
86
        }
69
87
        ia2ClassObjPunk->Release();
70
 
        for(i=0;i<ARRAYSIZE(ia2Iids);i++) {
 
88
        for(i=0;i<ARRAYSIZE(ia2Iids);++i) {
71
89
                CoGetPSClsid(ia2Iids[i],&(_ia2PSClsidBackups[i]));
72
90
                CoRegisterPSClsid(ia2Iids[i],IAccessible2ProxyIID);
73
91
        }
75
93
        return TRUE;
76
94
}
77
95
 
78
 
BOOL uninstallIA2Support() {
 
96
bool uninstallIA2Support() {
79
97
        int i;
80
98
        LPFNDLLCANUNLOADNOW IA2Dll_DllCanUnloadNow;
81
 
        if(isIA2Installed) {
82
 
        for(i=0;i<ARRAYSIZE(ia2Iids);i++) {
83
 
                        CoRegisterPSClsid(ia2Iids[i],_ia2PSClsidBackups[i]);
84
 
                }
85
 
                CoRevokeClassObject(IA2RegCooky);
86
 
                IA2Dll_DllCanUnloadNow=(LPFNDLLCANUNLOADNOW)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllCanUnloadNow");
87
 
                assert(IA2Dll_DllCanUnloadNow); //IAccessible2 proxy dll must have this function
88
 
                if(IA2Dll_DllCanUnloadNow()==S_OK) {
89
 
                        CoFreeLibrary(IA2DllHandle);
90
 
                }
91
 
                IA2DllHandle=0;
92
 
                isIA2Installed=FALSE;
93
 
        }
 
99
        if(!isIA2Installed)
 
100
                return FALSE;
 
101
        for(i=0;i<ARRAYSIZE(ia2Iids);++i) {
 
102
                CoRegisterPSClsid(ia2Iids[i],_ia2PSClsidBackups[i]);
 
103
        }
 
104
        CoRevokeClassObject(IA2RegCooky);
 
105
        IA2Dll_DllCanUnloadNow=(LPFNDLLCANUNLOADNOW)GetProcAddress(static_cast<HMODULE>(IA2DllHandle),"DllCanUnloadNow");
 
106
        nhAssert(IA2Dll_DllCanUnloadNow); //IAccessible2 proxy dll must have this function
 
107
        if(IA2Dll_DllCanUnloadNow()==S_OK) {
 
108
                CoFreeLibrary(IA2DllHandle);
 
109
        }
 
110
        IA2DllHandle=0;
 
111
        isIA2Installed=FALSE;
94
112
        return TRUE;
95
113
}
96
114
 
97
 
BOOL IA2Support_initialize() {
98
 
        assert(!isIA2Initialized);
 
115
bool IA2Support_initialize() {
 
116
        nhAssert(!isIA2Initialized);
99
117
        wsprintf(IA2DllPath,L"%s\\IAccessible2Proxy.dll",dllDirectory);
100
118
        isIA2Initialized=TRUE;
101
 
        installIA2Support();
102
 
        return TRUE;
103
 
}
104
 
 
105
 
BOOL IA2Support_terminate() {
106
 
        assert(isIA2Initialized);
107
 
        uninstallIA2Support();
108
 
        return TRUE;
 
119
        return TRUE;
 
120
}
 
121
 
 
122
void CALLBACK IA2Support_winEventProcHook(HWINEVENTHOOK hookID, DWORD eventID, HWND hwnd, long objectID, long childID, DWORD threadID, DWORD time) { 
 
123
        if (eventID != EVENT_SYSTEM_FOREGROUND && eventID != EVENT_OBJECT_FOCUS)
 
124
                return;
 
125
        if (installIA2Support()) {
 
126
                IA2UIThreadHandle=OpenThread(SYNCHRONIZE,false,threadID);
 
127
                IA2UIThreadID=threadID;
 
128
                // IA2 support successfully installed, so this hook isn't needed anymore.
 
129
                unregisterWinEventHook(IA2Support_winEventProcHook);
 
130
        }
 
131
}
 
132
 
 
133
LRESULT CALLBACK IA2Support_uninstallerHook(int code, WPARAM wParam, LPARAM lParam) {
 
134
        MSG* pmsg=(MSG*)lParam;
 
135
        if(pmsg->message==wm_uninstallIA2Support) {
 
136
                uninstallIA2Support();
 
137
                SetEvent(IA2UIThreadUninstalledEvent);
 
138
        }
 
139
        return 0;
109
140
}
110
141
 
111
142
void IA2Support_inProcess_initialize() {
112
 
        installIA2Support();
 
143
        if (isIA2Installed)
 
144
                return;
 
145
        // Try to install IA2 support on focus/foreground changes.
 
146
        // This hook will be unregistered by the callback once IA2 support is successfully installed.
 
147
        registerWinEventHook(IA2Support_winEventProcHook);
113
148
}
114
149
 
115
150
void IA2Support_inProcess_terminate() {
116
 
        uninstallIA2Support();
 
151
        // This will do nothing if the hook isn't registered.
 
152
        unregisterWinEventHook(IA2Support_winEventProcHook);
 
153
        if(!isIA2Installed||!IA2UIThreadHandle) {
 
154
                return;
 
155
        }
 
156
        //Check if the UI thread is still alive, if not there's nothing for us to do
 
157
        if(WaitForSingleObject(IA2UIThreadHandle,0)==0) {
 
158
                return;
 
159
        }
 
160
        //Instruct the UI thread to uninstall IA2
 
161
        IA2UIThreadUninstalledEvent=CreateEvent(NULL,true,false,NULL);
 
162
        registerWindowsHook(WH_GETMESSAGE,IA2Support_uninstallerHook);
 
163
        wm_uninstallIA2Support=RegisterWindowMessage(L"wm_uninstallIA2Support");
 
164
        PostThreadMessage(IA2UIThreadID,wm_uninstallIA2Support,0,0);
 
165
        HANDLE waitHandles[2]={IA2UIThreadUninstalledEvent,IA2UIThreadHandle};
 
166
        int res=WaitForMultipleObjects(2,waitHandles,false,10000);
 
167
        if(res!=WAIT_OBJECT_0&&res!=WAIT_OBJECT_0+1) {
 
168
                LOG_DEBUGWARNING(L"WaitForMultipleObjects returned "<<res);
 
169
        }
 
170
        unregisterWindowsHook(WH_GETMESSAGE,IA2Support_uninstallerHook);
 
171
        CloseHandle(IA2UIThreadUninstalledEvent);
 
172
        CloseHandle(IA2UIThreadHandle);
117
173
}