include: Add transact.idl to oledb.idl.
[wine.git] / dlls / oleacc / main.c
blob3ce616ae0c1117fee19da954941c6af7cd380969
1 /*
2 * Implementation of the OLEACC dll
4 * Copyright 2003 Mike McCormack for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "initguid.h"
24 #include "oleacc_private.h"
25 #include "resource.h"
27 #include "wine/debug.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(oleacc);
31 static const WCHAR lresult_atom_prefix[] = {'w','i','n','e','_','o','l','e','a','c','c',':'};
33 extern HRESULT WINAPI OLEACC_DllGetClassObject(REFCLSID, REFIID, void**) DECLSPEC_HIDDEN;
34 extern BOOL WINAPI OLEACC_DllMain(HINSTANCE, DWORD, void*) DECLSPEC_HIDDEN;
35 extern HRESULT WINAPI OLEACC_DllRegisterServer(void) DECLSPEC_HIDDEN;
36 extern HRESULT WINAPI OLEACC_DllUnregisterServer(void) DECLSPEC_HIDDEN;
38 static HINSTANCE oleacc_handle = 0;
40 int convert_child_id(VARIANT *v)
42 switch(V_VT(v)) {
43 case VT_I4:
44 return V_I4(v);
45 default:
46 FIXME("unhandled child ID variant type: %d\n", V_VT(v));
47 return -1;
51 const struct win_class_data* find_class_data(HWND hwnd, const struct win_class_data *classes)
53 WCHAR class_name[64];
54 int i, idx;
56 if(!RealGetWindowClassW(hwnd, class_name, ARRAY_SIZE(class_name)))
57 return NULL;
58 TRACE("got window class: %s\n", debugstr_w(class_name));
60 for(i=0; classes[i].name; i++) {
61 if(!wcsicmp(class_name, classes[i].name)) {
62 if(classes[i].stub)
63 FIXME("unhandled window class: %s\n", debugstr_w(class_name));
64 return &classes[i];
68 idx = SendMessageW(hwnd, WM_GETOBJECT, 0, OBJID_QUERYCLASSNAMEIDX);
69 if(idx) {
70 for(i=0; classes[i].name; i++) {
71 if(idx == classes[i].idx) {
72 if(classes[i].stub)
73 FIXME("unhandled window class: %s\n", debugstr_w(class_name));
74 return &classes[i];
78 WARN("unhandled class name idx: %x\n", idx);
81 return NULL;
84 HRESULT WINAPI CreateStdAccessibleObject( HWND hwnd, LONG idObject,
85 REFIID riidInterface, void** ppvObject )
87 TRACE("%p %d %s %p\n", hwnd, idObject,
88 debugstr_guid( riidInterface ), ppvObject );
90 switch(idObject) {
91 case OBJID_CLIENT:
92 return create_client_object(hwnd, riidInterface, ppvObject);
93 case OBJID_WINDOW:
94 return create_window_object(hwnd, riidInterface, ppvObject);
95 default:
96 FIXME("unhandled object id: %d\n", idObject);
97 return E_NOTIMPL;
101 HRESULT WINAPI ObjectFromLresult( LRESULT result, REFIID riid, WPARAM wParam, void **ppObject )
103 WCHAR atom_str[ARRAY_SIZE(lresult_atom_prefix)+3*8+3];
104 HANDLE server_proc, server_mapping, mapping;
105 DWORD proc_id, size;
106 IStream *stream;
107 HGLOBAL data;
108 void *view;
109 HRESULT hr;
110 WCHAR *p;
112 TRACE("%ld %s %ld %p\n", result, debugstr_guid(riid), wParam, ppObject );
114 if(wParam)
115 FIXME("unsupported wParam = %lx\n", wParam);
117 if(!ppObject)
118 return E_INVALIDARG;
119 *ppObject = NULL;
121 if(result != (ATOM)result)
122 return E_FAIL;
124 if(!GlobalGetAtomNameW(result, atom_str, ARRAY_SIZE(atom_str)))
125 return E_FAIL;
126 if(memcmp(atom_str, lresult_atom_prefix, sizeof(lresult_atom_prefix)))
127 return E_FAIL;
128 p = atom_str + ARRAY_SIZE(lresult_atom_prefix);
129 proc_id = wcstoul(p, &p, 16);
130 if(*p != ':')
131 return E_FAIL;
132 server_mapping = ULongToHandle( wcstoul(p+1, &p, 16) );
133 if(*p != ':')
134 return E_FAIL;
135 size = wcstoul(p+1, &p, 16);
136 if(*p != 0)
137 return E_FAIL;
139 server_proc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, proc_id);
140 if(!server_proc)
141 return E_FAIL;
143 if(!DuplicateHandle(server_proc, server_mapping, GetCurrentProcess(), &mapping,
144 0, FALSE, DUPLICATE_CLOSE_SOURCE|DUPLICATE_SAME_ACCESS))
145 return E_FAIL;
146 CloseHandle(server_proc);
147 GlobalDeleteAtom(result);
149 view = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
150 CloseHandle(mapping);
151 if(!view)
152 return E_FAIL;
154 data = GlobalAlloc(GMEM_FIXED, size);
155 if(!data) {
156 UnmapViewOfFile(view);
157 return E_OUTOFMEMORY;
159 memcpy(data, view, size);
160 UnmapViewOfFile(view);
162 hr = CreateStreamOnHGlobal(data, TRUE, &stream);
163 if(FAILED(hr)) {
164 GlobalFree(data);
165 return hr;
168 hr = CoUnmarshalInterface(stream, riid, ppObject);
169 IStream_Release(stream);
170 return hr;
173 LRESULT WINAPI LresultFromObject( REFIID riid, WPARAM wParam, LPUNKNOWN pAcc )
175 static const LARGE_INTEGER seek_zero = {{0}};
177 WCHAR atom_str[ARRAY_SIZE(lresult_atom_prefix)+3*8+3];
178 IStream *stream;
179 HANDLE mapping;
180 STATSTG stat;
181 HRESULT hr;
182 ATOM atom;
183 void *view;
185 TRACE("%s %ld %p\n", debugstr_guid(riid), wParam, pAcc);
187 if(wParam)
188 FIXME("unsupported wParam = %lx\n", wParam);
190 if(!pAcc)
191 return E_INVALIDARG;
193 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
194 if(FAILED(hr))
195 return hr;
197 hr = CoMarshalInterface(stream, riid, pAcc, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
198 if(FAILED(hr)) {
199 IStream_Release(stream);
200 return hr;
203 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
204 if(FAILED(hr)) {
205 IStream_Release(stream);
206 return hr;
209 hr = IStream_Stat(stream, &stat, STATFLAG_NONAME);
210 if(FAILED(hr)) {
211 CoReleaseMarshalData(stream);
212 IStream_Release(stream);
213 return hr;
214 }else if(stat.cbSize.u.HighPart) {
215 FIXME("stream size to big\n");
216 CoReleaseMarshalData(stream);
217 IStream_Release(stream);
218 return E_NOTIMPL;
221 mapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
222 stat.cbSize.u.HighPart, stat.cbSize.u.LowPart, NULL);
223 if(!mapping) {
224 CoReleaseMarshalData(stream);
225 IStream_Release(stream);
226 return hr;
229 view = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
230 if(!view) {
231 CloseHandle(mapping);
232 CoReleaseMarshalData(stream);
233 IStream_Release(stream);
234 return E_FAIL;
237 hr = IStream_Read(stream, view, stat.cbSize.u.LowPart, NULL);
238 UnmapViewOfFile(view);
239 if(FAILED(hr)) {
240 CloseHandle(mapping);
241 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
242 if(SUCCEEDED(hr))
243 CoReleaseMarshalData(stream);
244 IStream_Release(stream);
245 return hr;
249 memcpy(atom_str, lresult_atom_prefix, sizeof(lresult_atom_prefix));
250 swprintf(atom_str+ARRAY_SIZE(lresult_atom_prefix), 3*8 + 3, L"%08x:%08x:%08x", GetCurrentProcessId(),
251 HandleToUlong(mapping), stat.cbSize.u.LowPart);
252 atom = GlobalAddAtomW(atom_str);
253 if(!atom) {
254 CloseHandle(mapping);
255 hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL);
256 if(SUCCEEDED(hr))
257 CoReleaseMarshalData(stream);
258 IStream_Release(stream);
259 return E_FAIL;
262 IStream_Release(stream);
263 return atom;
266 HRESULT WINAPI AccessibleObjectFromPoint( POINT ptScreen, IAccessible** ppacc, VARIANT* pvarChild )
268 FIXME("{%d,%d} %p %p: stub\n", ptScreen.x, ptScreen.y, ppacc, pvarChild );
269 return E_NOTIMPL;
272 static void variant_init_i4( VARIANT *v, int val )
274 V_VT(v) = VT_I4;
275 V_I4(v) = val;
278 HRESULT WINAPI AccessibleObjectFromEvent( HWND hwnd, DWORD object_id, DWORD child_id,
279 IAccessible **acc_out, VARIANT *child_id_out )
281 VARIANT child_id_variant;
282 IAccessible *acc = NULL;
283 IDispatch *child = NULL;
284 HRESULT hr;
286 TRACE("%p %d %d %p %p\n", hwnd, object_id, child_id, acc_out, child_id_out);
288 if (!acc_out)
289 return E_INVALIDARG;
290 *acc_out = NULL;
291 VariantInit(child_id_out);
293 hr = AccessibleObjectFromWindow(hwnd, object_id, &IID_IAccessible, (void **)&acc);
294 if (FAILED(hr))
295 return hr;
297 variant_init_i4(&child_id_variant, child_id);
298 hr = IAccessible_get_accChild(acc, child_id_variant, &child);
299 if (FAILED(hr))
300 TRACE("get_accChild failed with %#x!\n", hr);
302 if (SUCCEEDED(hr) && child)
304 IAccessible_Release(acc);
305 hr = IDispatch_QueryInterface(child, &IID_IAccessible, (void **)&acc);
306 IDispatch_Release(child);
307 if (FAILED(hr))
308 return hr;
310 variant_init_i4(&child_id_variant, CHILDID_SELF);
313 *acc_out = acc;
314 *child_id_out = child_id_variant;
316 return S_OK;
319 HRESULT WINAPI AccessibleObjectFromWindow( HWND hwnd, DWORD dwObjectID,
320 REFIID riid, void** ppvObject )
322 TRACE("%p %d %s %p\n", hwnd, dwObjectID,
323 debugstr_guid( riid ), ppvObject );
325 if(!ppvObject)
326 return E_INVALIDARG;
327 *ppvObject = NULL;
329 if(IsWindow(hwnd)) {
330 LRESULT lres;
332 lres = SendMessageW(hwnd, WM_GETOBJECT, 0xffffffff, dwObjectID);
333 if(FAILED(lres))
334 return lres;
335 else if(lres)
336 return ObjectFromLresult(lres, riid, 0, ppvObject);
339 return CreateStdAccessibleObject(hwnd, dwObjectID, riid, ppvObject);
342 HRESULT WINAPI WindowFromAccessibleObject(IAccessible *acc, HWND *phwnd)
344 IDispatch *parent;
345 IOleWindow *ow;
346 HRESULT hres;
348 TRACE("%p %p\n", acc, phwnd);
350 IAccessible_AddRef(acc);
351 while(1) {
352 hres = IAccessible_QueryInterface(acc, &IID_IOleWindow, (void**)&ow);
353 if(SUCCEEDED(hres)) {
354 hres = IOleWindow_GetWindow(ow, phwnd);
355 IOleWindow_Release(ow);
356 IAccessible_Release(acc);
357 return hres;
360 hres = IAccessible_get_accParent(acc, &parent);
361 IAccessible_Release(acc);
362 if(FAILED(hres))
363 return hres;
364 if(hres!=S_OK || !parent) {
365 *phwnd = NULL;
366 return hres;
369 hres = IDispatch_QueryInterface(parent, &IID_IAccessible, (void**)&acc);
370 IDispatch_Release(parent);
371 if(FAILED(hres))
372 return hres;
376 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
377 LPVOID lpvReserved)
379 TRACE("%p, %d, %p\n", hinstDLL, fdwReason, lpvReserved);
381 switch (fdwReason)
383 case DLL_PROCESS_ATTACH:
384 oleacc_handle = hinstDLL;
385 DisableThreadLibraryCalls(hinstDLL);
386 break;
389 return OLEACC_DllMain(hinstDLL, fdwReason, lpvReserved);
392 HRESULT WINAPI DllRegisterServer(void)
394 return OLEACC_DllRegisterServer();
397 HRESULT WINAPI DllUnregisterServer(void)
399 return OLEACC_DllUnregisterServer();
402 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, void **ppv)
404 if(IsEqualGUID(&CLSID_CAccPropServices, rclsid)) {
405 TRACE("(CLSID_CAccPropServices %s %p)\n", debugstr_guid(iid), ppv);
406 return get_accpropservices_factory(iid, ppv);
409 if(IsEqualGUID(&CLSID_PSFactoryBuffer, rclsid)) {
410 TRACE("(CLSID_PSFactoryBuffer %s %p)\n", debugstr_guid(iid), ppv);
411 return OLEACC_DllGetClassObject(rclsid, iid, ppv);
414 FIXME("%s %s %p: stub\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
415 return E_NOTIMPL;
418 void WINAPI GetOleaccVersionInfo(DWORD* pVersion, DWORD* pBuild)
420 *pVersion = MAKELONG(0,7); /* Windows 7 version of oleacc: 7.0.0.0 */
421 *pBuild = MAKELONG(0,0);
424 HANDLE WINAPI GetProcessHandleFromHwnd(HWND hwnd)
426 DWORD proc_id;
428 TRACE("%p\n", hwnd);
430 if(!GetWindowThreadProcessId(hwnd, &proc_id))
431 return NULL;
432 return OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION |
433 PROCESS_VM_READ | PROCESS_VM_WRITE | SYNCHRONIZE, TRUE, proc_id);
436 UINT WINAPI GetRoleTextW(DWORD role, LPWSTR lpRole, UINT rolemax)
438 INT ret;
439 WCHAR *resptr;
441 TRACE("%u %p %u\n", role, lpRole, rolemax);
443 /* return role text length */
444 if(!lpRole)
445 return LoadStringW(oleacc_handle, role, (LPWSTR)&resptr, 0);
447 ret = LoadStringW(oleacc_handle, role, lpRole, rolemax);
448 if(!(ret > 0)){
449 if(rolemax > 0) lpRole[0] = '\0';
450 return 0;
453 return ret;
456 UINT WINAPI GetRoleTextA(DWORD role, LPSTR lpRole, UINT rolemax)
458 UINT length;
459 WCHAR *roletextW;
461 TRACE("%u %p %u\n", role, lpRole, rolemax);
463 if(lpRole && !rolemax)
464 return 0;
466 length = GetRoleTextW(role, NULL, 0);
467 if(!length) {
468 if(lpRole && rolemax)
469 lpRole[0] = 0;
470 return 0;
473 roletextW = HeapAlloc(GetProcessHeap(), 0, (length + 1)*sizeof(WCHAR));
474 if(!roletextW)
475 return 0;
477 GetRoleTextW(role, roletextW, length + 1);
479 length = WideCharToMultiByte( CP_ACP, 0, roletextW, -1, NULL, 0, NULL, NULL );
481 if(!lpRole){
482 HeapFree(GetProcessHeap(), 0, roletextW);
483 return length - 1;
486 if(rolemax < length) {
487 HeapFree(GetProcessHeap(), 0, roletextW);
488 lpRole[0] = 0;
489 return 0;
492 WideCharToMultiByte( CP_ACP, 0, roletextW, -1, lpRole, rolemax, NULL, NULL );
494 if(rolemax < length){
495 lpRole[rolemax-1] = '\0';
496 length = rolemax;
499 HeapFree(GetProcessHeap(), 0, roletextW);
501 return length - 1;
504 UINT WINAPI GetStateTextW(DWORD state_bit, WCHAR *state_str, UINT state_str_len)
506 DWORD state_id;
508 TRACE("%x %p %u\n", state_bit, state_str, state_str_len);
510 if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) {
511 if(state_str && state_str_len)
512 state_str[0] = 0;
513 return 0;
516 state_id = IDS_STATE_NORMAL;
517 while(state_bit) {
518 state_id++;
519 state_bit /= 2;
522 if(state_str) {
523 UINT ret = LoadStringW(oleacc_handle, state_id, state_str, state_str_len);
524 if(!ret && state_str_len)
525 state_str[0] = 0;
526 return ret;
527 }else {
528 WCHAR *tmp;
529 return LoadStringW(oleacc_handle, state_id, (WCHAR*)&tmp, 0);
534 UINT WINAPI GetStateTextA(DWORD state_bit, CHAR *state_str, UINT state_str_len)
536 DWORD state_id;
538 TRACE("%x %p %u\n", state_bit, state_str, state_str_len);
540 if(state_str && !state_str_len)
541 return 0;
543 if(state_bit & ~(STATE_SYSTEM_VALID | STATE_SYSTEM_HASPOPUP)) {
544 if(state_str && state_str_len)
545 state_str[0] = 0;
546 return 0;
549 state_id = IDS_STATE_NORMAL;
550 while(state_bit) {
551 state_id++;
552 state_bit /= 2;
555 if(state_str) {
556 UINT ret = LoadStringA(oleacc_handle, state_id, state_str, state_str_len);
557 if(!ret && state_str_len)
558 state_str[0] = 0;
559 return ret;
560 }else {
561 CHAR tmp[256];
562 return LoadStringA(oleacc_handle, state_id, tmp, sizeof(tmp));
566 HRESULT WINAPI AccessibleChildren(IAccessible *container,
567 LONG start, LONG count, VARIANT *children, LONG *children_cnt)
569 IEnumVARIANT *ev;
570 LONG i, child_no;
571 HRESULT hr;
573 TRACE("%p %d %d %p %p\n", container, start, count, children, children_cnt);
575 if(!container || !children || !children_cnt)
576 return E_INVALIDARG;
578 for(i=0; i<count; i++)
579 VariantInit(children+i);
581 hr = IAccessible_QueryInterface(container, &IID_IEnumVARIANT, (void**)&ev);
582 if(SUCCEEDED(hr)) {
583 hr = IEnumVARIANT_Reset(ev);
584 if(SUCCEEDED(hr))
585 hr = IEnumVARIANT_Skip(ev, start);
586 if(SUCCEEDED(hr))
587 hr = IEnumVARIANT_Next(ev, count, children, (ULONG*)children_cnt);
588 IEnumVARIANT_Release(ev);
589 return hr;
592 hr = IAccessible_get_accChildCount(container, &child_no);
593 if(FAILED(hr))
594 return hr;
596 for(i=0; i<count && start+i+1<=child_no; i++) {
597 IDispatch *disp;
599 V_VT(children+i) = VT_I4;
600 V_I4(children+i) = start+i+1;
602 hr = IAccessible_get_accChild(container, children[i], &disp);
603 if(SUCCEEDED(hr) && disp) {
604 V_VT(children+i) = VT_DISPATCH;
605 V_DISPATCH(children+i) = disp;
609 *children_cnt = i;
610 return i==count ? S_OK : S_FALSE;