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/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
45 static BOOL
FindProxyInfo(const ProxyFileInfo
**pProxyFileList
, REFIID riid
, const ProxyFileInfo
**pProxyInfo
, int *pIndex
)
47 while (*pProxyFileList
) {
48 if ((*pProxyFileList
)->pIIDLookupRtn(riid
, pIndex
)) {
49 *pProxyInfo
= *pProxyFileList
;
50 TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo
, *pIndex
);
59 static HRESULT WINAPI
CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface
,
63 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
64 TRACE("(%p)->QueryInterface(%s,%p)\n",iface
,debugstr_guid(riid
),obj
);
65 if (IsEqualGUID(&IID_IUnknown
,riid
) ||
66 IsEqualGUID(&IID_IPSFactoryBuffer
,riid
)) {
68 InterlockedIncrement( &This
->RefCount
);
74 static ULONG WINAPI
CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface
)
76 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
77 TRACE("(%p)->AddRef()\n",iface
);
78 return InterlockedIncrement( &This
->RefCount
);
81 static ULONG WINAPI
CStdPSFactory_Release(LPPSFACTORYBUFFER iface
)
83 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
84 TRACE("(%p)->Release()\n",iface
);
85 return InterlockedDecrement( &This
->RefCount
);
88 static HRESULT WINAPI
CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface
,
91 LPRPCPROXYBUFFER
*ppProxy
,
94 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
95 const ProxyFileInfo
*ProxyInfo
;
97 TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface
,pUnkOuter
,
98 debugstr_guid(riid
),ppProxy
,ppv
);
99 if (!FindProxyInfo(This
->pProxyFileList
,riid
,&ProxyInfo
,&Index
))
100 return E_NOINTERFACE
;
101 return StdProxy_Construct(riid
, pUnkOuter
, ProxyInfo
, Index
, iface
, ppProxy
, ppv
);
104 static HRESULT WINAPI
CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface
,
106 LPUNKNOWN pUnkServer
,
107 LPRPCSTUBBUFFER
*ppStub
)
109 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
110 const ProxyFileInfo
*ProxyInfo
;
112 TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface
,debugstr_guid(riid
),
114 if (!FindProxyInfo(This
->pProxyFileList
,riid
,&ProxyInfo
,&Index
))
115 return E_NOINTERFACE
;
117 if(ProxyInfo
->pDelegatedIIDs
&& ProxyInfo
->pDelegatedIIDs
[Index
])
118 return CStdStubBuffer_Delegating_Construct(riid
, pUnkServer
, ProxyInfo
->pNamesArray
[Index
],
119 ProxyInfo
->pStubVtblList
[Index
], ProxyInfo
->pDelegatedIIDs
[Index
],
122 return CStdStubBuffer_Construct(riid
, pUnkServer
, ProxyInfo
->pNamesArray
[Index
],
123 ProxyInfo
->pStubVtblList
[Index
], iface
, ppStub
);
126 static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl
=
128 CStdPSFactory_QueryInterface
,
129 CStdPSFactory_AddRef
,
130 CStdPSFactory_Release
,
131 CStdPSFactory_CreateProxy
,
132 CStdPSFactory_CreateStub
135 /***********************************************************************
136 * NdrDllGetClassObject [RPCRT4.@]
138 HRESULT WINAPI
NdrDllGetClassObject(REFCLSID rclsid
, REFIID iid
, LPVOID
*ppv
,
139 const ProxyFileInfo
**pProxyFileList
,
141 CStdPSFactoryBuffer
*pPSFactoryBuffer
)
143 TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid
),
144 debugstr_guid(iid
), ppv
, pProxyFileList
, debugstr_guid(pclsid
),
148 if (!pPSFactoryBuffer
->lpVtbl
) {
149 const ProxyFileInfo
**pProxyFileList2
;
150 int max_delegating_vtbl_size
= 0;
151 pPSFactoryBuffer
->lpVtbl
= &CStdPSFactory_Vtbl
;
152 pPSFactoryBuffer
->RefCount
= 0;
153 pPSFactoryBuffer
->pProxyFileList
= pProxyFileList
;
154 for (pProxyFileList2
= pProxyFileList
; *pProxyFileList2
; pProxyFileList2
++) {
156 for (i
= 0; i
< (*pProxyFileList2
)->TableSize
; i
++) {
157 /* FIXME: i think that different vtables should be copied for
158 * async interfaces */
159 void * const *pSrcRpcStubVtbl
= (void * const *)&CStdStubBuffer_Vtbl
;
160 void **pRpcStubVtbl
= (void **)&(*pProxyFileList2
)->pStubVtblList
[i
]->Vtbl
;
163 if ((*pProxyFileList2
)->pDelegatedIIDs
&& (*pProxyFileList2
)->pDelegatedIIDs
[i
]) {
164 pSrcRpcStubVtbl
= (void * const *)&CStdStubBuffer_Delegating_Vtbl
;
165 if ((*pProxyFileList2
)->pStubVtblList
[i
]->header
.DispatchTableCount
> max_delegating_vtbl_size
)
166 max_delegating_vtbl_size
= (*pProxyFileList2
)->pStubVtblList
[i
]->header
.DispatchTableCount
;
169 for (j
= 0; j
< sizeof(IRpcStubBufferVtbl
)/sizeof(void *); j
++)
170 if (!pRpcStubVtbl
[j
])
171 pRpcStubVtbl
[j
] = pSrcRpcStubVtbl
[j
];
174 if(max_delegating_vtbl_size
> 0)
175 create_delegating_vtbl(max_delegating_vtbl_size
);
177 if (IsEqualGUID(rclsid
, pclsid
))
178 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER
)pPSFactoryBuffer
, iid
, ppv
);
180 const ProxyFileInfo
*info
;
182 /* otherwise, the dll may be using the iid as the clsid, so
183 * search for it in the proxy file list */
184 if (FindProxyInfo(pProxyFileList
, rclsid
, &info
, &index
))
185 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER
)pPSFactoryBuffer
, iid
, ppv
);
187 WARN("class %s not available\n", debugstr_guid(rclsid
));
188 return CLASS_E_CLASSNOTAVAILABLE
;
192 /***********************************************************************
193 * NdrDllCanUnloadNow [RPCRT4.@]
195 HRESULT WINAPI
NdrDllCanUnloadNow(CStdPSFactoryBuffer
*pPSFactoryBuffer
)
197 return !(pPSFactoryBuffer
->RefCount
);
200 /***********************************************************************
201 * NdrDllRegisterProxy [RPCRT4.@]
203 HRESULT WINAPI
NdrDllRegisterProxy(HMODULE hDll
,
204 const ProxyFileInfo
**pProxyFileList
,
208 char keyname
[120], module
[MAX_PATH
];
212 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
213 UuidToStringA((UUID
*)pclsid
, (unsigned char**)&clsid
);
215 /* register interfaces to point to clsid */
216 while (*pProxyFileList
) {
218 for (u
=0; u
<(*pProxyFileList
)->TableSize
; u
++) {
219 CInterfaceStubVtbl
*proxy
= (*pProxyFileList
)->pStubVtblList
[u
];
220 PCInterfaceName name
= (*pProxyFileList
)->pNamesArray
[u
];
223 TRACE("registering %s %s => %s\n", name
, debugstr_guid(proxy
->header
.piid
), clsid
);
225 UuidToStringA((UUID
*)proxy
->header
.piid
, (unsigned char**)&iid
);
226 snprintf(keyname
, sizeof(keyname
), "Interface\\{%s}", iid
);
227 RpcStringFreeA((unsigned char**)&iid
);
228 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, NULL
, 0,
229 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
231 RegSetValueExA(key
, NULL
, 0, REG_SZ
, (const BYTE
*)name
, strlen(name
));
232 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
233 KEY_WRITE
, NULL
, &subkey
, NULL
) == ERROR_SUCCESS
) {
234 snprintf(module
, sizeof(module
), "{%s}", clsid
);
235 RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)module
, strlen(module
));
244 /* register clsid to point to module */
245 snprintf(keyname
, sizeof(keyname
), "CLSID\\{%s}", clsid
);
246 len
= GetModuleFileNameA(hDll
, module
, sizeof(module
));
247 if (len
&& len
< sizeof(module
)) {
248 TRACE("registering CLSID %s => %s\n", clsid
, module
);
249 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, NULL
, 0,
250 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
251 RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (const BYTE
*)"PSFactoryBuffer", strlen("PSFactoryBuffer"));
252 if (RegCreateKeyExA(key
, "InProcServer32", 0, NULL
, 0,
253 KEY_WRITE
, NULL
, &subkey
, NULL
) == ERROR_SUCCESS
) {
254 RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)module
, strlen(module
));
255 RegSetValueExA(subkey
, "ThreadingModel", 0, REG_SZ
, (const BYTE
*)"Both", strlen("Both"));
263 RpcStringFreeA((unsigned char**)&clsid
);
267 /***********************************************************************
268 * NdrDllUnregisterProxy [RPCRT4.@]
270 HRESULT WINAPI
NdrDllUnregisterProxy(HMODULE hDll
,
271 const ProxyFileInfo
**pProxyFileList
,
275 char keyname
[120], module
[MAX_PATH
];
278 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
279 UuidToStringA((UUID
*)pclsid
, (unsigned char**)&clsid
);
281 /* unregister interfaces */
282 while (*pProxyFileList
) {
284 for (u
=0; u
<(*pProxyFileList
)->TableSize
; u
++) {
285 CInterfaceStubVtbl
*proxy
= (*pProxyFileList
)->pStubVtblList
[u
];
286 PCInterfaceName name
= (*pProxyFileList
)->pNamesArray
[u
];
289 TRACE("unregistering %s %s <= %s\n", name
, debugstr_guid(proxy
->header
.piid
), clsid
);
291 UuidToStringA((UUID
*)proxy
->header
.piid
, (unsigned char**)&iid
);
292 snprintf(keyname
, sizeof(keyname
), "Interface\\{%s}", iid
);
293 RpcStringFreeA((unsigned char**)&iid
);
294 RegDeleteKeyA(HKEY_CLASSES_ROOT
, keyname
);
299 /* unregister clsid */
300 snprintf(keyname
, sizeof(keyname
), "CLSID\\{%s}", clsid
);
301 len
= GetModuleFileNameA(hDll
, module
, sizeof(module
));
302 if (len
&& len
< sizeof(module
)) {
303 TRACE("unregistering CLSID %s <= %s\n", clsid
, module
);
304 RegDeleteKeyA(HKEY_CLASSES_ROOT
, keyname
);
308 RpcStringFreeA((unsigned char**)&clsid
);