CoCreateInstance of IWICImagingFactory - c++

I am running Visual Studio 2012 on my Windows 7 machine.
When I run the SimpleDirect2dApplication found here : http://technet.microsoft.com/en-us/subscriptions/dd940321%28v=vs.85%29.aspx
hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&m_pWICFactory)
);
the CoCreateInstance fails with a "Class Not Registered" and the ptr to the factory is 0.
Any help would be appreciated.

According to an answer in a Microsoft's forum a breaking change in the Windows SDK 8.0 requires you to define _WIN32_WINNT to 0x0600 for backward compatibility with Windows Vista or to 0x0601 for backward compatibily with Windows 7.

Here's the code I use to handle WIC creation for both WIC and WIC2 scenarios:
namespace
{
bool g_WIC2 = false;
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID *ifactory) noexcept
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}
}
bool IsWIC2() noexcept
{
return g_WIC2;
}
IWICImagingFactory* GetWIC() noexcept
{
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
IWICImagingFactory* factory = nullptr;
if (!InitOnceExecuteOnce(
&s_initOnce,
InitializeWICFactory,
nullptr,
reinterpret_cast<LPVOID*>(&factory)))
{
return nullptr;
}
return factory;
}
This handles creating the factory once from any thread. You use it by just calling:
auto pWIC = GetWIC();
if (!pWIC)
// error
For those few cases where you care about WIC vs. WIC2, you use IsWIC2:
if (targetFormat && memcmp(&guidContainerFormat, &GUID_ContainerFormatBmp, sizeof(WICPixelFormatGUID)) == 0 && IsWIC2())
{
// Opt-in to the WIC2 support for writing 32-bit Windows BMP files with an alpha channel
PROPBAG2 option = {};
option.pstrName = const_cast<wchar_t*>(L"EnableV5Header32bppBGRA");
VARIANT varValue;
varValue.vt = VT_BOOL;
varValue.boolVal = VARIANT_TRUE;
(void)props->Write(1, &option, &varValue);
}
I had use a C++11 lambda for this code in the past, but clang/LLVM doesn't like it so much.

using this
#if defined(CLSID_WICImagingFactory)
#undef CLSID_WICImagingFactory
#endif
and then you may pass this
Refer:
http://skia.googlecode.com/svn/trunk/src/ports/SkImageDecoder_WIC.cpp

Related

Can't query IDirect3D7 from IDirectDraw7 in Win10

I'm trying the following code:
hr = ddr7->QueryInterface(IID_IDirect3D7,(void**)&d3d7)
the hr returned is E_NOINTERFACE, how does this happen?
On my Windows 10 system Version 1909 (18363) [x64], this worked fine:
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <ddraw.h>
#include <d3d.h>
typedef HRESULT ( WINAPI* LPDIRECTDRAWCREATEEX )( GUID FAR * lpGuid, LPVOID *lplpDD, REFIID iid,IUnknown FAR *pUnkOuter );
void main()
{
HINSTANCE hInstDDraw = nullptr;
LPDIRECTDRAW pDDraw = nullptr;
hInstDDraw = LoadLibraryW( L"ddraw.dll" );
if( hInstDDraw )
{
auto pDDCreate = reinterpret_cast<LPDIRECTDRAWCREATEEX>(GetProcAddress( hInstDDraw, "DirectDrawCreateEx" ) );
if (pDDCreate)
{
HRESULT hr = pDDCreate(nullptr, reinterpret_cast<LPVOID*>(&pDDraw), IID_IDirectDraw7, nullptr);
if (SUCCEEDED(hr))
{
LPDIRECT3D7 d3d7 = nullptr;
hr = pDDraw->QueryInterface(IID_IDirect3D7, reinterpret_cast<LPVOID*>(&d3d7));
if (SUCCEEDED(hr))
{
printf("Worked\n");
return;
}
else
{
printf("QI Failed: %08X\n", static_cast<int>(hr));
}
}
else
{
printf("DDCreate Failed: %08X\n", static_cast<int>(hr));
}
}
FreeLibrary( hInstDDraw );
}
printf("Failed\n");
}
You should make sure the HRESULT from your call to DirectDrawCreateEx worked. Also, it's possible it could be an issue with your drivers or setup.
Your original question really should include more code, particularly the DirectDrawCreateEx since the QueryInterface alone isn't particularly informative.
Happens to me too, works fine on 32bit application but fails on 64bit application. I'm on Windows 10 x64 version 10.0.18363.1082. As others already commented, D3D7 is already obsolete.

