[Author: zork]
[google-gears.git] / gears / third_party / passthru_app / ProtocolCF.inl
blobd7149f6de0cf0d125654175a72beb5c1c1ece803
1 // Copyright 2007 Igor Tandetnik
2 // 
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 #ifndef GEARS_THIRD_PARTY_PASSTHRU_APP_PROTOCOLCF_INL__
16 #define GEARS_THIRD_PARTY_PASSTHRU_APP_PROTOCOLCF_INL__
18 #if _MSC_VER > 1000
19 #pragma once
20 #endif // _MSC_VER > 1000
22 #ifndef GEARS_THIRD_PARTY_PASSTHRU_APP_PROTOCOLCF_H__
23   #error ProtocolCF.inl requires ProtocolCF.h to be included first
24 #endif
26 #include "PassthroughObject.h"
28 namespace PassthroughAPP
31 // ===== CComClassFactoryProtocol =====
33 inline STDMETHODIMP CComClassFactoryProtocol::CreateInstance(
34   IUnknown* punkOuter, REFIID riid, void** ppvObj)
36   // gears - this is added to prevent tons of asserts below when Gears'
37   // handler is installed. Gears uses an undocumented method of getting URLMON 
38   // to use IInternetProtocolInfo for well known protocols.
39   // See \gears\localserver\ie\http_handler_ie.cc for more info.
40   if (riid != IID_IUnknown) 
41     return E_NOINTERFACE;
43   ATLASSERT(ppvObj != 0);
44   if (!ppvObj)
45   {
46     return E_POINTER;
47   }
48   *ppvObj = 0;
50   CComPtr<IUnknown> spUnkTarget;
51   HRESULT hr = CreateInstanceTarget(&spUnkTarget);
52   ATLASSERT(SUCCEEDED(hr) && spUnkTarget != 0);
54   CComPtr<IUnknown> spUnkObject;
55   if (SUCCEEDED(hr))
56   {
57     hr = BaseClass::CreateInstance(punkOuter, riid,
58       reinterpret_cast<void**>(&spUnkObject));
59     ATLASSERT(SUCCEEDED(hr) && spUnkObject != 0);
60   }
62   if (SUCCEEDED(hr))
63   {
64     CComPtr<IPassthroughObject> spPassthroughObj;
65     hr = spUnkObject->QueryInterface(&spPassthroughObj);
66     ATLASSERT(SUCCEEDED(hr) && spPassthroughObj != 0);
67     if (SUCCEEDED(hr))
68     {
69       hr = spPassthroughObj->SetTargetUnknown(spUnkTarget);
70       ATLASSERT(SUCCEEDED(hr));
71     }
72   }
74   if (SUCCEEDED(hr))
75   {
76     *ppvObj = spUnkObject.Detach();
77   }
78   return hr;
81 inline HRESULT CComClassFactoryProtocol::CreateInstanceTarget(
82   IUnknown** ppTargetProtocol)
84   ATLASSERT(ppTargetProtocol != 0);
85   if (!ppTargetProtocol)
86   {
87     return E_POINTER;
88   }
89   *ppTargetProtocol = 0;
91   CComPtr<IClassFactory> spTargetCF;
92   HRESULT hr = GetTargetClassFactory(&spTargetCF);
93   ATLASSERT(SUCCEEDED(hr) && spTargetCF != 0);
94   if (SUCCEEDED(hr))
95   {
96     hr = spTargetCF->CreateInstance(0, IID_IInternetProtocolRoot,
97       reinterpret_cast<void**>(ppTargetProtocol));
98     ATLASSERT(SUCCEEDED(hr) && *ppTargetProtocol != 0);
99   }
100   return hr;
103 inline HRESULT CComClassFactoryProtocol::GetTargetClassFactory(
104   IClassFactory** ppCF)
106   ObjectLock lock(this);
107   return m_spTargetCF.CopyTo(ppCF);
110 inline HRESULT CComClassFactoryProtocol::SetTargetClassFactory(
111   IClassFactory* pCF)
113   HRESULT hr = (pCF ? pCF->LockServer(TRUE) : S_OK);
114   if (SUCCEEDED(hr))
115   {
116     ObjectLock lock(this);
117     if (m_spTargetCF)
118     {
119       // LockServer(FALSE) is assumed to always succeed. Otherwise,
120       // it is impossible to implement correct semantics
121       HRESULT hr1 = m_spTargetCF->LockServer(FALSE);
122       hr1;
123       ATLASSERT(SUCCEEDED(hr1));
124     }
125     m_spTargetCF = pCF;
126   }
127   return hr;
130 inline HRESULT CComClassFactoryProtocol::SetTargetCLSID(REFCLSID clsid,
131   DWORD clsContext)
133   CComPtr<IClassFactory> spTargetCF;
134 #ifdef WINCE
135   // Gears - the normal way to create the class object is as follows:
136   // HRESULT hr = CoGetClassObject(clsid, clsContext, 0, IID_IClassFactory,
137   //  reinterpret_cast<void**>(&spTargetCF));
138   // However, this doesn't work on Windows Mobile 5 due to the relevant keys 
139   // missing from the registry. We therefore bypass the registry.
140   typedef HRESULT (*DllGetClassObjectPointer)(REFCLSID rclsid,
141                                               REFIID riid,
142                                               LPVOID * ppv);
143   HINSTANCE urlmon = CoLoadLibrary(L"urlmon.dll", FALSE);
144   ATLASSERT(urlmon);
145   if (!urlmon)
146   {
147     return HRESULT_FROM_WIN32(GetLastError());
148   }
150   DllGetClassObjectPointer dll_get_class_object =
151       reinterpret_cast<DllGetClassObjectPointer>(
152       GetProcAddress(urlmon, L"DllGetClassObject"));
153   ATLASSERT(dll_get_class_object);
154   if (!dll_get_class_object)
155   {
156     return HRESULT_FROM_WIN32(GetLastError());
157   }
159   HRESULT hr = dll_get_class_object(clsid,
160                                     IID_IClassFactory,
161                                     reinterpret_cast<void**>(&spTargetCF));
162   CoFreeLibrary(urlmon);
163 #else
164   HRESULT hr = CoGetClassObject(clsid, clsContext, 0, IID_IClassFactory,
165     reinterpret_cast<void**>(&spTargetCF));
166 #endif
167   ATLASSERT(SUCCEEDED(hr) && spTargetCF != 0);
168   if (SUCCEEDED(hr))
169   {
170     hr = SetTargetClassFactory(spTargetCF);
171     ATLASSERT(SUCCEEDED(hr));
172   }
173   return hr;
176 inline void CComClassFactoryProtocol::FinalRelease()
178   // No need to be thread safe here
179   if (m_spTargetCF)
180   {
181     // LockServer(FALSE) is assumed to always succeed.
182     HRESULT hr = m_spTargetCF->LockServer(FALSE);
183     hr;
184     ATLASSERT(SUCCEEDED(hr));
186     m_spTargetCF.Release();
187   }
190 // ===== CMetaFactory =====
192 template <class Factory, class Protocol, class FactoryComObject>
193 inline HRESULT CMetaFactory<Factory, Protocol, FactoryComObject>::
194   CreateInstance(Factory** ppObj)
196   ATLASSERT(ppObj != 0);
197   if (!ppObj)
198   {
199     return E_POINTER;
200   }
202   HRESULT hr = E_OUTOFMEMORY;
203   void* pv = static_cast<void*>(CreatorClass::CreateInstance);
204   FactoryComObject* p = 0;
205   ATLTRY(p = new FactoryComObject(pv))
206   if (p != NULL)
207   {
208     p->SetVoid(pv);
209     p->InternalFinalConstructAddRef();
210 #if _ATL_VER >= 0x800  // gears - added by cprince
211     hr = p->_AtlInitialConstruct();  
212     if (SUCCEEDED(hr))
213 #endif
214       hr = p->FinalConstruct();
215 #if _ATL_VER >= 0x800  // gears - added by cprince
216     if (SUCCEEDED(hr))
217       hr = p->_AtlFinalConstruct();
218 #endif
219     p->InternalFinalConstructRelease();
220     if (FAILED(hr))
221     {
222       delete p;
223       p = 0;
224     }
225   }
226   *ppObj = p;
227   return hr;
230 template <class Factory, class Protocol, class FactoryComObject>
231 inline HRESULT CMetaFactory<Factory, Protocol, FactoryComObject>::
232   CreateInstance(IClassFactory* pTargetCF, IClassFactory** ppCF)
234   if (!ppCF)
235   {
236     return E_POINTER;
237   }
238   *ppCF = 0;
240   Factory* pObj = 0;
241   HRESULT hr = CreateInstance(&pObj);
242   ATLASSERT(SUCCEEDED(hr) && pObj != 0);
243   if (SUCCEEDED(hr))
244   {
245     pObj->AddRef();
247     hr = pObj->SetTargetClassFactory(pTargetCF);
248     ATLASSERT(SUCCEEDED(hr));
250     if (SUCCEEDED(hr))
251     {
252       hr = pObj->QueryInterface(IID_IClassFactory,
253         reinterpret_cast<void**>(ppCF));
254       ATLASSERT(SUCCEEDED(hr) && *ppCF != 0);
255     }
257     pObj->Release();
258   }
259   return hr;
262 template <class Factory, class Protocol, class FactoryComObject>
263 inline HRESULT CMetaFactory<Factory, Protocol, FactoryComObject>::
264   CreateInstance(REFCLSID clsidTarget, IClassFactory** ppCF)
266   if (!ppCF)
267   {
268     return E_POINTER;
269   }
270   *ppCF = 0;
272   Factory* pObj = 0;
273   HRESULT hr = CreateInstance(&pObj);
274   ATLASSERT(SUCCEEDED(hr) && pObj != 0);
275   if (SUCCEEDED(hr))
276   {
277     pObj->AddRef();
279     hr = pObj->SetTargetCLSID(clsidTarget);
280     ATLASSERT(SUCCEEDED(hr));
282     if (SUCCEEDED(hr))
283     {
284       hr = pObj->QueryInterface(IID_IClassFactory,
285         reinterpret_cast<void**>(ppCF));
286       ATLASSERT(SUCCEEDED(hr) && *ppCF != 0);
287     }
289     pObj->Release();
290   }
291   return hr;
294 } // end namespace PassthroughAPP
296 #endif // GEARS_THIRD_PARTY_PASSTHRU_APP_PROTOCOLCF_INL__