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
36 #include "wine/debug.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
);
65 static HRESULT WINAPI
CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface
,
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
)) {
74 InterlockedIncrement( &This
->RefCount
);
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
,
97 LPRPCPROXYBUFFER
*ppProxy
,
100 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
101 const ProxyFileInfo
*ProxyInfo
;
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
,
112 LPUNKNOWN pUnkServer
,
113 LPRPCSTUBBUFFER
*ppStub
)
115 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
116 const ProxyFileInfo
*ProxyInfo
;
118 TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface
,debugstr_guid(riid
),
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
],
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
)
146 psfac
->lpVtbl
= &CStdPSFactory_Vtbl
;
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
,
182 CStdPSFactoryBuffer
*pPSFactoryBuffer
)
184 TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid
),
185 debugstr_guid(iid
), ppv
, pProxyFileList
, debugstr_guid(pclsid
),
189 if (!pPSFactoryBuffer
->lpVtbl
) init_psfactory( pPSFactoryBuffer
, pProxyFileList
);
191 if (pclsid
&& IsEqualGUID(rclsid
, pclsid
))
192 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER
)pPSFactoryBuffer
, iid
, ppv
);
194 const ProxyFileInfo
*info
;
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
,
222 WCHAR clsid
[39], keyname
[50], module
[MAX_PATH
];
226 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
228 if (!hDll
) return E_HANDLE
;
229 if (!*pProxyFileList
) return E_NOINTERFACE
;
232 format_clsid( clsid
, pclsid
);
233 else if ((*pProxyFileList
)->TableSize
> 0)
234 format_clsid( clsid
,(*pProxyFileList
)->pStubVtblList
[0]->header
.piid
);
236 return E_NOINTERFACE
;
238 /* register interfaces to point to clsid */
239 while (*pProxyFileList
) {
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
) {
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 );
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"));
283 /***********************************************************************
284 * NdrDllUnregisterProxy [RPCRT4.@]
286 HRESULT WINAPI
NdrDllUnregisterProxy(HMODULE hDll
,
287 const ProxyFileInfo
**pProxyFileList
,
293 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
295 format_clsid( clsid
, pclsid
);
296 else if ((*pProxyFileList
)->TableSize
> 0)
297 format_clsid( clsid
,(*pProxyFileList
)->pStubVtblList
[0]->header
.piid
);
299 return E_NOINTERFACE
;
301 /* unregister interfaces */
302 while (*pProxyFileList
) {
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
);
317 /* unregister clsid */
318 lstrcpyW( keyname
, L
"CLSID\\" );
319 lstrcatW( keyname
, clsid
);
320 RegDeleteTreeW(HKEY_CLASSES_ROOT
, keyname
);