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
22 #include "wine/port.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ole);
46 static void format_clsid( WCHAR *buffer, const CLSID *clsid )
48 static const WCHAR clsid_formatW[] = {'{','%','0','8','X','-','%','0','4','X','-','%','0','4','X','-',
49 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X',
50 '%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','}',0};
52 sprintfW( buffer, clsid_formatW, clsid->Data1, clsid->Data2, clsid->Data3,
53 clsid->Data4[0], clsid->Data4[1], clsid->Data4[2], clsid->Data4[3],
54 clsid->Data4[4], clsid->Data4[5], clsid->Data4[6], clsid->Data4[7] );
58 static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex)
60 while (*pProxyFileList) {
61 if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) {
62 *pProxyInfo = *pProxyFileList;
63 TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex);
72 static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface,
76 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
77 TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj);
78 if (IsEqualGUID(&IID_IUnknown,riid) ||
79 IsEqualGUID(&IID_IPSFactoryBuffer,riid)) {
81 InterlockedIncrement( &This->RefCount );
87 static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface)
89 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
90 TRACE("(%p)->AddRef()\n",iface);
91 return InterlockedIncrement( &This->RefCount );
94 static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface)
96 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
97 TRACE("(%p)->Release()\n",iface);
98 return InterlockedDecrement( &This->RefCount );
101 static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface,
104 LPRPCPROXYBUFFER *ppProxy,
107 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
108 const ProxyFileInfo *ProxyInfo;
110 TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter,
111 debugstr_guid(riid),ppProxy,ppv);
112 if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
113 return E_NOINTERFACE;
114 return StdProxy_Construct(riid, pUnkOuter, ProxyInfo, Index, iface, ppProxy, ppv);
117 static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,
119 LPUNKNOWN pUnkServer,
120 LPRPCSTUBBUFFER *ppStub)
122 CStdPSFactoryBuffer *This = (CStdPSFactoryBuffer *)iface;
123 const ProxyFileInfo *ProxyInfo;
125 TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid),
127 if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
128 return E_NOINTERFACE;
130 if(ProxyInfo->pDelegatedIIDs && ProxyInfo->pDelegatedIIDs[Index])
131 return CStdStubBuffer_Delegating_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
132 ProxyInfo->pStubVtblList[Index], ProxyInfo->pDelegatedIIDs[Index],
135 return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
136 ProxyInfo->pStubVtblList[Index], iface, ppStub);
139 static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl =
141 CStdPSFactory_QueryInterface,
142 CStdPSFactory_AddRef,
143 CStdPSFactory_Release,
144 CStdPSFactory_CreateProxy,
145 CStdPSFactory_CreateStub
148 /***********************************************************************
149 * NdrDllGetClassObject [RPCRT4.@]
151 HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
152 const ProxyFileInfo **pProxyFileList,
154 CStdPSFactoryBuffer *pPSFactoryBuffer)
156 TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid),
157 debugstr_guid(iid), ppv, pProxyFileList, debugstr_guid(pclsid),
161 if (!pPSFactoryBuffer->lpVtbl) {
162 const ProxyFileInfo **pProxyFileList2;
163 DWORD max_delegating_vtbl_size = 0;
164 pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl;
165 pPSFactoryBuffer->RefCount = 0;
166 pPSFactoryBuffer->pProxyFileList = pProxyFileList;
167 for (pProxyFileList2 = pProxyFileList; *pProxyFileList2; pProxyFileList2++) {
169 for (i = 0; i < (*pProxyFileList2)->TableSize; i++) {
170 /* FIXME: i think that different vtables should be copied for
171 * async interfaces */
172 void * const *pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Vtbl;
173 void **pRpcStubVtbl = (void **)&(*pProxyFileList2)->pStubVtblList[i]->Vtbl;
176 if ((*pProxyFileList2)->pDelegatedIIDs && (*pProxyFileList2)->pDelegatedIIDs[i]) {
177 pSrcRpcStubVtbl = (void * const *)&CStdStubBuffer_Delegating_Vtbl;
178 if ((*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount > max_delegating_vtbl_size)
179 max_delegating_vtbl_size = (*pProxyFileList2)->pStubVtblList[i]->header.DispatchTableCount;
182 for (j = 0; j < sizeof(IRpcStubBufferVtbl)/sizeof(void *); j++)
183 if (!pRpcStubVtbl[j])
184 pRpcStubVtbl[j] = pSrcRpcStubVtbl[j];
187 if(max_delegating_vtbl_size > 0)
188 create_delegating_vtbl(max_delegating_vtbl_size);
190 if (pclsid && IsEqualGUID(rclsid, pclsid))
191 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
193 const ProxyFileInfo *info;
195 /* otherwise, the dll may be using the iid as the clsid, so
196 * search for it in the proxy file list */
197 if (FindProxyInfo(pProxyFileList, rclsid, &info, &index))
198 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
200 WARN("class %s not available\n", debugstr_guid(rclsid));
201 return CLASS_E_CLASSNOTAVAILABLE;
205 /***********************************************************************
206 * NdrDllCanUnloadNow [RPCRT4.@]
208 HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
210 return pPSFactoryBuffer->RefCount != 0 ? S_FALSE : S_OK;
214 /***********************************************************************
215 * NdrDllRegisterProxy [RPCRT4.@]
217 HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,
218 const ProxyFileInfo **pProxyFileList,
221 static const WCHAR bothW[] = {'B','o','t','h',0};
222 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
223 static const WCHAR clsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
224 static const WCHAR interfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
225 static const WCHAR psfactoryW[] = {'P','S','F','a','c','t','o','r','y','B','u','f','f','e','r',0};
226 static const WCHAR numformatW[] = {'%','u',0};
227 static const WCHAR nummethodsW[] = {'N','u','m','M','e','t','h','o','d','s',0};
228 static const WCHAR inprocserverW[] = {'I','n','P','r','o','c','S','e','r','v','e','r','3','2',0};
229 static const WCHAR threadingmodelW[] = {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
230 WCHAR clsid[39], keyname[50], module[MAX_PATH];
234 TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
235 format_clsid( clsid, pclsid );
237 /* register interfaces to point to clsid */
238 while (*pProxyFileList) {
240 for (u=0; u<(*pProxyFileList)->TableSize; u++) {
241 CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
242 PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
244 TRACE("registering %s %s => %s\n",
245 debugstr_a(name), debugstr_guid(proxy->header.piid), debugstr_w(clsid));
247 strcpyW( keyname, interfaceW );
248 format_clsid( keyname + strlenW(keyname), proxy->header.piid );
249 if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
252 RegSetValueExA(key, NULL, 0, REG_SZ, (const BYTE *)name, strlen(name)+1);
253 RegSetValueW( key, clsid32W, REG_SZ, clsid, 0 );
254 sprintfW(num, numformatW, proxy->header.DispatchTableCount);
255 RegSetValueW( key, nummethodsW, REG_SZ, num, 0 );
262 /* register clsid to point to module */
263 strcpyW( keyname, clsidW );
264 strcatW( keyname, clsid );
265 len = GetModuleFileNameW(hDll, module, sizeof(module)/sizeof(WCHAR));
266 if (len && len < sizeof(module)) {
267 TRACE("registering CLSID %s => %s\n", debugstr_w(clsid), debugstr_w(module));
268 if (RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key) == ERROR_SUCCESS) {
269 RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)psfactoryW, sizeof(psfactoryW));
270 if (RegCreateKeyW(key, inprocserverW, &subkey) == ERROR_SUCCESS) {
271 RegSetValueExW(subkey, NULL, 0, REG_SZ, (LPBYTE)module, (strlenW(module)+1)*sizeof(WCHAR));
272 RegSetValueExW(subkey, threadingmodelW, 0, REG_SZ, (const BYTE *)bothW, sizeof(bothW));
282 /***********************************************************************
283 * NdrDllUnregisterProxy [RPCRT4.@]
285 HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
286 const ProxyFileInfo **pProxyFileList,
289 static const WCHAR clsidW[] = {'C','L','S','I','D','\\',0};
290 static const WCHAR interfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
293 TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
295 /* unregister interfaces */
296 while (*pProxyFileList) {
298 for (u=0; u<(*pProxyFileList)->TableSize; u++) {
299 CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
300 PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
302 TRACE("unregistering %s %s\n", debugstr_a(name), debugstr_guid(proxy->header.piid));
304 strcpyW( keyname, interfaceW );
305 format_clsid( keyname + strlenW(keyname), proxy->header.piid );
306 RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname);
311 /* unregister clsid */
312 strcpyW( keyname, clsidW );
313 format_clsid( keyname + strlenW(keyname), pclsid );
314 RegDeleteTreeW(HKEY_CLASSES_ROOT, keyname);