Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

359 lines
10 KiB

  1. #include "urlmon.h"
  2. #include <stdio.h>
  3. void
  4. SystemMessage (
  5. LPTSTR szPrefix,
  6. HRESULT hr
  7. )
  8. {
  9. LPTSTR szMessage;
  10. if (HRESULT_FACILITY(hr) == FACILITY_WINDOWS)
  11. hr = HRESULT_CODE(hr);
  12. FormatMessage (
  13. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  14. FORMAT_MESSAGE_FROM_SYSTEM,
  15. NULL,
  16. hr,
  17. MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
  18. (LPTSTR) &szMessage,
  19. 0,
  20. NULL);
  21. printf ("%s: %s(%lx)\n", szPrefix, szMessage, hr);
  22. LocalFree(szMessage);
  23. }
  24. class CBindStatusCallback : public IBindStatusCallback
  25. {
  26. public:
  27. // IUnknown methods
  28. STDMETHODIMP QueryInterface(REFIID riid,void ** ppv);
  29. STDMETHODIMP_(ULONG) AddRef();
  30. STDMETHODIMP_(ULONG) Release();
  31. // IBindStatusCallback methods
  32. STDMETHODIMP OnStartBinding(DWORD grfBSCOption, IBinding* pbinding);
  33. STDMETHODIMP GetPriority(LONG* pnPriority);
  34. STDMETHODIMP OnLowResource(DWORD dwReserved);
  35. STDMETHODIMP OnProgress(ULONG ulProgress,
  36. ULONG ulProgressMax,
  37. ULONG ulStatusCode,
  38. LPCWSTR szStatusText);
  39. STDMETHODIMP OnStopBinding(HRESULT hrResult, LPCWSTR szError);
  40. STDMETHODIMP GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindinfo);
  41. STDMETHODIMP OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC *pfmtetc,
  42. STGMEDIUM* pstgmed);
  43. STDMETHODIMP OnObjectAvailable(REFIID riid, IUnknown* punk);
  44. // constructors/destructors
  45. CBindStatusCallback();
  46. private:
  47. long _cRef;
  48. HRESULT _hr;
  49. };
  50. int
  51. __cdecl
  52. main(
  53. int argc,
  54. char *argv[]
  55. )
  56. {
  57. if (argc!=2)
  58. {
  59. printf("Usage: CABINST <URL>\n");
  60. exit (E_INVALIDARG);
  61. }
  62. CoInitialize(NULL);
  63. HRESULT hr=S_OK;
  64. IBindCtx *pBC=NULL;
  65. //Synchronous call with bind context.
  66. CBindStatusCallback *pCallback = new CBindStatusCallback();
  67. if (!pCallback)
  68. {
  69. exit (-1);
  70. }
  71. hr = CreateAsyncBindCtx(0, pCallback, NULL, &pBC);
  72. WCHAR wszArg[_MAX_PATH];
  73. MultiByteToWideChar(CP_ACP, 0, argv[1], -1, wszArg, sizeof(wszArg)/sizeof(wszArg[0]));
  74. #if 1
  75. IUnknown* punk=NULL;
  76. hr=CoGetClassObjectFromURL (
  77. IID_IUnknown,
  78. wszArg,
  79. (DWORD) -1,(DWORD) -1, L"", pBC, CLSCTX_SERVER, NULL, IID_IUnknown, (void**) &punk);
  80. if (punk)
  81. {
  82. punk->Release();
  83. }
  84. #else
  85. typedef HRESULT (STDAPICALLTYPE *PFNASYNCGETCLASSBITS)(
  86. REFCLSID rclsid, // CLSID
  87. DWORD dwFileVersionMS, // CODE=http://foo#Version=a,b,c,d
  88. DWORD dwFileVersionLS, // MAKEDWORD(c,b) of above
  89. LPCWSTR szURL, // CODE= in INSERT tag
  90. IBindCtx *pbc, // bind ctx
  91. DWORD dwClsContext, // CLSCTX flags
  92. LPVOID pvReserved, // Must be NULL
  93. REFIID riid, // Usually IID_IClassFactory
  94. DWORD flags);
  95. PFNASYNCGETCLASSBITS pfnAsyncGetClassBits=NULL;
  96. HINSTANCE hDll;
  97. hDll = LoadLibraryEx("URLMON.DLL", NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
  98. if(hDll != 0)
  99. {
  100. pfnAsyncGetClassBits = (PFNASYNCGETCLASSBITS)
  101. GetProcAddress(hDll, "AsyncGetClassBits");
  102. if(pfnAsyncGetClassBits == 0)
  103. {
  104. hr = HRESULT_FROM_WIN32(GetLastError());
  105. IUnknown* punk=NULL;
  106. hr=CoGetClassObjectFromURL (
  107. IID_IUnknown,
  108. wszArg,
  109. (DWORD) -1,(DWORD) -1, L"", pBC, CLSCTX_SERVER, NULL, IID_IUnknown, (void**) &punk);
  110. if (punk)
  111. {
  112. punk->Release();
  113. }
  114. }
  115. else
  116. {
  117. hr = (*pfnAsyncGetClassBits)(
  118. IID_IUnknown, // bogus CLSID
  119. (DWORD) -1,(DWORD) -1, // don't care about version #
  120. wszArg, // URL/Path
  121. pBC, // Bind context with IBSC
  122. CLSCTX_SERVER,
  123. NULL,
  124. IID_IClassFactory,
  125. 0); // 1 == CD_FLAGS_FORCE_DOWNLOAD
  126. }
  127. FreeLibrary(hDll);
  128. }
  129. else
  130. {
  131. hr = HRESULT_FROM_WIN32(GetLastError());
  132. }
  133. #endif
  134. if (hr==MK_S_ASYNCHRONOUS)
  135. {
  136. MSG msg;
  137. while (GetMessage(&msg, NULL, 0,0))
  138. {
  139. TranslateMessage(&msg);
  140. DispatchMessage(&msg);
  141. }
  142. hr=msg.wParam;
  143. }
  144. if (hr==REGDB_E_CLASSNOTREG)
  145. {
  146. hr=S_OK; // Ignore instantiation error since we are asking for IID_IUnknown...
  147. }
  148. if (FAILED(hr))
  149. {
  150. SystemMessage("Unable to install CAB file", hr);
  151. }
  152. pCallback->Release();
  153. pBC->Release();
  154. CoUninitialize();
  155. return hr;
  156. }
  157. // ===========================================================================
  158. // CBindStatusCallback Implementation
  159. // ===========================================================================
  160. //+---------------------------------------------------------------------------
  161. //
  162. // Method: CBindStatusCallback::CBindStatusCallback
  163. //
  164. // Synopsis: Creates a bind status callback object.
  165. //
  166. //----------------------------------------------------------------------------
  167. CBindStatusCallback::CBindStatusCallback()
  168. : _cRef(1), _hr(MK_S_ASYNCHRONOUS)
  169. {
  170. }
  171. //+---------------------------------------------------------------------------
  172. //
  173. // Method: CBindStatusCallback::QueryInterface
  174. //
  175. // Synopsis: Gets an interface pointer to the bind status callback object.
  176. //
  177. //----------------------------------------------------------------------------
  178. STDMETHODIMP
  179. CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
  180. {
  181. HRESULT hr = S_OK;
  182. *ppv = NULL;
  183. if(IsEqualIID(riid, IID_IUnknown) ||
  184. IsEqualIID(riid, IID_IBindStatusCallback))
  185. {
  186. AddRef();
  187. *ppv = (IBindStatusCallback *) this;
  188. }
  189. else
  190. {
  191. hr = E_NOINTERFACE;
  192. }
  193. return hr;
  194. }
  195. //+---------------------------------------------------------------------------
  196. //
  197. // Method: CBindStatusCallback::AddRef
  198. //
  199. // Synopsis: Increments the reference count.
  200. //
  201. //----------------------------------------------------------------------------
  202. STDMETHODIMP_(ULONG)
  203. CBindStatusCallback::AddRef()
  204. {
  205. InterlockedIncrement((long *) &_cRef);
  206. return _cRef;
  207. }
  208. //+---------------------------------------------------------------------------
  209. //
  210. // Method: CBindStatusCallback::Release
  211. //
  212. // Synopsis: Decrements the reference count.
  213. //
  214. //----------------------------------------------------------------------------
  215. STDMETHODIMP_(ULONG)
  216. CBindStatusCallback::Release()
  217. {
  218. LONG count = _cRef - 1;
  219. if(0 == InterlockedDecrement((long *) &_cRef))
  220. {
  221. delete this;
  222. count = 0;
  223. }
  224. return count;
  225. }
  226. // ---------------------------------------------------------------------------
  227. // %%Function: CBindStatusCallback::OnStartBinding
  228. // ---------------------------------------------------------------------------
  229. STDMETHODIMP
  230. CBindStatusCallback::OnStartBinding(DWORD grfBSCOption, IBinding* pbinding)
  231. {
  232. return(NOERROR);
  233. }
  234. // ---------------------------------------------------------------------------
  235. // %%Function: CBindStatusCallback::GetPriority
  236. // ---------------------------------------------------------------------------
  237. STDMETHODIMP
  238. CBindStatusCallback::GetPriority(LONG* pnPriority)
  239. {
  240. return(NOERROR);
  241. }
  242. // ---------------------------------------------------------------------------
  243. // %%Function: CBindStatusCallback::OnLowResource
  244. // ---------------------------------------------------------------------------
  245. STDMETHODIMP
  246. CBindStatusCallback::OnLowResource(DWORD dwReserved)
  247. {
  248. return(NOERROR);
  249. }
  250. // ---------------------------------------------------------------------------
  251. // %%Function: CBindStatusCallback::OnStopBinding
  252. // ---------------------------------------------------------------------------
  253. STDMETHODIMP
  254. CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR pszError)
  255. {
  256. _hr = hrStatus;
  257. PostQuitMessage(hrStatus);
  258. return(NOERROR);
  259. }
  260. // ---------------------------------------------------------------------------
  261. // %%Function: CBindStatusCallback::GetBindInfo
  262. // ---------------------------------------------------------------------------
  263. STDMETHODIMP
  264. CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
  265. {
  266. return (NOERROR);
  267. }
  268. // ---------------------------------------------------------------------------
  269. // %%Function: CBindStatusCallback::OnDataAvailable
  270. // This function is called whenever data starts arriving. When the file download is
  271. // complete then the BSCF_LASTDATANOTIFICATION comes and you can get the local cached
  272. // File Name.
  273. // ---------------------------------------------------------------------------
  274. STDMETHODIMP
  275. CBindStatusCallback::OnDataAvailable
  276. (
  277. DWORD grfBSCF,
  278. DWORD dwSize,
  279. FORMATETC* pfmtetc,
  280. STGMEDIUM* pstgmed
  281. )
  282. {
  283. return(NOERROR);
  284. }
  285. // ---------------------------------------------------------------------------
  286. // %%Function: CBindStatusCallback::OnObjectAvailable
  287. // ---------------------------------------------------------------------------
  288. STDMETHODIMP
  289. CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown* punk)
  290. {
  291. return(NOERROR);
  292. }
  293. // ---------------------------------------------------------------------------
  294. // %%Function: CBindStatusCallback::OnProgress
  295. // ---------------------------------------------------------------------------
  296. STDMETHODIMP
  297. CBindStatusCallback::OnProgress
  298. (
  299. ULONG ulProgress,
  300. ULONG ulProgressMax,
  301. ULONG ulStatusCode,
  302. LPCWSTR pwzStatusText
  303. )
  304. {
  305. return(NOERROR);
  306. }