Leaked source code of windows server 2003
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.

486 lines
13 KiB

  1. // GifConv.cpp : Implementation of CICWGifConvert
  2. #include "pre.h"
  3. #include "webvwids.h"
  4. /////////////////////////////////////////////////////////////////////////////
  5. // CICWGifConvert
  6. //+----------------------------------------------------------------------------
  7. //
  8. // Function CICWGifConvert:CICWGifConvert
  9. //
  10. // Synopsis This is the constructor, nothing fancy
  11. //
  12. //-----------------------------------------------------------------------------
  13. CICWGifConvert::CICWGifConvert
  14. (
  15. CServer* pServer
  16. )
  17. {
  18. TraceMsg(TF_CWEBVIEW, "CICWGifConvert constructor called");
  19. m_lRefCount = 0;
  20. // Assign the pointer to the server control object.
  21. m_pServer = pServer;
  22. }
  23. //+----------------------------------------------------------------------------
  24. //
  25. // Function CICWGifConvert::QueryInterface
  26. //
  27. // Synopsis This is the standard QI, with support for
  28. // IID_Unknown, IICW_Extension and IID_ICWApprentice
  29. // (stolen from Inside COM, chapter 7)
  30. //
  31. //
  32. //-----------------------------------------------------------------------------
  33. HRESULT CICWGifConvert::QueryInterface( REFIID riid, void** ppv )
  34. {
  35. TraceMsg(TF_CWEBVIEW, "CICWGifConvert::QueryInterface");
  36. if (ppv == NULL)
  37. return(E_INVALIDARG);
  38. *ppv = NULL;
  39. // IID_IICWGifConvert
  40. if (IID_IICWGifConvert == riid)
  41. *ppv = (void *)(IICWGifConvert *)this;
  42. // IID_IUnknown
  43. else if (IID_IUnknown == riid)
  44. *ppv = (void *)this;
  45. else
  46. return(E_NOINTERFACE);
  47. ((LPUNKNOWN)*ppv)->AddRef();
  48. return(S_OK);
  49. }
  50. //+----------------------------------------------------------------------------
  51. //
  52. // Function CICWGifConvert::AddRef
  53. //
  54. // Synopsis This is the standard AddRef
  55. //
  56. //
  57. //-----------------------------------------------------------------------------
  58. ULONG CICWGifConvert::AddRef( void )
  59. {
  60. TraceMsg(TF_CWEBVIEW, "CICWGifConvert::AddRef %d", m_lRefCount + 1);
  61. return InterlockedIncrement(&m_lRefCount) ;
  62. }
  63. //+----------------------------------------------------------------------------
  64. //
  65. // Function CICWGifConvert::Release
  66. //
  67. // Synopsis This is the standard Release
  68. //
  69. //
  70. //-----------------------------------------------------------------------------
  71. ULONG CICWGifConvert::Release( void )
  72. {
  73. ASSERT( m_lRefCount > 0 );
  74. InterlockedDecrement(&m_lRefCount);
  75. TraceMsg(TF_CWEBVIEW, "CICWGifConvert::Release %d", m_lRefCount);
  76. if( 0 == m_lRefCount )
  77. {
  78. if (NULL != m_pServer)
  79. m_pServer->ObjectsDown();
  80. delete this;
  81. return 0;
  82. }
  83. return( m_lRefCount );
  84. }
  85. void CALLBACK ImgCtx_Callback(void * pIImgCtx, void* pfDone);
  86. HRESULT CICWGifConvert::GifToBitmap(TCHAR * pszFile, HBITMAP* phBitmap)
  87. {
  88. HRESULT hr = E_FAIL; //don't assume success
  89. ULONG fState;
  90. SIZE sz;
  91. IImgCtx* pIImgCtx;
  92. BSTR bstrFile = A2W(pszFile);
  93. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  94. IID_IImgCtx, (void**)&pIImgCtx);
  95. BOOL bCoInit = FALSE;
  96. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  97. SUCCEEDED(CoInitialize(NULL)))
  98. {
  99. bCoInit = TRUE;
  100. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  101. IID_IImgCtx, (void**)&pIImgCtx);
  102. }
  103. if (SUCCEEDED(hr))
  104. {
  105. ASSERT(pIImgCtx);
  106. hr = SynchronousDownload(pIImgCtx, bstrFile);
  107. pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
  108. if (SUCCEEDED(hr))
  109. {
  110. ASSERT(pIImgCtx);
  111. HDC hdcScreen = GetDC(NULL);
  112. if (hdcScreen)
  113. {
  114. *phBitmap = CreateCompatibleBitmap(hdcScreen, sz.cx, sz.cy);
  115. if (*phBitmap)
  116. {
  117. HDC hdcImgDst = CreateCompatibleDC(NULL);
  118. if (hdcImgDst)
  119. {
  120. HGDIOBJ hbmOld = SelectObject(hdcImgDst, *phBitmap);
  121. if (hbmOld)
  122. {
  123. hr = StretchBltImage(pIImgCtx, &sz, hdcImgDst);
  124. SelectObject(hdcImgDst, hbmOld);
  125. }
  126. DeleteDC(hdcImgDst);
  127. }
  128. }
  129. ReleaseDC(NULL, hdcScreen);
  130. }
  131. }
  132. pIImgCtx->Release();
  133. }
  134. if (bCoInit)
  135. CoUninitialize();
  136. return hr;
  137. }
  138. HRESULT CICWGifConvert::GifToIcon(TCHAR * pszFile, UINT nIconSize, HICON* phIcon)
  139. {
  140. HRESULT hr = E_FAIL; //don't assume success
  141. SIZE Size;
  142. if (0 != nIconSize)
  143. {
  144. Size.cx = nIconSize;
  145. Size.cy = nIconSize;
  146. }
  147. IImgCtx* pIImgCtx;
  148. ULONG fState;
  149. BSTR bstrFile = A2W(pszFile);
  150. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  151. IID_IImgCtx, (void**)&pIImgCtx);
  152. BOOL bCoInit = FALSE;
  153. if ((CO_E_NOTINITIALIZED == hr || REGDB_E_IIDNOTREG == hr) &&
  154. SUCCEEDED(CoInitialize(NULL)))
  155. {
  156. bCoInit = TRUE;
  157. hr = CoCreateInstance(CLSID_IImgCtx, NULL, CLSCTX_INPROC_SERVER,
  158. IID_IImgCtx, (void**)&pIImgCtx);
  159. }
  160. if (SUCCEEDED(hr))
  161. {
  162. ASSERT(pIImgCtx);
  163. hr = SynchronousDownload(pIImgCtx, bstrFile);
  164. if (0 == nIconSize)
  165. {
  166. pIImgCtx->GetStateInfo(&fState, &Size, TRUE);
  167. }
  168. if (SUCCEEDED(hr))
  169. {
  170. *phIcon = ExtractImageIcon(&Size, pIImgCtx);
  171. }
  172. pIImgCtx->Release();
  173. }
  174. if (bCoInit)
  175. CoUninitialize();
  176. return hr;
  177. }
  178. HRESULT CICWGifConvert::SynchronousDownload(IImgCtx* pIImgCtx, BSTR bstrFile)
  179. {
  180. ASSERT(pIImgCtx);
  181. HRESULT hr;
  182. hr = pIImgCtx->Load(bstrFile, 0);
  183. if (SUCCEEDED(hr))
  184. {
  185. ULONG fState;
  186. SIZE sz;
  187. pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
  188. if (!(fState & (IMGLOAD_COMPLETE | IMGLOAD_ERROR)))
  189. {
  190. BOOL fDone = FALSE;
  191. hr = pIImgCtx->SetCallback(ImgCtx_Callback, &fDone);
  192. if (SUCCEEDED(hr))
  193. {
  194. hr = pIImgCtx->SelectChanges(IMGCHG_COMPLETE, 0, TRUE);
  195. if (SUCCEEDED(hr))
  196. {
  197. MSG msg;
  198. BOOL fMsg;
  199. // HACK: restrict the message pump to those messages we know that URLMON and
  200. // HACK: the imageCtx stuff needs, otherwise we will be pumping messages for
  201. // HACK: windows we shouldn't be pumping right now...
  202. while(!fDone )
  203. {
  204. fMsg = PeekMessage(&msg, NULL, WM_USER + 1, WM_USER + 4, PM_REMOVE );
  205. if (!fMsg)
  206. fMsg = PeekMessage( &msg, NULL, WM_APP + 2, WM_APP + 2, PM_REMOVE );
  207. if (!fMsg)
  208. {
  209. // go to sleep until we get a new message....
  210. WaitMessage();
  211. continue;
  212. }
  213. TranslateMessage(&msg);
  214. DispatchMessage(&msg);
  215. }
  216. }
  217. }
  218. pIImgCtx->Disconnect();
  219. }
  220. hr = pIImgCtx->GetStateInfo(&fState, &sz, TRUE);
  221. if (SUCCEEDED(hr))
  222. hr = (fState & IMGLOAD_COMPLETE) ? S_OK : E_FAIL;
  223. }
  224. return hr;
  225. }
  226. HICON CICWGifConvert::ExtractImageIcon(SIZE* pSize, IImgCtx * pIImgCtx)
  227. {
  228. ASSERT(pIImgCtx);
  229. HICON hiconRet = NULL;
  230. HDC hdcScreen = GetDC(NULL);
  231. if (hdcScreen)
  232. {
  233. HBITMAP hbmImage = CreateCompatibleBitmap(hdcScreen, pSize->cx, pSize->cy);
  234. if (hbmImage)
  235. {
  236. HBITMAP hbmMask = CreateBitmap(pSize->cx, pSize->cy, 1, 1, NULL);
  237. if (hbmMask)
  238. {
  239. SIZE sz;
  240. sz.cx = pSize->cx;
  241. sz.cy = pSize->cy;
  242. if (SUCCEEDED(CreateImageAndMask(pIImgCtx, hdcScreen, &sz,
  243. &hbmImage, &hbmMask)))
  244. {
  245. ICONINFO ii;
  246. ii.fIcon = TRUE;
  247. ii.hbmMask = hbmMask;
  248. ii.hbmColor = hbmImage;
  249. hiconRet = CreateIconIndirect(&ii);
  250. }
  251. DeleteObject(hbmMask);
  252. }
  253. DeleteObject(hbmImage);
  254. }
  255. ReleaseDC(NULL, hdcScreen);
  256. }
  257. return hiconRet;
  258. }
  259. HRESULT CICWGifConvert::CreateImageAndMask(IImgCtx * pIImgCtx,
  260. HDC hdcScreen,
  261. SIZE * pSize,
  262. HBITMAP * phbmImage,
  263. HBITMAP * phbmMask)
  264. {
  265. ASSERT(pIImgCtx);
  266. ASSERT(phbmImage);
  267. ASSERT(phbmMask);
  268. HRESULT hr = E_FAIL;
  269. HDC hdcImgDst = CreateCompatibleDC(NULL);
  270. if (hdcImgDst)
  271. {
  272. HGDIOBJ hbmOld = SelectObject(hdcImgDst, *phbmImage);
  273. if (hbmOld)
  274. {
  275. if (ColorFill(hdcImgDst, pSize, COLOR1))
  276. {
  277. hr = StretchBltImage(pIImgCtx, pSize, hdcImgDst);
  278. if (SUCCEEDED(hr))
  279. {
  280. hr = CreateMask(pIImgCtx, hdcScreen, hdcImgDst, pSize,
  281. phbmMask);
  282. }
  283. }
  284. SelectObject(hdcImgDst, hbmOld);
  285. }
  286. DeleteDC(hdcImgDst);
  287. }
  288. return hr;
  289. }
  290. HRESULT CICWGifConvert::StretchBltImage(IImgCtx * pIImgCtx, const SIZE * pSize, HDC hdcDst)
  291. {
  292. ASSERT(pIImgCtx);
  293. ASSERT(hdcDst);
  294. HRESULT hr;
  295. SIZE sz;
  296. ULONG fState;
  297. hr = pIImgCtx->GetStateInfo(&fState, &sz, FALSE);
  298. if (SUCCEEDED(hr))
  299. {
  300. hr = pIImgCtx->StretchBlt(hdcDst, 0, 0, pSize->cx, pSize->cy, 0, 0,
  301. sz.cx, sz.cy, SRCCOPY);
  302. ASSERT(SUCCEEDED(hr) && "Icon extraction pIImgCtx->StretchBlt failed!");
  303. }
  304. return hr;
  305. }
  306. HRESULT CICWGifConvert::CreateMask(IImgCtx * pIImgCtx, HDC hdcScreen, HDC hdc1, const SIZE * pSize, HBITMAP * phbMask)
  307. {
  308. ASSERT(hdc1);
  309. ASSERT(pSize);
  310. ASSERT(phbMask);
  311. HRESULT hr = E_FAIL;
  312. HDC hdc2 = CreateCompatibleDC(NULL);
  313. if (hdc2)
  314. {
  315. HBITMAP hbm2 = CreateCompatibleBitmap(hdcScreen, pSize->cx, pSize->cy);
  316. if (hbm2)
  317. {
  318. HGDIOBJ hbmOld2 = SelectObject(hdc2, hbm2);
  319. if (hbmOld2)
  320. {
  321. ColorFill(hdc2, pSize, COLOR2);
  322. hr = StretchBltImage(pIImgCtx, pSize, hdc2);
  323. if (SUCCEEDED(hr) &&
  324. BitBlt(hdc2, 0, 0, pSize->cx, pSize->cy, hdc1, 0, 0,
  325. SRCINVERT))
  326. {
  327. if (GetDeviceCaps(hdcScreen, BITSPIXEL) <= 8)
  328. {
  329. //
  330. // 6 is the XOR of the index for COLOR1 and the index
  331. // for COLOR2.
  332. //
  333. SetBkColor(hdc2, PALETTEINDEX(6));
  334. }
  335. else
  336. {
  337. SetBkColor(hdc2, (COLORREF)(COLOR1 ^ COLOR2));
  338. }
  339. HDC hdcMask = CreateCompatibleDC(NULL);
  340. if (hdcMask)
  341. {
  342. HGDIOBJ hbmOld = SelectObject(hdcMask, *phbMask);
  343. if (hbmOld)
  344. {
  345. if (BitBlt(hdcMask, 0, 0, pSize->cx, pSize->cy, hdc2, 0,
  346. 0, SRCCOPY))
  347. {
  348. //
  349. // RasterOP 0x00220326 does a copy of the ~mask bits
  350. // of hdc1 and sets everything else to 0 (Black).
  351. //
  352. if (BitBlt(hdc1, 0, 0, pSize->cx, pSize->cy, hdcMask,
  353. 0, 0, 0x00220326))
  354. {
  355. hr = S_OK;
  356. }
  357. }
  358. SelectObject(hdcMask, hbmOld);
  359. }
  360. DeleteDC(hdcMask);
  361. }
  362. }
  363. SelectObject(hdc2, hbmOld2);
  364. }
  365. DeleteObject(hbm2);
  366. }
  367. DeleteDC(hdc2);
  368. }
  369. return hr;
  370. }
  371. BOOL CICWGifConvert::ColorFill(HDC hdc, const SIZE * pSize, COLORREF clr)
  372. {
  373. ASSERT(hdc);
  374. BOOL fRet = FALSE;
  375. HBRUSH hbSolid = CreateSolidBrush(clr);
  376. if (hbSolid)
  377. {
  378. HGDIOBJ hbOld = SelectObject(hdc, hbSolid);
  379. if (hbOld)
  380. {
  381. PatBlt(hdc, 0, 0, pSize->cx, pSize->cy, PATCOPY);
  382. fRet = TRUE;
  383. SelectObject(hdc, hbOld);
  384. }
  385. DeleteObject(hbSolid);
  386. }
  387. return fRet;
  388. }
  389. void CALLBACK ImgCtx_Callback(void* pIImgCtx,void* pfDone)
  390. {
  391. ASSERT(pfDone);
  392. *(BOOL*)pfDone = TRUE;
  393. return;
  394. }