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
  • 相关阅读:
    oracle的根容器下新建pdb容器及本地用户
    oracle监听配置与防火墙问题
    oracle问题:ORA-09817及解决办法
    Oracle:Ora-01652无法通过128(在temp表空间中)扩展temp段的过程-解决步骤
    oracle:ORA-14765建索引阻塞创建分区及处理步骤
    oracle-组合索引字段位置与查询效率之间的关系
    hbase的split策略和预分区
    启动hbase后hmaster自动关闭
    hive一级分区、二级分区、动态分区
    hive beeline连接和交互shell连接
  • 原文地址:https://www.cnblogs.com/csuftzzk/p/cocreateinstance_failed_0x80040154.html
Copyright © 2011-2022 走看看