user32/tests: Test pending redraw state with owner-drawn list box.
[wine.git] / dlls / rpcrt4 / cpsf.c
blob006e6bce62ffc83d09e9a58a44c994a1ba5c56c2
1 /*
2 * COM proxy/stub factory (CStdPSFactory) implementation
4 * Copyright 2001 Ove Kåven, TransGaming Technologies
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 #include <stdarg.h>
22 #include <stdio.h>
23 #include <string.h>
25 #define COBJMACROS
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winerror.h"
30 #include "winreg.h"
32 #include "objbase.h"
34 #include "rpcproxy.h"
36 #include "wine/debug.h"
38 #include "cpsf.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ole);
42 static void format_clsid( WCHAR *buffer, const CLSID *clsid )
44 swprintf( buffer, 39, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
45 clsid->Data1, clsid->Data2, clsid->Data3,
46 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
47 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
51 static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex)
53 while (*pProxyFileList) {
54 if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) {
55 *pProxyInfo = *pProxyFileList;
56 TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex);
57 return TRUE;
59 pProxyFileList++;
61 TRACE("not found\n");
62 return FALSE;
65 static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface,
66 REFIID riid,
67 LPVOID *obj)
69 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
70 TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj);
71 if (IsEqualGUID(&IID_IUnknown,riid) ||
72 IsEqualGUID(&IID_IPSFactoryBuffer,riid)) {
73 *obj = This;
74 InterlockedIncrement( &This->RefCount );
75 return S_OK;
77 return E_NOINTERFACE;
80 static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface)
82 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
83 TRACE("(%p)->AddRef()\n",iface);
84 return InterlockedIncrement( &This->RefCount );
87 static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface)
89 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
90 TRACE("(%p)->Release()\n",iface);
91 return InterlockedDecrement( &This->RefCount );
94 static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface,
95 LPUNKNOWN pUnkOuter,
96 REFIID riid,
97 LPRPCPROXYBUFFER *ppProxy,
98 LPVOID *ppv)
100 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
101 const ProxyFileInfo *ProxyInfo;
102 int Index;
103 TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter,
104 debugstr_guid(riid),ppProxy,ppv);
105 if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
106 return E_NOINTERFACE;
107 return StdProxy_Construct(riid, pUnkOuter, ProxyInfo, Index, iface, ppProxy, ppv);
110 static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,
111 REFIID riid,
112 LPUNKNOWN pUnkServer,
113 LPRPCSTUBBUFFER *ppStub)
115 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
116 const ProxyFileInfo *ProxyInfo;
117 int Index;
118 TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid),
119 pUnkServer,ppStub);
120 if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
121 return E_NOINTERFACE;
123 if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index])
124 return CStdStubBuffer_Delegating_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
125 ProxyInfo->pStubVtblList[Index], ProxyInfo->pDelegatedIIDs[Index],
126 iface, ppStub);
128 return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
129 ProxyInfo->pStubVtblList[Index], iface, ppStub);
132 static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl =
134 CStdPSFactory_QueryInterface,
135 CStdPSFactory_AddRef,
136 CStdPSFactory_Release,
137 CStdPSFactory_CreateProxy,
138 CStdPSFactory_CreateStub
142 static void init_psfactory( CStdPSFactoryBuffer *psfac, const ProxyFileInfo **file_list )
144 DWORD i, j, k;
146 psfac->lpVtbl = &CStdPSFactory_Vtbl;
147 psfac->RefCount = 0;
148 psfac->pProxyFileList = file_list;
149 for (i = 0; file_list[i]; i++)
151 const PCInterfaceProxyVtblList *proxies = file_list[i]->pProxyVtblList;
152 const PCInterfaceStubVtblList *stubs = file_list[i]->pStubVtblList;
154 for (j = 0; j < file_list[i]->TableSize; j++)
156 /* FIXME: i think that different vtables should be copied for
157 * async interfaces */
158 void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl;
159 void **pRpcStubVtbl = (void **)&stubs[j]->Vtbl;
161 if (file_list[i]->pDelegatedIIDs && file_list[i]->pDelegatedIIDs[j])
163 void **vtbl = proxies[j]->Vtbl;
164 if (file_list[i]->TableVersion > 1) vtbl++;
165 fill_delegated_proxy_table( (IUnknownVtbl *)vtbl, stubs[j]->header.DispatchTableCount );
166 pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl;
169 for (k = 0; k < sizeof(IRpcStubBufferVtbl)/sizeof(void *); k++)
170 if (!pRpcStubVtbl[k]) pRpcStubVtbl[k] = pSrcRpcStubVtbl[k];
176 /***********************************************************************
177 * NdrDllGetClassObject [RPCRT4.@]
179 HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
180 const ProxyFileInfo **pProxyFileList,
181 const CLSID *pclsid,
182 CStdPSFactoryBuffer *pPSFactoryBuffer)
184 TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid),
185 debugstr_guid(iid), ppv, pProxyFileList, debugstr_guid(pclsid),
186 pPSFactoryBuffer);
188 *ppv = NULL;
189 if (!pPSFactoryBuffer->lpVtbl) init_psfactory( pPSFactoryBuffer, pProxyFileList );
191 if (pclsid && IsEqualGUID(rclsid, pclsid))
192 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
193 else {
194 const ProxyFileInfo *info;
195 int index;
196 /* otherwise, the dll may be using the iid as the clsid, so
197 * search for it in the proxy file list */
198 if (FindProxyInfo(pProxyFileList, rclsid, &info, &index))
199 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
201 WARN("class %s not available\n", debugstr_guid(rclsid));
202 return CLASS_E_CLASSNOTAVAILABLE;
206 /***********************************************************************
207 * NdrDllCanUnloadNow [RPCRT4.@]
209 HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
211 return pPSFactoryBuffer->RefCount != 0 ? S_FALSE : S_OK;
215 /***********************************************************************
216 * NdrDllRegisterProxy [RPCRT4.@]
218 HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,
219 const ProxyFileInfo **pProxyFileList,
220 const CLSID *pclsid)
222 WCHAR clsid[39], keyname[50], module[MAX_PATH];
223 HKEY key, subkey;
224 DWORD len;
226 TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
228 if (!hDll) return E_HANDLE;
229 if (!*pProxyFileList) return E_NOINTERFACE;
231 if (pclsid)
232 format_clsid( clsid, pclsid );
233 else if ((*pProxyFileList)->TableSize > 0)
234 format_clsid( clsid,(*pProxyFileList)->pStubVtblList[0]->header.piid);
235 else
236 return E_NOINTERFACE;
238 /* register interfaces to point to clsid */
239 while (*pProxyFileList) {
240 unsigned u;
241 for (u=0; u<(*pProxyFileList)->TableSize; u++) {
242 CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
243 PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
245 TRACE("registering %s %s => %s\n",
246 debugstr_a(name), debugstr_guid(proxy->header.piid), debugstr_w(clsid));
248 lstrcpyW( keyname, L"Interface\\" );
249 format_clsid( keyname + lstrlenW(keyname), proxy->header.piid );
250 if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
251 WCHAR num[10];
252 if (name)
253 RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE *)name, strlen(name)+1);
254 RegSetValueW( key, L"ProxyStubClsid32", REG_SZ, clsid, 0 );
255 swprintf(num, ARRAY_SIZE(num), L"%u", proxy->header.DispatchTableCount);
256 RegSetValueW( key, L"NumMethods", REG_SZ, num, 0 );
257 RegCloseKey(key);
260 pProxyFileList++;
263 /* register clsid to point to module */
264 lstrcpyW( keyname, L"CLSID\\" );
265 lstrcatW( keyname, clsid );
266 len = GetModuleFileNameW(hDll, module, ARRAY_SIZE(module));
267 if (len && len < sizeof(module)) {
268 TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module));
269 if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
270 RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)L"PSFactoryBuffer", sizeof(L"PSFactoryBuffer"));
271 if (RegCreateKeyW(key, L"InProcServer32", &subkey) == ERROR_SUCCESS) {
272 RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (lstrlenW(module)+1)*sizeof(WCHAR));
273 RegSetValueExW(subkey, L"ThreadingModel", 0, REG_SZ, (const BYTE *)L"Both", sizeof(L"Both"));
274 RegCloseKey(subkey);
276 RegCloseKey(key);
280 return S_OK;
283 /***********************************************************************
284 * NdrDllUnregisterProxy [RPCRT4.@]
286 HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
287 const ProxyFileInfo **pProxyFileList,
288 const CLSID *pclsid)
290 WCHAR keyname[50];
291 WCHAR clsid[39];
293 TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
294 if (pclsid)
295 format_clsid( clsid, pclsid );
296 else if ((*pProxyFileList)->TableSize > 0)
297 format_clsid( clsid,(*pProxyFileList)->pStubVtblList[0]->header.piid);
298 else
299 return E_NOINTERFACE;
301 /* unregister interfaces */
302 while (*pProxyFileList) {
303 unsigned u;
304 for (u=0; u<(*pProxyFileList)->TableSize; u++) {
305 CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
306 PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
308 TRACE("unregistering %s %s\n", debugstr_a(name), debugstr_guid(proxy->header.piid));
310 lstrcpyW( keyname, L"Interface\\" );
311 format_clsid( keyname + lstrlenW(keyname), proxy->header.piid );
312 RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname);
314 pProxyFileList++;
317 /* unregister clsid */
318 lstrcpyW( keyname, L"CLSID\\" );
319 lstrcatW( keyname, clsid );
320 RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname);
322 return S_OK;