DirectX11 CreateShaderResourceView FromMemory or FromResource - c++

Excuse me for my low english skills, I hope you will edit my post if you got enough karma.
I am trying to initialize ShaderResourceView from the Win32 Program Resource. I am using Visual Studio 2015.
Next code fails:
HMODULE hMod = GetModuleHandleW(0);
HRSRC hRes = FindResourceW(hMod, (const wchar*)MAKEINTRESOURCE(IDB_BITMAP1), RT_BITMAP);
HGLOBAL hGlob = LoadResource(hMod, hRes);
DWORD dwImageSize = SizeofResource(hMod, hRes);
byte *lpResourceData = (byte*)LockResource(hGlob);
HRESULT hr = D3DX11CreateShaderResourceViewFromMemory(lpDevice, lpResourceData, dwImageSize, NULL, NULL, &lpNodeTexture, NULL);
if(FAILED(hr)) {
Int3();
}
FreeResource(hGlob);
All of these WinApi functions are succeeded and I really have this resource in my program, but hresult always returns E_FAIL. Can you pls give me an advice. Thank you.
EDITED:
I forgot to add next code as well to the first post:
D3DX11CreateShaderResourceViewFromFileW(lpDevice, L"Node.bmp", 0, 0, &texture, 0).
Its working for me, but I need to pack my textures into application. Can the problem be more difficult than creating D3D Device with Debug Layer flag? Thanks.

Related

Calling COM server, C++ CoCreateInstance throws "No such interface supported", C# works without issue

I'm trying to rewrite some code that calls a local COM Server from C# to C++. The C# code works without issue. The key part is:
Guid lr_FactoryGuid = Guid.Parse("AE7CFA4B-985A-4F76-8CC6-2011649FC8A9");
Guid lr_FactoryClass = Guid.Parse("1CA0D073-4ABB-4D06-B318-BFFDE38E4903");
IntPtr lk_FactoryPtr = new IntPtr();
CoGetClassObject(
ref lr_FactoryClass,
4,
new IntPtr(),
ref lr_FactoryGuid,
out lk_FactoryPtr);
if (lk_FactoryPtr == IntPtr.Zero)
{
MessageBox.Show("lk_FactoryPtr == IntPtr.Zero");
return false;
}
I've tried to rewrite this into C++ and I can't get any further than here, the error is give as "No such interface supported":
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CLSID clsid;
HRESULT hr = CLSIDFromString(L"{1CA0D073-4ABB-4D06-B318-BFFDE38E4903}", &clsid);
CLSID iid;
hr = CLSIDFromString(L"{AE7CFA4B-985A-4F76-8CC6-2011649FC8A9}", &iid);
void* pIFace;
hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, iid, &pIFace);
if (!SUCCEEDED(hr))
{
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();
MessageBox(NULL, errMsg, L"SiteKiosk demo", MB_ICONEXCLAMATION | MB_OK);
}
There is a .tlb file that I used to generate the interop DLL for C# and to import into the C++, however it's currently commented out of the C++ in an attempt to keep the code smaller and I still get this error from CoCreateInstance.
The COM application I'm calling is a 32 bit app, so both my C# and C++ clients applications are also 32 bit. Both of the clients are Windows Console applications.
Is there anything else I need to set/do to get the C++ working?
The suggestion by Hans solved the problem, I used CoGetClassObject and the rest of the code then clicked into place.

Calling DuplicateOutput With D3D12Device Fails With E_NOINTERFACE