WIC factory will always be nullptr on windows7 (used "What's a Creel?" tutorial)

I used this tutorial and i always got an error that says "wicFactory was nullptr". I'm using windows 7 and this code doesn't make it work. I've read that you should use CLSID_WICImagingfactory1 But it doesn't work.
this is my code:
HRESULT hr;
bmp = nullptr;
IWICBitmapDecoder *pDecoder = NULL;
IWICBitmapFrameDecode *pSource = NULL;
IWICFormatConverter *pConverter = NULL;
//Creating a factory
IWICImagingFactory *wicFactory = NULL;
CoCreateInstance(
CLSID_WICImagingFactory1,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&wicFactory);
MessageBox(NULL, (LPCWSTR)wicFactory, NULL, MB_OK);
//Creating a decoder
hr = wicFactory->CreateDecoderFromFilename(
filename,
NULL,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
&pDecoder);
//Read Frame from image
if (SUCCEEDED(hr)) {
// Create the initial frame.
hr = pDecoder->GetFrame(0, &pSource);
}
//Creating a Converter
if (SUCCEEDED(hr)) {
// Convert the image format to 32bppPBGRA
// (DXGI_FORMAT_B8G8R8A8_UNORM + D2D1_ALPHA_MODE_PREMULTIPLIED).
hr = wicFactory->CreateFormatConverter(&pConverter);
}
//Setup the converter
if (SUCCEEDED(hr)) {
hr = pConverter->Initialize(
pSource,
GUID_WICPixelFormat32bppPBGRA,
WICBitmapDitherTypeNone,
NULL,
0.0f,
WICBitmapPaletteTypeMedianCut
);
}
//Use the converter to create an D2D1Bitmap
//ID2D1Bitmap* bmp;
if (SUCCEEDED(hr))
{
hr = d2dg->pRT->CreateBitmapFromWicBitmap(
pConverter,
NULL,
&bmp
);
}
if (wicFactory)wicFactory->Release();
if (pDecoder)pDecoder->Release();
if (pConverter)pConverter->Release();
if (pSource)pSource->Release();
Can anyone Identify the issue here? I cant find any more information about that problem other then define _WIN32_WINNT to 0x0600 or 0x0601, still that wont help...
As noted in the comments, you need to call CoInitializeEx before you can call CoCreateInstance.
BTW, here's some robust code for creating a WIC factory that handles the "WIC2" vs. "WIC1" down-level scenario for Windows 7 with or without the KB2670838 update:
namespace
{
bool g_WIC2 = false;
BOOL WINAPI InitializeWICFactory(PINIT_ONCE, PVOID, PVOID *ifactory) noexcept
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
ifactory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
g_WIC2 = false;
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
g_WIC2 = false;
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
ifactory)) ? TRUE : FALSE;
#endif
}
}
IWICImagingFactory* GetWICFactory(bool& iswic2) noexcept
{
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
IWICImagingFactory* factory = nullptr;
if (!InitOnceExecuteOnce(&s_initOnce,
InitializeWICFactory,
nullptr,
reinterpret_cast<LPVOID*>(&factory)))
{
return nullptr;
}
iswic2 = g_WIC2;
return factory;
}
For details on what's in WIC2, see Microsoft Docs. I support both in DirectXTex to get 32bpp BMP with alpha (BITMAPV5HEADER) and support for 96bp TIFF (GUID_WICPixelFormat96bppRGBFloat) when WIC2 is installed.
You can use WIC2 on Windows 7 if installed, which you enable by building with /D_WIN32_WINNT=0x0601 /D_WIN7_PLATFORM_UPDATE.

How to instantiate the IWebViewControl in MFC or C++?

