zoukankan      html  css  js  c++  java
  • CoCreateInstance调用返回代码0x80040154的一种解决方法

    引言

          前面的一篇博文中总结了开发Windows Thumbnail Handler的一些经验。在公司实际项目中,需要同时针对图片和视频实现缩略图。同时还要在图片和视频文件的顶部加上LOGO。像如下这样的:

          

          于是考虑了一下实现方案:
          (1)LOGO资源采用Base64编码编译到DLL中去
          (2)公司自有的图片和视频文件进行全景拼接时依赖一串参数,而这串参数需要从文件中提取。因此采用RecipeThumbnailProvider实现IInitializeWithFile接口比较合适,这样能得到文件路径,具备更灵活的可操作性。
          (3)LOGO资源使用Windows自带的解码库来进行解码,也就是Windows Image Component(WIC).
          这么一思考,还是挺靠谱的。于是就动手开始编码,编写了一个解码LOGO资源的函数:
    /** 
     * Decode the Base64-encoded string to get logo resources.
     */
    HRESULT RecipeThumbnailProvider::GetLogoFromString(LPCWSTR encodedString, UINT* width, UINT* height, PBYTE* rawPixels)
    {
    	IStream* pImageStream = NULL;
    	HRESULT hr = E_FAIL;
    	DWORD dwDecodedImageSize = 0;
    	DWORD dwSkipChars = 0;
    	DWORD dwActualFormat = 0;
    
    	if (CryptStringToBinary(encodedString, NULL, CRYPT_STRING_BASE64, NULL, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
    	{
    		BYTE* pbDecodedImage = static_cast<BYTE*>(LocalAlloc(LPTR, dwDecodedImageSize));
    		if (pbDecodedImage)
    		{
    			if (CryptStringToBinary(encodedString, lstrlen(encodedString), CRYPT_STRING_BASE64, pbDecodedImage, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
    			{
    				pImageStream = SHCreateMemStream(pbDecodedImage, dwDecodedImageSize);
    				if (pImageStream != NULL)
    				{
    					IWICImagingFactory* pImageFactory;
    					hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImageFactory));
    					LOGINFO(L"CoCreateIntance() returns 0x%x", hr);
    					if (SUCCEEDED(hr))
    					{
    						IWICBitmapDecoder* pDecoder;
    						hr = pImageFactory->CreateDecoderFromStream(pImageStream, &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, &pDecoder);
    						if (SUCCEEDED(hr))
    						{
    							IWICBitmapFrameDecode* pBitmapFrameDecode;
    							hr = pDecoder->GetFrame(0, &pBitmapFrameDecode);
    							if (SUCCEEDED(hr))
    							{
    								IWICBitmapSource* pBitmapSourceConverted = NULL;
    								WICPixelFormatGUID guidPixelFormatSource;
    								hr = pBitmapFrameDecode->GetPixelFormat(&guidPixelFormatSource);
    								if (SUCCEEDED(hr) && (guidPixelFormatSource != GUID_WICPixelFormat24bppBGR))
    								{
    									IWICFormatConverter* pFormatConverter;
    									hr = pImageFactory->CreateFormatConverter(&pFormatConverter);
    									if (SUCCEEDED(hr))
    									{
    										hr = pFormatConverter->Initialize(pBitmapFrameDecode, GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone, NULL, 0, WICBitmapPaletteTypeCustom);
    										if (SUCCEEDED(hr))
    										{
    											hr = pFormatConverter->QueryInterface(&pBitmapSourceConverted);
    										}
    										pFormatConverter->Release();
    									}
    								}
    								else
    								{
    									hr = pBitmapFrameDecode->QueryInterface(&pBitmapSourceConverted);
    								}
    								if (SUCCEEDED(hr))
    								{
    									hr = pBitmapSourceConverted->GetSize(width, height);
    									if (SUCCEEDED(hr))
    									{
    										WICRect rect = { 0, 0, *width, *height };
    										*rawPixels = static_cast<BYTE*>(LocalAlloc(LPTR, (*width)*(*height)*3));
    										hr = pBitmapSourceConverted->CopyPixels(&rect, (*width) * 3, (*width)*(*height) * 3, *rawPixels);
    									}
    									else
    									{
    										*width = 0;
    										*height = 0;
    										*rawPixels = NULL; 
    									}
    									pBitmapSourceConverted->Release();
    								}
    								pBitmapFrameDecode->Release();
    							}
    							pDecoder->Release();
    						}
    						pImageFactory->Release();
    					}
    					pImageStream->Release();
    				}
    			}
    		}
    
    		LocalFree(pbDecodedImage);
    	}
    	return hr;
    }
    

      当我注册好COM组件开始使用时,在本机上测试简直完美。满以为就这么搞定了,然而并么有。在另外一台Win7机器上测试时,缩略图中并没有出现想象中的LOGO。一看日志文件,发现一直在报:CoCreateInstance()调用返回0x80040154。于是下面的代码都没执行,LOGO资源自然没有加载成功了。那么CoCreateInstance()为啥会返回0x80040154呢?这个代码又意味着什么嗯?从网上的搜索结果来看,0x80040154是表示"Class Not Registered"。也就是说COM类并没有注册,在注册表HKEY_CLASSES_ROOTCLSID下面也就没有类ID了。我们程序中使用了WIC组件来解码图片,那么难道是WIC组件类没有注册吗?

          再一想,开发时采用的一直是Windows10,可以正常运行。到了Windows7上为啥就不行了呢?难道是WIC在Windows7上不支持?这个怀疑显然是不成立的,从MSDN上来看从XP SP2就开始支持了啊:
          那么难道是参数给的不对?以CLSID_WICImagingFactory为关键字一搜索果然搜到了一篇帖子CLSID_WICImagingFactory在Windows10上被解析为了CLSID_WICImagingFactory2:
          而这个GUID在Windows7上是不存在的(搜索注册表即可看到结果):
          自然CoCreateInstance()调用就会返回0x80040154了。解决方案就是传递CLSID_WICImagingFactory1给CoCreateInstance()。这样就能同时兼容Windows10和Windows7了。

    参考链接

    1. http://stackoverflow.com/questions/16697112/why-using-wic-in-my-32-bit-application-fails-in-windows-7-32-bit
  • 相关阅读:
    有点忙啊
    什么是协程
    HDU 1110 Equipment Box (判断一个大矩形里面能不能放小矩形)
    HDU 1155 Bungee Jumping(物理题,动能公式,弹性势能公式,重力势能公式)
    HDU 1210 Eddy's 洗牌问题(找规律,数学)
    HDU1214 圆桌会议(找规律,数学)
    HDU1215 七夕节(模拟 数学)
    HDU 1216 Assistance Required(暴力打表)
    HDU 1220 Cube(数学,找规律)
    HDU 1221 Rectangle and Circle(判断圆和矩形是不是相交)
  • 原文地址:https://www.cnblogs.com/csuftzzk/p/cocreateinstance_failed_0x80040154.html
Copyright © 2011-2022 走看看