I have been trying to make an application that utilizes the desktop duplication api, but having no experience with directx it is turning out to be quite a challenge. Everything seems to work until I call output1->DuplicateOutput()at which point it returns E_NOINTERFACE. This error is not defined in the msdn documentation so I am having trouble diagnosing the problem. I think that this code should work, but I must be missing something.
#include <windows.h>
#include <d3d12.h>
#include <dxgi1_5.h>
int main()
{
HRESULT hr;
ID3D12Debug *debug;
hr = D3D12GetDebugInterface(IID_PPV_ARGS(&debug));
debug->EnableDebugLayer();
IDXGIFactory1 *factory;
hr = CreateDXGIFactory1(IID_PPV_ARGS(&factory));
IDXGIAdapter1 *adapter;
hr = factory->EnumAdapters1(0, &adapter);
factory->Release();
IDXGIOutput *junkput;
hr = adapter->EnumOutputs(0, &junkput);
IDXGIOutput1 *output1;
hr = junkput->QueryInterface(IID_PPV_ARGS(&output1));
junkput->Release();
ID3D12Device *device;
hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&device));
IDXGIOutputDuplication *dupl;
hr = output1->DuplicateOutput(device, &dupl);
return 0;
}
In my debug window I notice that I am getting two _com_errors when I call output1->DuplicateOutput.
Update:
I narrowed the problem down to the fact that I am using a ID3D12Device instead of an ID3D11Device. As exemplified by the fact that this code works:
ID3D11Device *device;
D3D_FEATURE_LEVEL reallevel;
ID3D11DeviceContext *context;
hr = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, NULL, featurelevels, ARRAYSIZE(featurelevels), D3D11_SDK_VERSION, &device, &reallevel, &context);
IDXGIOutputDuplication *dupl;
hr = output1->DuplicateOutput(device, &dupl);
What I don't understand is why that is a problem. Isn't the desktop duplication api compatible with directx 12?
DXGI DuplicateOutput does not support DirectX 12 devices yet. As you have no experience using DirectX, you should be using DirectX 11 anyhow. DirectX 12 is an API designed for graphics experts who are assumed to already be deeply familiar with DirectX 11.
Note that D3D11On12CreateDevice devices should work with DXGI DuplicateOutput, but I've not tried it myself.

SHGetFolderPath returns garbage string in distribute version

char desktopPath[MAX_PATH];
HRESULT r = SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, 0, desktopPath);
if (r != S_OK) {
throw XArch(new XArchEvalWindows());
}
m_desktopPath = CString(desktopPath);
It is so weird. This piece of code works in VS2010 under both the release and debug modes. After I distribute it and run the application, I would get an error saying "The system cannot find the file specified". The more strange thing is my colleague runs the same application on his machine and it works.
In MSDN it says SHGetFolderPath is deprecated, so I tried to use SHGetKnownFolderPath. It is the same situation.
PWSTR desktopPathW = 0;
HRESULT hr = SHGetKnownFolderPath(FOLDERID_Desktop, 0, NULL, &desktopPathW);
if (!SUCCEEDED(hr)) {
throw XArch(new XArchEvalWindows());
}
CoTaskMemFree(static_cast<void*>(desktopPathW));
Any idea about what is going on? Or how am I suppose to debug this?
Thanks in advance.
Jerry
The comments explicitly state that S_OK is the only success result, and the error codes include S_FALSE, E_FAIL and E_INVALIDARG. You incorrectly assume that these 3 are the only error codes.

WriteFile writes incorrectly