Recently Microsoft has introduced IWebViewControl for WPF and winforms.
IWebViewControl uses the Edge rendering engine.
It is very easy to instantiate the IWebViewControl using the class constructor but I am not sure how to instantiate the IWebViewControl in MFC or C++.
https://learn.microsoft.com/en-us/microsoft-edge/hosting/webview
Here is IWebViewControl example in C++:
https://github.com/rjmurillo/webview-samples/tree/master/WinMD/Win32/WebViewSamples.Win32
Excerpt from the code:
void CheckFailure(_In_ HRESULT hr)
{
if (FAILED(hr))
{
WCHAR message[512] = L"";
StringCchPrintf(message, ARRAYSIZE(message), L"Error: 0x%x", hr);
MessageBoxW(nullptr, message, nullptr, MB_OK);
ExitProcess(-1);
}
}
template <typename TInterface>
Microsoft::WRL::ComPtr<TInterface> GetActivationFactoryFailFast(_In_z_ PCWSTR factoryClassName)
{
ComPtr<TInterface> factoryInstance;
CheckFailure(RoGetActivationFactory(
HStringReference(factoryClassName).Get(),
IID_PPV_ARGS(&factoryInstance)));
return factoryInstance;
}
template <typename TInterface>
Microsoft::WRL::ComPtr<TInterface> ActivateInstanceFailFast(_In_z_ PCWSTR className)
{
ComPtr<TInterface> classInstanceAsInspectable;
ComPtr<TInterface> classInstance;
CheckFailure(RoActivateInstance(
HStringReference(className).Get(),
&classInstanceAsInspectable));
CheckFailure(classInstanceAsInspectable.As(&classInstance));
return classInstance;
}
ComPtr<IUriRuntimeClass> CreateWinRtUri(_In_z_ PCWSTR uri, _In_ bool allowInvalidUri = false)
{
auto uriRuntimeClassFactory = GetActivationFactoryFailFast<IUriRuntimeClassFactory>(RuntimeClass_Windows_Foundation_Uri);
ComPtr<IUriRuntimeClass> uriRuntimeClass;
if (!allowInvalidUri)
{
CheckFailure(uriRuntimeClassFactory->CreateUri(HStringReference(uri).Get(), &uriRuntimeClass));
}
else
{
uriRuntimeClassFactory->CreateUri(HStringReference(uri).Get(), &uriRuntimeClass);
}
return uriRuntimeClass;
}
m_processOptions = ActivateInstanceFailFast<IWebViewControlProcessOptions>(RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcessOptions);
ComPtr<IWebViewControlProcessFactory> webViewControlProcessFactory = GetActivationFactoryFailFast<IWebViewControlProcessFactory>(RuntimeClass_Windows_Web_UI_Interop_WebViewControlProcess);
CheckFailure(webViewControlProcessFactory->CreateWithOptions(m_processOptions.Get(), &m_process));
ComPtr<IAsyncOperation<WebViewControl*>> createWebViewAsyncOperation;
CheckFailure(m_process->CreateWebViewControlAsync(reinterpret_cast<INT64>(m_hostWindow), HwndWindowRectToBoundsRect(m_hostWindow), &createWebViewAsyncOperation));
HRESULT hr = createWebViewAsyncOperation->put_Completed(Callback<IAsyncOperationCompletedHandler<WebViewControl*>>([this, createWebViewAsyncOperation](IAsyncOperation<WebViewControl*>*, AsyncStatus status) -> HRESULT
{
CheckFailure(createWebViewAsyncOperation->GetResults(&m_webViewControl));
NavigateToUri(L"https://www.bing.com/");
return S_OK;
}).Get());
CheckFailure(hr);
I don't know if this is an answer as such and will remove it on request. MBut Microsoft now have a WebView2 in beta and it has a Win32 variant:
https://learn.microsoft.com/en-us/microsoft-edge/webview2/gettingstarted/win32
Since MFC is a Win32/Win64 app is it not possible to use this SDK?

TaskScheduler RegisterTaskDefinition fails with NULL path in Win10

