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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
42 static BOOL
FindProxyInfo(const ProxyFileInfo
**pProxyFileList
, REFIID riid
, const ProxyFileInfo
**pProxyInfo
, int *pIndex
)
44 while (*pProxyFileList
) {
45 if ((*pProxyFileList
)->pIIDLookupRtn(riid
, pIndex
)) {
46 *pProxyInfo
= *pProxyFileList
;
47 TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo
, *pIndex
);
56 static HRESULT WINAPI
CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface
,
60 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
61 TRACE("(%p)->QueryInterface(%s,%p)\n",iface
,debugstr_guid(riid
),obj
);
62 if (IsEqualGUID(&IID_IUnknown
,riid
) ||
63 IsEqualGUID(&IID_IPSFactoryBuffer
,riid
)) {
71 static ULONG WINAPI
CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface
)
73 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
74 TRACE("(%p)->AddRef()\n",iface
);
75 return ++(This
->RefCount
);
78 static ULONG WINAPI
CStdPSFactory_Release(LPPSFACTORYBUFFER iface
)
80 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
81 TRACE("(%p)->Release()\n",iface
);
82 return --(This
->RefCount
);
85 static HRESULT WINAPI
CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface
,
88 LPRPCPROXYBUFFER
*ppProxy
,
91 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
92 const ProxyFileInfo
*ProxyInfo
;
94 TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface
,pUnkOuter
,
95 debugstr_guid(riid
),ppProxy
,ppv
);
96 if (!FindProxyInfo(This
->pProxyFileList
,riid
,&ProxyInfo
,&Index
))
98 return StdProxy_Construct(riid
, pUnkOuter
, ProxyInfo
->pNamesArray
[Index
],
99 ProxyInfo
->pProxyVtblList
[Index
],
100 ProxyInfo
->pStubVtblList
[Index
], iface
, ppProxy
, ppv
);
103 static HRESULT WINAPI
CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface
,
105 LPUNKNOWN pUnkServer
,
106 LPRPCSTUBBUFFER
*ppStub
)
108 CStdPSFactoryBuffer
*This
= (CStdPSFactoryBuffer
*)iface
;
109 const ProxyFileInfo
*ProxyInfo
;
111 TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface
,debugstr_guid(riid
),
113 if (!FindProxyInfo(This
->pProxyFileList
,riid
,&ProxyInfo
,&Index
))
114 return E_NOINTERFACE
;
115 return CStdStubBuffer_Construct(riid
, pUnkServer
, ProxyInfo
->pNamesArray
[Index
],
116 ProxyInfo
->pStubVtblList
[Index
], iface
, ppStub
);
119 static const IPSFactoryBufferVtbl CStdPSFactory_Vtbl
=
121 CStdPSFactory_QueryInterface
,
122 CStdPSFactory_AddRef
,
123 CStdPSFactory_Release
,
124 CStdPSFactory_CreateProxy
,
125 CStdPSFactory_CreateStub
128 /***********************************************************************
129 * NdrDllGetClassObject [RPCRT4.@]
131 HRESULT WINAPI
NdrDllGetClassObject(REFCLSID rclsid
, REFIID iid
, LPVOID
*ppv
,
132 const ProxyFileInfo
**pProxyFileList
,
134 CStdPSFactoryBuffer
*pPSFactoryBuffer
)
136 TRACE("(%s, %s, %p, %p, %s, %p)\n", debugstr_guid(rclsid
),
137 debugstr_guid(iid
), ppv
, pProxyFileList
, debugstr_guid(pclsid
),
141 if (!pPSFactoryBuffer
->lpVtbl
) {
142 pPSFactoryBuffer
->lpVtbl
= &CStdPSFactory_Vtbl
;
143 pPSFactoryBuffer
->RefCount
= 0;
144 pPSFactoryBuffer
->pProxyFileList
= pProxyFileList
;
146 if (IsEqualGUID(rclsid
, pclsid
))
147 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER
)pPSFactoryBuffer
, iid
, ppv
);
149 const ProxyFileInfo
*info
;
151 /* otherwise, the dll may be using the iid as the clsid, so
152 * search for it in the proxy file list */
153 if (FindProxyInfo(pProxyFileList
, rclsid
, &info
, &index
))
154 return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER
)pPSFactoryBuffer
, iid
, ppv
);
156 WARN("class %s not available\n", debugstr_guid(rclsid
));
157 return CLASS_E_CLASSNOTAVAILABLE
;
161 /***********************************************************************
162 * NdrDllCanUnloadNow [RPCRT4.@]
164 HRESULT WINAPI
NdrDllCanUnloadNow(CStdPSFactoryBuffer
*pPSFactoryBuffer
)
166 return !(pPSFactoryBuffer
->RefCount
);
169 /***********************************************************************
170 * NdrDllRegisterProxy [RPCRT4.@]
172 HRESULT WINAPI
NdrDllRegisterProxy(HMODULE hDll
,
173 const ProxyFileInfo
**pProxyFileList
,
177 char keyname
[120], module
[MAX_PATH
];
181 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
182 UuidToStringA((UUID
*)pclsid
, (unsigned char**)&clsid
);
184 /* register interfaces to point to clsid */
185 while (*pProxyFileList
) {
187 for (u
=0; u
<(*pProxyFileList
)->TableSize
; u
++) {
188 CInterfaceStubVtbl
*proxy
= (*pProxyFileList
)->pStubVtblList
[u
];
189 PCInterfaceName name
= (*pProxyFileList
)->pNamesArray
[u
];
192 TRACE("registering %s %s => %s\n", name
, debugstr_guid(proxy
->header
.piid
), clsid
);
194 UuidToStringA((UUID
*)proxy
->header
.piid
, (unsigned char**)&iid
);
195 snprintf(keyname
, sizeof(keyname
), "Interface\\{%s}", iid
);
196 RpcStringFreeA((unsigned char**)&iid
);
197 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, NULL
, 0,
198 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
200 RegSetValueExA(key
, NULL
, 0, REG_SZ
, (LPBYTE
)name
, strlen(name
));
201 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
202 KEY_WRITE
, NULL
, &subkey
, NULL
) == ERROR_SUCCESS
) {
203 snprintf(module
, sizeof(module
), "{%s}", clsid
);
204 RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)module
, strlen(module
));
213 /* register clsid to point to module */
214 snprintf(keyname
, sizeof(keyname
), "CLSID\\{%s}", clsid
);
215 len
= GetModuleFileNameA(hDll
, module
, sizeof(module
));
216 if (len
&& len
< sizeof(module
)) {
217 TRACE("registering CLSID %s => %s\n", clsid
, module
);
218 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyname
, 0, NULL
, 0,
219 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
220 if (RegCreateKeyExA(key
, "InProcServer32", 0, NULL
, 0,
221 KEY_WRITE
, NULL
, &subkey
, NULL
) == ERROR_SUCCESS
) {
222 RegSetValueExA(subkey
, NULL
, 0, REG_SZ
, (LPBYTE
)module
, strlen(module
));
230 RpcStringFreeA((unsigned char**)&clsid
);
234 /***********************************************************************
235 * NdrDllUnregisterProxy [RPCRT4.@]
237 HRESULT WINAPI
NdrDllUnregisterProxy(HMODULE hDll
,
238 const ProxyFileInfo
**pProxyFileList
,
242 char keyname
[120], module
[MAX_PATH
];
245 TRACE("(%p,%p,%s)\n", hDll
, pProxyFileList
, debugstr_guid(pclsid
));
246 UuidToStringA((UUID
*)pclsid
, (unsigned char**)&clsid
);
248 /* unregister interfaces */
249 while (*pProxyFileList
) {
251 for (u
=0; u
<(*pProxyFileList
)->TableSize
; u
++) {
252 CInterfaceStubVtbl
*proxy
= (*pProxyFileList
)->pStubVtblList
[u
];
253 PCInterfaceName name
= (*pProxyFileList
)->pNamesArray
[u
];
256 TRACE("unregistering %s %s <= %s\n", name
, debugstr_guid(proxy
->header
.piid
), clsid
);
258 UuidToStringA((UUID
*)proxy
->header
.piid
, (unsigned char**)&iid
);
259 snprintf(keyname
, sizeof(keyname
), "Interface\\{%s}", iid
);
260 RpcStringFreeA((unsigned char**)&iid
);
261 RegDeleteKeyA(HKEY_CLASSES_ROOT
, keyname
);
266 /* unregister clsid */
267 snprintf(keyname
, sizeof(keyname
), "CLSID\\{%s}", clsid
);
268 len
= GetModuleFileNameA(hDll
, module
, sizeof(module
));
269 if (len
&& len
< sizeof(module
)) {
270 TRACE("unregistering CLSID %s <= %s\n", clsid
, module
);
271 RegDeleteKeyA(HKEY_CLASSES_ROOT
, keyname
);
275 RpcStringFreeA((unsigned char**)&clsid
);