I'm trying to copy a file from resources to %localappdata%. I've something like this:
HINSTANCE hInstance = GetModuleHandle(NULL);
HANDLE hFile = INVALID_HANDLE_VALUE;
HRSRC hrsrc = FindResource(hInstance, MAKEINTRESOURCE(MSIE), RT_RCDATA);
HGLOBAL exeRes = LoadResource(hInstance, hrsrc);
DWORD size = SizeofResource(hInstance, hrsrc);
TCHAR szPath[MAX_PATH];
HANDLE hfile;
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) {
PathAppend(szPath, TEXT("test.exe"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
LPVOID exePtr = LockResource(hrsrc);
DWORD exeWritten = 0;
BOOL writeResult = WriteFile(hFile, exePtr, size, &exeWritten, NULL);
cout << GetLastError() << endl;
BOOL closed = CloseHandle(hFile);
system("PAUSE");
return 0;
I'm able to locate the HRSRC and confirm the size using SizeofResource() just fine. CreateFile is in fact creating the file and returning the handle. GetLastError() reports that there are no errors. The amount of bytes written to disk is exactly right.
The output exe however is corrupted (the version of this file is incompatible with the version of Windows... blah blah) - it's lost its icon and everything. Looking at the original and the output file side-by-side in a hex editor it appears there's random data at the start of file.
What am I missing here?
Your LockResource is not correct. It should be passed the HGLOBAL exeRes you loaded previously.
LockResource(hrsrc);
should be
LockResource(exeRes);
From the MS documentation on LockResource() :
Do not try to lock a resource by using the handle returned by the FindResource or FindResourceEx function. Such a handle points to random data.
And as a side note, you may want to try cleaning up that loaded-and-locked resource when you're through with it.

DirectShow DVD playback

I have created a custom allocator/presenter that works fine for playback of normal media files. However, when I use the following code to try to playback a DVD, it fails with a stack overflow exception.
vmr9_ap = new vmr9ap();
HMONITOR monitor = MonitorFromWindow(hwnd, NULL);
IGraphBuilder *graph;
IBaseFilter *filter;
IDvdGraphBuilder *builder;
CoCreateInstance(CLSID_DvdGraphBuilder, NULL, CLSCTX_INPROC_SERVER, IID_IDvdGraphBuilder, reinterpret_cast<void**>(&builder));
CoCreateInstance(::CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast<void**>(&filter));
builder->GetDvdInterface(IID_IVMRFilterConfig9, (void**)&vmr9_config);
vmr9_ap->Initialize(g_pd3dDevice, monitor, vmr9_config);
HRESULT hr = builder->RenderDvdVideoVolume(L"G:\\VIDEO_TS", AM_DVD_SWDEC_PREFER | AM_DVD_VMR9_ONLY, &status);
builder->GetFiltergraph(&graph);
IDvdControl2 *dvdControl;
builder->GetDvdInterface(::IID_IDvdControl2, (void**)&dvdControl);
graph->QueryInterface(::IID_IMediaControl, (void**)&control);
HRESULT h = control->Run();
The stack overflow happens immediately after the call to control->Run(). It's driving me nuts, as I'm sure I'm just forgetting something really really simple.
Thanks.
Your graph should look something like this. Make sure there aren't any buggy filters in your graph.
Because you are using a custom allocator, I would look there for the issue and set some breakpoints there. You code you pasted might be incomplete as I do not see you configure the VMR9 with the custom allocator, nor do I see it being added to the graph. I avoid using the DVDGraphBuilder as I had too difficult of a time getting it RenderVolume correctly with my VMR9+Allocator. I would build the graph a little more manually.
I have a custom allocator in my open source project, along w/ a DVD player. You can check that out for reference, though there is a lot of code noise in there due to me needing to hack a few things in there for WPF compatiblity. http://wpfmediakit.codeplex.com
What you are seeing should NOT be a DRM issue.
alt text http://img29.imageshack.us/img29/7798/capturelu.jpg
Could it be a form of DRM protection? Decoders in DVD graphs will typically try to prevent you building graphs that get access to the uncompressed data as you do here. Normally they do that by a cleaner method, such as refusing to connect to unauthorised renderers, but it's possible that this might be caused by something like that -- certainly there are mpeg-2 decoders which use deliberate crashes to prevent reverse engineering.
G
Thanks to the code Jeremiah Morrill pointed me to, I managed to get playback mostly working.
It works fine, as long as you don't try to resize the D3DImage that it's played in. Devil's in the details, I suppose.
Thanks to all the answers. DVD playback doesn't work with a debugger attached, which according to Google, is not DRM, but is an anti-reverse engineering measure. Could be particular to the DVD codec I'm using too.
extern "C" __declspec(dllexport) LPDIRECT3DSURFACE9 InitializeDvd(HWND hWnd)
{
CoInitialize(NULL);
IPin *dvdVideoOut;
IPin *vmr9VideoIn;
HRESULT hr = S_OK;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&graph);
if(graph)
{
hr = CoCreateInstance(CLSID_DVDNavigator, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **)&dvdNavigator);
if(dvdNavigator)
{
hr = graph->AddFilter(dvdNavigator, L"DVD Navigator");
if(SUCCEEDED(hr))
{
hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER,
IID_IBaseFilter, (void **)&vmr9);
if(vmr9)
{
hr = vmr9->QueryInterface(IID_IVMRFilterConfig9, reinterpret_cast<void**>(&p_fConfig));
p_Ap = new VMR9AllocatorPresenter();
p_Dh = new DeviceHandler();
p_device = p_Dh->Initialize(hWnd);
p_fConfig->SetRenderingMode(VMR9Mode_Renderless);
p_fConfig->SetNumberOfStreams(1);
p_Ap->Initialize(hWnd, p_device, p_fConfig);
if(SUCCEEDED(hr))
{
hr = graph->AddFilter(vmr9, L"Video Mixing Renderer 9");
if(p_fConfig)
{
dvdNavigator->FindPin(L"Video", &dvdVideoOut);
if(dvdVideoOut)
{
hr = graph->Render(dvdVideoOut);
}
hr = graph->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&control));
if(control)
{
control->Run();
}
}
}
}
}
}
}
return p_Dh->g_surface9;
}