Add support for specific EOI PIC command.
[wine] / dlls / rpcrt4 / cpsf.c
1 /*
2  * COM proxy/stub factory (CStdPSFactory) implementation
3  *
4  * Copyright 2001 Ove Kåven, TransGaming Technologies
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include <stdio.h>
22 #include <string.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winerror.h"
27 #include "winreg.h"
28
29 #include "objbase.h"
30
31 #include "rpcproxy.h"
32
33 #include "wine/debug.h"
34
35 #include "cpsf.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
38
39 static BOOL FindProxyInfo(const ProxyFileInfo **pProxyFileList, REFIID riid, const ProxyFileInfo **pProxyInfo, int *pIndex)
40 {
41   while (*pProxyFileList) {
42     if ((*pProxyFileList)->pIIDLookupRtn(riid, pIndex)) {
43       *pProxyInfo = *pProxyFileList;
44       TRACE("found: ProxyInfo %p Index %d\n", *pProxyInfo, *pIndex);
45       return TRUE;
46     }
47     pProxyFileList++;
48   }
49   TRACE("not found\n");
50   return FALSE;
51 }
52
53 static HRESULT WINAPI CStdPSFactory_QueryInterface(LPPSFACTORYBUFFER iface,
54                                                   REFIID riid,
55                                                   LPVOID *obj)
56 {
57   ICOM_THIS(CStdPSFactoryBuffer,iface);
58   TRACE("(%p)->QueryInterface(%s,%p)\n",iface,debugstr_guid(riid),obj);
59   if (IsEqualGUID(&IID_IUnknown,riid) ||
60       IsEqualGUID(&IID_IPSFactoryBuffer,riid)) {
61     *obj = This;
62     This->RefCount++;
63     return S_OK;
64   }
65   return E_NOINTERFACE;
66 }
67
68 static ULONG WINAPI CStdPSFactory_AddRef(LPPSFACTORYBUFFER iface)
69 {
70   ICOM_THIS(CStdPSFactoryBuffer,iface);
71   TRACE("(%p)->AddRef()\n",iface);
72   return ++(This->RefCount);
73 }
74
75 static ULONG WINAPI CStdPSFactory_Release(LPPSFACTORYBUFFER iface)
76 {
77   ICOM_THIS(CStdPSFactoryBuffer,iface);
78   TRACE("(%p)->Release()\n",iface);
79   return --(This->RefCount);
80 }
81
82 static HRESULT WINAPI CStdPSFactory_CreateProxy(LPPSFACTORYBUFFER iface,
83                                                LPUNKNOWN pUnkOuter,
84                                                REFIID riid,
85                                                LPRPCPROXYBUFFER *ppProxy,
86                                                LPVOID *ppv)
87 {
88   ICOM_THIS(CStdPSFactoryBuffer,iface);
89   const ProxyFileInfo *ProxyInfo;
90   int Index;
91   TRACE("(%p)->CreateProxy(%p,%s,%p,%p)\n",iface,pUnkOuter,
92        debugstr_guid(riid),ppProxy,ppv);
93   if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
94     return E_NOINTERFACE;
95   return StdProxy_Construct(riid, pUnkOuter, ProxyInfo->pNamesArray[Index],
96                             ProxyInfo->pProxyVtblList[Index],
97                             ProxyInfo->pStubVtblList[Index], iface, ppProxy, ppv);
98 }
99
100 static HRESULT WINAPI CStdPSFactory_CreateStub(LPPSFACTORYBUFFER iface,
101                                               REFIID riid,
102                                               LPUNKNOWN pUnkServer,
103                                               LPRPCSTUBBUFFER *ppStub)
104 {
105   ICOM_THIS(CStdPSFactoryBuffer,iface);
106   const ProxyFileInfo *ProxyInfo;
107   int Index;
108   TRACE("(%p)->CreateStub(%s,%p,%p)\n",iface,debugstr_guid(riid),
109        pUnkServer,ppStub);
110   if (!FindProxyInfo(This->pProxyFileList,riid,&ProxyInfo,&Index))
111     return E_NOINTERFACE;
112   return CStdStubBuffer_Construct(riid, pUnkServer, ProxyInfo->pNamesArray[Index],
113                                   ProxyInfo->pStubVtblList[Index], iface, ppStub);
114 }
115
116 static ICOM_VTABLE(IPSFactoryBuffer) CStdPSFactory_Vtbl =
117 {
118   ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
119   CStdPSFactory_QueryInterface,
120   CStdPSFactory_AddRef,
121   CStdPSFactory_Release,
122   CStdPSFactory_CreateProxy,
123   CStdPSFactory_CreateStub
124 };
125
126 /***********************************************************************
127  *           NdrDllGetClassObject [RPCRT4.@]
128  */
129 HRESULT WINAPI NdrDllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv,
130                                    const ProxyFileInfo **pProxyFileList,
131                                    const CLSID *pclsid,
132                                    CStdPSFactoryBuffer *pPSFactoryBuffer)
133 {
134   *ppv = NULL;
135   if (!pPSFactoryBuffer->lpVtbl) {
136     pPSFactoryBuffer->lpVtbl = &CStdPSFactory_Vtbl;
137     pPSFactoryBuffer->RefCount = 0;
138     pPSFactoryBuffer->pProxyFileList = pProxyFileList;
139   }
140   if (IsEqualGUID(rclsid, pclsid))
141     return IPSFactoryBuffer_QueryInterface((LPPSFACTORYBUFFER)pPSFactoryBuffer, iid, ppv);
142   return CLASS_E_CLASSNOTAVAILABLE;
143 }
144
145 /***********************************************************************
146  *           NdrDllCanUnloadNow [RPCRT4.@]
147  */
148 HRESULT WINAPI NdrDllCanUnloadNow(CStdPSFactoryBuffer *pPSFactoryBuffer)
149 {
150   return !(pPSFactoryBuffer->RefCount);
151 }
152
153 /***********************************************************************
154  *           NdrDllRegisterProxy [RPCRT4.@]
155  */
156 HRESULT WINAPI NdrDllRegisterProxy(HMODULE hDll,
157                                   const ProxyFileInfo **pProxyFileList,
158                                   const CLSID *pclsid)
159 {
160   LPSTR clsid;
161   char keyname[120], module[120];
162   HKEY key, subkey;
163
164   TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
165   UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid);
166
167   /* register interfaces to point to clsid */
168   while (*pProxyFileList) {
169     unsigned u;
170     for (u=0; u<(*pProxyFileList)->TableSize; u++) {
171       CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
172       PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
173       LPSTR iid;
174
175       TRACE("registering %s %s => %s\n", name, debugstr_guid(proxy->header.piid), clsid);
176
177       UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid);
178       snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid);
179       RpcStringFreeA((unsigned char**)&iid);
180       if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0,
181                           KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
182         if (name)
183           RegSetValueExA(key, NULL, 0, REG_SZ, name, strlen(name));
184         if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
185                             KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) {
186           snprintf(module, sizeof(module), "{%s}", clsid);
187           RegSetValueExA(subkey, NULL, 0, REG_SZ, module, strlen(module));
188           RegCloseKey(subkey);
189         }
190         RegCloseKey(key);
191       }
192     }
193     pProxyFileList++;
194   }
195
196   /* register clsid to point to module */
197   snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid);
198   GetModuleFileNameA(hDll, module, sizeof(module));
199   TRACE("registering CLSID %s => %s\n", clsid, module);
200   if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyname, 0, NULL, 0,
201                       KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
202      if (RegCreateKeyExA(key, "InProcServer32", 0, NULL, 0,
203                          KEY_WRITE, NULL, &subkey, NULL) == ERROR_SUCCESS) {
204        RegSetValueExA(subkey, NULL, 0, REG_SZ, module, strlen(module));
205        RegCloseKey(subkey);
206      }
207      RegCloseKey(key);
208   }
209
210   /* done */
211   RpcStringFreeA((unsigned char**)&clsid);
212   return S_OK;
213 }
214
215 /***********************************************************************
216  *           NdrDllUnregisterProxy [RPCRT4.@]
217  */
218 HRESULT WINAPI NdrDllUnregisterProxy(HMODULE hDll,
219                                     const ProxyFileInfo **pProxyFileList,
220                                     const CLSID *pclsid)
221 {
222   LPSTR clsid;
223   char keyname[120], module[120];
224
225   TRACE("(%p,%p,%s)\n", hDll, pProxyFileList, debugstr_guid(pclsid));
226   UuidToStringA((UUID*)pclsid, (unsigned char**)&clsid);
227
228   /* unregister interfaces */
229   while (*pProxyFileList) {
230     unsigned u;
231     for (u=0; u<(*pProxyFileList)->TableSize; u++) {
232       CInterfaceStubVtbl *proxy = (*pProxyFileList)->pStubVtblList[u];
233       PCInterfaceName name = (*pProxyFileList)->pNamesArray[u];
234       LPSTR iid;
235
236       TRACE("unregistering %s %s <= %s\n", name, debugstr_guid(proxy->header.piid), clsid);
237
238       UuidToStringA((UUID*)proxy->header.piid, (unsigned char**)&iid);
239       snprintf(keyname, sizeof(keyname), "Interface\\{%s}", iid);
240       RpcStringFreeA((unsigned char**)&iid);
241       RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);
242     }
243     pProxyFileList++;
244   }
245
246   /* unregister clsid */
247   snprintf(keyname, sizeof(keyname), "CLSID\\{%s}", clsid);
248   GetModuleFileNameA(hDll, module, sizeof(module));
249   TRACE("unregistering CLSID %s <= %s\n", clsid, module);
250   RegDeleteKeyA(HKEY_CLASSES_ROOT, keyname);
251
252   /* done */
253   RpcStringFreeA((unsigned char**)&clsid);
254   return S_OK;
255 }