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
);