#define UNICODE #include #include #include using namespace std; #define DLLEXPORT extern "C" __declspec(dllexport) #pragma data_seg(".shared") static HHOOK messageHookID=0; static HWND hookedWindow=NULL; #pragma data_seg() #pragma comment(linker, "/section:.shared,rws") HINSTANCE moduleHandle=NULL; int wm=0; #pragma comment(linker,"/entry:_DllMainCRTStartup@12") BOOL DllMain(HINSTANCE hModule,DWORD reason,LPVOID lpReserved) { if(reason==DLL_PROCESS_ATTACH) { Beep(100,100); moduleHandle=hModule; wm=RegisterWindowMessage(L"wm_MSAAWalker_message"); } return TRUE; } VARIANT makeChildIDVariant(int childID) { VARIANT v; v.vt=VT_I4; v.lVal=childID; return v; } int walkMSAATree(IAccessible* pacc,VARIANT varChild,int level, FILE* logFile) { int count=1; wstring infoString; BSTR s; VARIANT varRole; wchar_t roleText[100]; long numChildren; VARIANT* children; IAccessible* paccChild; if((pacc->get_accName(varChild,&s)==S_OK)&&(s>0)) { infoString.append(s); SysFreeString(s); infoString.append(L" "); } if(pacc->get_accRole(varChild,&varRole)==S_OK) { if(varRole.vt==VT_I4) { GetRoleText(varRole.lVal,roleText,100); infoString.append(roleText); infoString.append(L" "); } else if(varRole.vt==VT_BSTR) { infoString.append(varRole.bstrVal); infoString.append(L" "); } VariantClear(&varRole); } if((pacc->get_accValue(varChild,&s)==S_OK)&&(s>0)) { infoString.append(s); SysFreeString(s); infoString.append(L" "); } int bufLen=WideCharToMultiByte(28591,0,infoString.c_str(),-1,NULL,0,NULL,NULL); char* buf=(char*)malloc(sizeof(char)*bufLen); WideCharToMultiByte(28591,0,infoString.c_str(),-1,buf,bufLen,NULL,NULL); fprintf(logFile,"Visit: %s\n",buf); free(buf); if((varChild.vt==VT_I4)&&(varChild.lVal>0)) { return count; } pacc->get_accChildCount(&numChildren); if(numChildren<1) { return count; } children=(VARIANT*)malloc(sizeof(VARIANT)*numChildren); if(AccessibleChildren(pacc,0,numChildren,children,&numChildren)==S_OK) { level+=1; fprintf(logFile,"Down: level %d, contains %d items\n",level,numChildren); for(int i=0;i0) { fprintf(logFile,"Next\n"); } if(children[i].vt==VT_DISPATCH) { if(children[i].pdispVal->QueryInterface(IID_IAccessible,(void**)(&paccChild))==S_OK) { children[i].pdispVal->Release(); count+=walkIAccessibles(paccChild,makeChildIDVariant(0),level,logFile); paccChild->Release(); } VariantClear(&(children[i])); } else if((children[i].vt==VT_I4)&&(children[i].lVal>0)) { count+=walkIAccessibles(pacc,children[i],level,logFile); } VariantClear(&(children[i])); } level-=1; fprintf(logFile,"Up: level %d\n",level); } free(children); return count; } DLLEXPORT void startWalkMSAATree(HWND hwnd, long objectID, long childID,char* logFileName) { IAccessible* pacc; VARIANT varChild; FILE* logFile; int count=0; Beep(440,250); CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); logFile = fopen(logFileName,"w"); fprintf(logFile,"walkMSAATree: window %d, object ID %d, child ID %d\n",hwnd,objectID,childID); if(AccessibleObjectFromEvent(hwnd,objectID,childID,&pacc,&varChild)!=S_OK) { fprintf(logFile,"walkMSAATree: error in AccessibleObjectFromEvent"); Beep(220,250); return; } count=walkMSAATree(pacc,varChild,0,logFile); pacc->Release(); fprintf(logFile,"Total count: %d",count); fclose(logFile); Beep(880,250); } LRESULT CALLBACK hook_message(int code, WPARAM wParam,LPARAM lParam) { CWPSTRUCT* pmsg=(CWPSTRUCT*)lParam; if((code==HC_ACTION)&&(pmsg->hwnd==hookedWindow)&&(pmsg->message==wm)) { startWalkMSAATree(pmsg->hwnd,pmsg->wParam,pmsg->lParam,"c:\\users\\mick\\MSAAWalker_inProcess.txt"); return 1; } else { return CallNextHookEx(messageHookID,code,wParam,lParam); } } DLLEXPORT void inProcessStartWalkMSAATree(HWND hwnd, long objectID, long childID) { DWORD processID, threadID; FILE* logFile=fopen("debug_inprocessWalkMSAATree.txt","w"); fprintf(logFile,"hwnd: %d, object ID: %d, child ID: %d\n",hwnd,objectID,childID); threadID=GetWindowThreadProcessId(hwnd,&processID); fprintf(logFile,"threadID: %d, process ID: %d\n",threadID,processID); messageHookID=SetWindowsHookEx(WH_CALLWNDPROC,(HOOKPROC)hook_message,moduleHandle,threadID); fprintf(logFile,"message hook ID: %d\n",messageHookID); hookedWindow=hwnd; fprintf(logFile,"hooked window: %d, window message: %d\n",hookedWindow,wm); SendMessage(hwnd,wm,objectID,childID); UnhookWindowsHookEx(messageHookID); fclose(logFile); } DLLEXPORT void outOfProcessStartWalkMSAATree(HWND hwnd, long objectID, long childID) { startWalkMSAATree(hwnd, objectID, childID,"c:\\users\\mick\\MSAAWalker_outOfProcess.txt"); }