1 // Copyright 2007 Igor Tandetnik
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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__
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
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)
43 ATLASSERT(ppvObj != 0);
50 CComPtr<IUnknown> spUnkTarget;
51 HRESULT hr = CreateInstanceTarget(&spUnkTarget);
52 ATLASSERT(SUCCEEDED(hr) && spUnkTarget != 0);
54 CComPtr<IUnknown> spUnkObject;
57 hr = BaseClass::CreateInstance(punkOuter, riid,
58 reinterpret_cast<void**>(&spUnkObject));
59 ATLASSERT(SUCCEEDED(hr) && spUnkObject != 0);
64 CComPtr<IPassthroughObject> spPassthroughObj;
65 hr = spUnkObject->QueryInterface(&spPassthroughObj);
66 ATLASSERT(SUCCEEDED(hr) && spPassthroughObj != 0);
69 hr = spPassthroughObj->SetTargetUnknown(spUnkTarget);
70 ATLASSERT(SUCCEEDED(hr));
76 *ppvObj = spUnkObject.Detach();
81 inline HRESULT CComClassFactoryProtocol::CreateInstanceTarget(
82 IUnknown** ppTargetProtocol)
84 ATLASSERT(ppTargetProtocol != 0);
85 if (!ppTargetProtocol)
89 *ppTargetProtocol = 0;
91 CComPtr<IClassFactory> spTargetCF;
92 HRESULT hr = GetTargetClassFactory(&spTargetCF);
93 ATLASSERT(SUCCEEDED(hr) && spTargetCF != 0);
96 hr = spTargetCF->CreateInstance(0, IID_IInternetProtocolRoot,
97 reinterpret_cast<void**>(ppTargetProtocol));
98 ATLASSERT(SUCCEEDED(hr) && *ppTargetProtocol != 0);
103 inline HRESULT CComClassFactoryProtocol::GetTargetClassFactory(
104 IClassFactory** ppCF)
106 ObjectLock lock(this);
107 return m_spTargetCF.CopyTo(ppCF);
110 inline HRESULT CComClassFactoryProtocol::SetTargetClassFactory(
113 HRESULT hr = (pCF ? pCF->LockServer(TRUE) : S_OK);
116 ObjectLock lock(this);
119 // LockServer(FALSE) is assumed to always succeed. Otherwise,
120 // it is impossible to implement correct semantics
121 HRESULT hr1 = m_spTargetCF->LockServer(FALSE);
123 ATLASSERT(SUCCEEDED(hr1));
130 inline HRESULT CComClassFactoryProtocol::SetTargetCLSID(REFCLSID clsid,
133 CComPtr<IClassFactory> spTargetCF;
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,
143 HINSTANCE urlmon = CoLoadLibrary(L"urlmon.dll", FALSE);
147 return HRESULT_FROM_WIN32(GetLastError());
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)
156 return HRESULT_FROM_WIN32(GetLastError());
159 HRESULT hr = dll_get_class_object(clsid,
161 reinterpret_cast<void**>(&spTargetCF));
162 CoFreeLibrary(urlmon);
164 HRESULT hr = CoGetClassObject(clsid, clsContext, 0, IID_IClassFactory,
165 reinterpret_cast<void**>(&spTargetCF));
167 ATLASSERT(SUCCEEDED(hr) && spTargetCF != 0);
170 hr = SetTargetClassFactory(spTargetCF);
171 ATLASSERT(SUCCEEDED(hr));
176 inline void CComClassFactoryProtocol::FinalRelease()
178 // No need to be thread safe here
181 // LockServer(FALSE) is assumed to always succeed.
182 HRESULT hr = m_spTargetCF->LockServer(FALSE);
184 ATLASSERT(SUCCEEDED(hr));
186 m_spTargetCF.Release();
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);
202 HRESULT hr = E_OUTOFMEMORY;
203 void* pv = static_cast<void*>(CreatorClass::CreateInstance);
204 FactoryComObject* p = 0;
205 ATLTRY(p = new FactoryComObject(pv))
209 p->InternalFinalConstructAddRef();
210 #if _ATL_VER >= 0x800 // gears - added by cprince
211 hr = p->_AtlInitialConstruct();
214 hr = p->FinalConstruct();
215 #if _ATL_VER >= 0x800 // gears - added by cprince
217 hr = p->_AtlFinalConstruct();
219 p->InternalFinalConstructRelease();
230 template <class Factory, class Protocol, class FactoryComObject>
231 inline HRESULT CMetaFactory<Factory, Protocol, FactoryComObject>::
232 CreateInstance(IClassFactory* pTargetCF, IClassFactory** ppCF)
241 HRESULT hr = CreateInstance(&pObj);
242 ATLASSERT(SUCCEEDED(hr) && pObj != 0);
247 hr = pObj->SetTargetClassFactory(pTargetCF);
248 ATLASSERT(SUCCEEDED(hr));
252 hr = pObj->QueryInterface(IID_IClassFactory,
253 reinterpret_cast<void**>(ppCF));
254 ATLASSERT(SUCCEEDED(hr) && *ppCF != 0);
262 template <class Factory, class Protocol, class FactoryComObject>
263 inline HRESULT CMetaFactory<Factory, Protocol, FactoryComObject>::
264 CreateInstance(REFCLSID clsidTarget, IClassFactory** ppCF)
273 HRESULT hr = CreateInstance(&pObj);
274 ATLASSERT(SUCCEEDED(hr) && pObj != 0);
279 hr = pObj->SetTargetCLSID(clsidTarget);
280 ATLASSERT(SUCCEEDED(hr));
284 hr = pObj->QueryInterface(IID_IClassFactory,
285 reinterpret_cast<void**>(ppCF));
286 ATLASSERT(SUCCEEDED(hr) && *ppCF != 0);
294 } // end namespace PassthroughAPP
296 #endif // GEARS_THIRD_PARTY_PASSTHRU_APP_PROTOCOLCF_INL__