According to this MSDN doc, we may pass NULL for the path argument:
path [in]
The name of the task. If this value is NULL, the task will be registered in the root task folder and the task name will be a GUID value created by the Task Scheduler service.
I have a code that use this behavior. The code works fine in Win7 and 8.1, but not in my Win10 box (ver 1709 64-bit, build 16299). In Win10, it will return 0x80070005 aka "Access Denied" when path is NULL. If I specify a name like "Foobar", it will work fine.
Test code:
// Link comsuppw.lib and taskschd.lib.
#include <stdio.h>
#include <windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <shlobj.h>
#include <taskschd.h>
#include <comutil.h>
class AutoHR {
HRESULT hr;
public:
void operator=(HRESULT hr)
{
this->hr = hr;
if (FAILED(hr)) {throw *this;}
}
HRESULT GetHR() const { return hr; }
};
static void TestTaskSched()
{
AutoHR hr;
CComPtr<ITaskService> taskSvc;
CComPtr<ITaskFolder> taskFol;
CComPtr<ITaskDefinition> taskDef;
CComPtr<IActionCollection> taskAC;
CComPtr<IAction> taskAction;
CComPtr<IExecAction> taskEA;
CComPtr<IRegisteredTask> registeredTask;
try {
hr = taskSvc.CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_ALL);
hr = taskSvc->Connect(CComVariant(),CComVariant(),CComVariant(),CComVariant());
hr = taskSvc->GetFolder(_bstr_t(L""), &taskFol);
hr = taskSvc->NewTask(0, &taskDef);
hr = taskDef->get_Actions(&taskAC);
hr = taskAC->Create(TASK_ACTION_EXEC, &taskAction);
hr = taskAction.QueryInterface<IExecAction>(&taskEA);
hr = taskEA->put_Path(_bstr_t(L"C:\\Windows\\System32\\cmd.exe"));
hr = taskEA->put_Arguments(_bstr_t(L"/k echo Testing"));
// Note that NULL is passed as the first argument.
hr = taskFol->RegisterTaskDefinition(nullptr, taskDef,
TASK_CREATE_OR_UPDATE, CComVariant(), CComVariant(),
TASK_LOGON_NONE, CComVariant(), &registeredTask);
MessageBoxW(nullptr, L"Succeeded!", L"OK", MB_ICONINFORMATION);
}
catch (AutoHR const &autohr) {
WCHAR buf[99] = {0};
wsprintfW(buf, L"HRESULT error 0x%.8X\n", autohr.GetHR());
MessageBoxW(nullptr, buf, nullptr, MB_ICONERROR);
}
}
int main()
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr))
{
TestTaskSched();
CoUninitialize();
}
return 0;
}
Test result:
Questions:
1) Is there a behavior change between Win10 and older Windows? I suspect there is, but I cannot find any doc that mentions it.
2) Any good alternative for this behavior? I hope I don't have to generate GUID by myself for temporary task creation.

How to globally mute and unmute sound in Vista and 7, and to get a mute state?

I'm using the old good Mixer API right now, but it does not work as expected on Windows Vista & 7 in the normal, not in XP compatibility mode. It mutes the sound for the current app only, but I need a global (hardware) mute. How to rearch the goal? Is there any way to code this w/o COM interfaces and strange calls, in pure C/C++?
The audio stack was significantly rewritten for Vista. Per-application volume and mute control was indeed one of the new features. Strange calls will be required to use the IAudioEndpointVolume interface.
I recently dealt with this same issue. We have a Windows application that uses the sound system for alarms. We cannot abide the user muting the sound system inadvertently. Here is how I was able to use the interface suggested above to address this issue:
During initialization I added a function to initialize a member of type IAudioEndpointVolume. It was a bit tricky and the help wasn't as helpful as it could be. Here's how to do it:
/****************************************************************************
** Initialize the Audio Endpoint (Only for post XP systems)
****************************************************************************/
void CMuteWatchdog::InitAudioEndPoint(void)
{
HRESULT hr;
IMMDeviceEnumerator * pDevEnum;
IMMDevice * pDev;
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pDevEnum);
m_pIaudEndPt = NULL;
if(hr == S_OK)
{
hr = pDevEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDev);
if(hr == S_OK)
{
DWORD dwClsCtx;
const IID iidAEV = __uuidof(IAudioEndpointVolume);
dwClsCtx = 0;
hr = pDev->Activate(iidAEV, dwClsCtx, NULL, (void**) &m_pIaudEndPt);
if(hr == S_OK)
{
// Everything is groovy.
}
else
{
m_pIaudEndPt = NULL; // Might mean it's running on XP or something. Don't use.
}
pDev->Release();
}
pDevEnum->Release();
}
}
...
About once per second I added a simple call to the following:
////////////////////////////////////////////////////////////////////////
// Watchdog function for mute.
void CMuteWatchdog::GuardMute(void)
{
if(m_pIaudEndPt)
{
BOOL bMute;
HRESULT hr;
bMute = FALSE;
hr = m_pIaudEndPt->GetMute(&bMute);
if(hr == S_OK)
{
if(bMute)
{
m_pIaudEndPt->SetMute(FALSE, NULL);
}
}
}
}
Finally, when the program exits just remember to release the allocated resource.
////////////////////////////////////////////////////////////////////////
// De-initialize the watchdog
void CMuteWatchdog::OnClose(void)
{
if(m_pIaudEndPt)
{
m_pIaudEndPt->Release();
m_pIaudEndPt = NULL;
}
}