DXGI got an error in func Map "Access Violation" - c++

Good afternoon, I am writing a program that will extract pixels from the desktop, but unfortunately I ran into a problem, Map gives an error "Access Violation". Help me please.
I've divided all the code by function to make it clear to you.
I hope you can help me because I have little experience with directx and dxgi so far.
ID3D11Device *m_pDevice;
ID3D11DeviceContext *m_pDeviceContext;
IDXGIDevice *m_pDXGIDevice;
ID3D11Texture2D* m_pDesktopTexture;
ID3D11Texture2D* m_pCompatibleTexture;
//ID3D11Device* m_pDevice;
IDXGIAdapter* m_pDXGIAdapter;
IDXGIOutput* m_pDXGIOutput;
IDXGIOutput1* m_pDXGIOutput1;
IDXGIOutputDuplication* m_pOutputDuplication = nullptr;
DXGI_OUTDUPL_DESC m_OutputDuplicationDescription;
DXGI_OUTPUT_DESC m_OutputDescription;
D3D11_MAPPED_SUBRESOURCE m_mappedResource;
HRESULT CreateD3DDevice()
{
HRESULT hResult = S_OK;
D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_9_1;
hResult = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
0, &featureLevel, (UINT)(1), D3D11_SDK_VERSION, &m_pDevice, 0, &m_pDeviceContext);
return hResult;
}
HRESULT CreateDXGIDevice()
{
return m_pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&m_pDXGIDevice));;
}
HRESULT CreateCompatibleTexture()
{
D3D11_TEXTURE2D_DESC textureDescription;
textureDescription.Width = m_OutputDuplicationDescription.ModeDesc.Width;
textureDescription.Height = m_OutputDuplicationDescription.ModeDesc.Height;
textureDescription.Format = m_OutputDuplicationDescription.ModeDesc.Format;
textureDescription.ArraySize = 1;
textureDescription.BindFlags = 0;
textureDescription.MiscFlags = 0;
textureDescription.SampleDesc.Count = 1;
textureDescription.SampleDesc.Quality = 0;
textureDescription.MipLevels = 1;
textureDescription.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
textureDescription.Usage = D3D11_USAGE_STAGING;
return m_pDevice->CreateTexture2D(&textureDescription, 0, &m_pCompatibleTexture);
}
HRESULT CreateDXGIOutput()
{
return m_pDXGIAdapter->EnumOutputs((UINT)(0), &m_pDXGIOutput);
}
HRESULT DuplicateOutput()
{
return m_pDXGIOutput1->DuplicateOutput(m_pDevice, &m_pOutputDuplication);
}
HRESULT CreateDXGIAdapter()
{
return m_pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&m_pDXGIAdapter));
}
HRESULT CreateDXGIOutput1()
{
return m_pDXGIOutput->QueryInterface(__uuidof(m_pDXGIOutput1), reinterpret_cast<void**>(&m_pDXGIOutput1));
}
HRESULT GetOutputDescription()
{
return m_pDXGIOutput->GetDesc(&m_OutputDescription);
}
HRESULT CaptureScreen()
{
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
IDXGIResource* DesktopResource = nullptr;
HRESULT hResult = m_pOutputDuplication->AcquireNextFrame(9999, &FrameInfo, &DesktopResource);
if (FAILED(hResult))
{
return hResult;
}
hResult = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&m_pDesktopTexture));
DesktopResource->Release();
DesktopResource = nullptr;
if (FAILED(hResult))
{
return hResult;
}
m_pDeviceContext->CopyResource(m_pCompatibleTexture, m_pDesktopTexture);
m_pDeviceContext->Map(m_pCompatibleTexture, D3D11CalcSubresource(0, 0, 0), D3D11_MAP_READ_WRITE, 0, &m_mappedResource);
BYTE* sptr = reinterpret_cast<BYTE*>(m_mappedResource.pData);
m_pDeviceContext->Unmap(m_pCompatibleTexture, 0);
m_pOutputDuplication->ReleaseFrame();
return hResult;
}
int main()
{
HRESULT hr;
hr = CreateD3DDevice();
std::cout << hr << std::endl;
hr = CreateDXGIDevice();
std::cout << hr << std::endl;
hr = CreateDXGIAdapter();
std::cout << hr << std::endl;
hr = CreateDXGIOutput();
std::cout << hr << std::endl;
hr = GetOutputDescription();
std::cout << hr << std::endl;
hr = CreateDXGIOutput1();
std::cout << hr << std::endl;
hr = DuplicateOutput();
std::cout << hr << std::endl;
m_pOutputDuplication->GetDesc(&m_OutputDuplicationDescription);
hr = CaptureScreen();
std::cout << hr << std::endl;
}

Related

Why do I get a success code when I start a task, but it does nothing?

Please help me to solve a problem. I'm trying to copy a system RegIdleBackup task and launch the copied task. I successfully copied task with ITaskService api, and change some settings in it. And after all i tried to Run this task, and I got return code S_OK, but task info didn't changed in Task Scheduler window and backup files didn't update. I can manually run this task from task sheduler and my copied task works good. My problem is with launch method, but i can't find it. Thank you.
Here is my code
HRESULT GetTask(ITaskService* pService, const std::wstring& fullTaskName, IRegisteredTask** pTask)
{
ITaskFolder* pFolder = nullptr;
HRESULT hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
return hr;
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
if (FAILED(hr))
return hr;
hr = pFolder->GetTask(SysAllocString(L"RegIdleBackup"), pTask);
pFolder->Release();
return hr;
}
HRESULT CreateTaskCopy(ITaskService* pService, IRegisteredTask* pTask, const std::wstring& fullTaskName)
{
ITaskFolder* pFolder = nullptr;
HRESULT hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
return hr;
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
ITaskDefinition* pTaskDef = nullptr;
ITaskSettings* pTaskSettings = nullptr;
IRegisteredTask* iTask = nullptr;
hr = pTask->get_Definition(&pTaskDef);
if (FAILED(hr))
goto exit;
hr = pTaskDef->get_Settings(&pTaskSettings);
if (FAILED(hr))
goto exit;
hr = pTaskSettings->put_AllowDemandStart(_variant_t(TRUE));
if (FAILED(hr))
goto exit;
hr = pTaskSettings->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
if (FAILED(hr))
goto exit;
hr = pTaskDef->put_Settings(pTaskSettings);
if (FAILED(hr))
goto exit;
pTaskSettings->Release();
pTaskSettings = nullptr;
hr = pFolder->DeleteTask(_bstr_t(taskName.c_str()), 0);
hr = pFolder->RegisterTaskDefinition(_bstr_t(taskName.c_str()),
pTaskDef,
TASK_CREATE_OR_UPDATE,
_variant_t(),
_variant_t(),
TASK_LOGON_SERVICE_ACCOUNT,
_variant_t(L""),
&iTask);
exit:
if (pTaskSettings)
pTaskSettings->Release();
if (iTask)
iTask->Release();
if (pTaskDef)
pTaskDef->Release();
return hr;
}
HRESULT CopyTask(const std::wstring& fullTaskName, const std::wstring& copyName)
{
ITaskService* pService = nullptr;
IRegisteredTask* pTask = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
hr = GetTask(pService, fullTaskName, &pTask);
if (FAILED(hr))
goto exit;
hr = CreateTaskCopy(pService, pTask, copyName);
exit:
if(pService)
pService->Release();
if (pTask)
pTask->Release();
return hr;
}
HRESULT StartTask(const std::wstring& fullTaskName)
{
ITaskService* pService = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
{
pService->Release();
return hr;
}
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
ITaskFolder* pFolder = nullptr;
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
IRegisteredTask* pTask = nullptr;
pFolder->GetTask(_bstr_t(taskName.c_str()), &pTask);
pFolder->Release();
IRunningTask* pRunningTask = nullptr;
hr = pTask->RunEx(_variant_t(),0,0, _bstr_t(L"S-1-5-18"), &pRunningTask);
pTask->Release();
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
return hr;
hr = CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0, nullptr);
if (FAILED(hr))
return hr;
hr = CopyTask(L"\\Microsoft\\Windows\\Registry\\RegIdleBackup", L"\\Microsoft\\Windows\\Registry\\MyTask");
hr = StartTask(L"\\Microsoft\\Windows\\Registry\\MyTask");
CoUninitialize();
return hr;
}
Today morning I tried to run task with replacing launch trigger, and same time fixed some task settings. And all worked good, and after all I started to test my program on Win 7 and all were great, but on Win10 i got some interesting issue, task created with another last launch time (on Win7 field empty, on Win 10 message - "Task never launched before") and i tried to use IRegisteredTask::Run method, and it's worked! I tested on other OSes and run method working. I paste my code sample, maybe it canbe usefull for somebody.
HRESULT GetTaskDefinition(ITaskService* pService, const std::wstring& fullTaskName, ITaskDefinition** pTask)
{
ITaskFolder* pFolder = nullptr;
IRegisteredTask* pRegTask = nullptr;
HRESULT hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
return hr;
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
if (FAILED(hr))
return hr;
hr = pFolder->GetTask(SysAllocString(L"RegIdleBackup"), &pRegTask);
pFolder->Release();
if (FAILED(hr))
return hr;
hr = pRegTask->get_Definition(pTask);
return hr;
}
HRESULT ChangeTaskSettings(ITaskDefinition* pTaskDef)
{
ITaskSettings* pTaskSettings = nullptr;
HRESULT hr = pTaskDef->get_Settings(&pTaskSettings);
if (FAILED(hr))
return hr;
hr = pTaskSettings->put_AllowDemandStart(VARIANT_TRUE);
hr = pTaskSettings->put_MultipleInstances(TASK_INSTANCES_PARALLEL);
hr = pTaskSettings->put_RunOnlyIfIdle(VARIANT_FALSE);
hr = pTaskSettings->put_StartWhenAvailable(VARIANT_TRUE);
hr = pTaskSettings->put_StopIfGoingOnBatteries(VARIANT_FALSE);
hr = pTaskSettings->put_Enabled(VARIANT_FALSE);
hr = pTaskSettings->put_DisallowStartIfOnBatteries(VARIANT_FALSE);
hr = pTaskDef->put_Settings(pTaskSettings);
pTaskSettings->Release();
return hr;
}
FILETIME AddSecondsToFIleTime(FILETIME ft, unsigned seconds)
{
FILETIME res;
#define _SECONDS ((__int64) 10000000) //100 ns intervals in second
ULONGLONG tmp = (static_cast<ULONGLONG>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime + seconds*_SECONDS;
res.dwLowDateTime = static_cast<DWORD>(tmp & 0xFFFFFFFF);
res.dwHighDateTime = static_cast<DWORD>(tmp >> 32);
return res;
}
std::wstring GetTaskLaunchTimeWstring(SYSTEMTIME st, unsigned wait_interval)
{
FILETIME ft;
SystemTimeToFileTime(&st, &ft);
ft = AddSecondsToFIleTime(ft, wait_interval);
FileTimeToSystemTime(&ft, &st);
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << st.wYear << "-" <<
std::setfill('0') << std::setw(2) << st.wMonth << "-" <<
std::setfill('0') << std::setw(2) << st.wDay << "T" <<
std::setfill('0') << std::setw(2) << st.wHour << ":" <<
std::setfill('0') << std::setw(2) << st.wMinute << ":" <<
std::setfill('0') << std::setw(2) << st.wSecond;
std::string str = ss.str();
return std::wstring(str.begin(), str.end());
}
HRESULT ChangeTaskTriggers(ITaskDefinition* pTaskDef, const std::wstring& LaunchTimeStr)
{
ITriggerCollection* pTriggersCollection = nullptr;
HRESULT hr = pTaskDef->get_Triggers(&pTriggersCollection);
hr = pTriggersCollection->Clear();
ITrigger* pTrigger = nullptr;
hr = pTriggersCollection->Create(TASK_TRIGGER_TIME, &pTrigger);
pTriggersCollection->Release();
if (FAILED(hr))
return hr;
ITimeTrigger* pTimeTrigger = nullptr;
hr = pTrigger->QueryInterface(IID_ITimeTrigger, reinterpret_cast<void**>(&pTimeTrigger));
pTrigger->Release();
if (FAILED(hr))
return hr;
hr = pTimeTrigger->put_Id(_bstr_t(L"Trigger"));
hr = pTimeTrigger->put_Enabled(VARIANT_TRUE);
hr = pTimeTrigger->put_StartBoundary(_bstr_t(LaunchTimeStr.c_str()));
pTimeTrigger->Release();
return hr;
}
HRESULT RegisterTask(ITaskService* pService, ITaskDefinition* pTaskDef, const std::wstring& fullTaskName)
{
ITaskFolder* pFolder = nullptr;
HRESULT hr = pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
return hr;
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
IRegisteredTask* pRegisteredTAsk = nullptr;
hr = pFolder->DeleteTask(_bstr_t(taskName.c_str()), 0);
hr = pFolder->RegisterTaskDefinition(_bstr_t(taskName.c_str()),
pTaskDef,
TASK_CREATE_OR_UPDATE,
_variant_t(),
_variant_t(),
TASK_LOGON_SERVICE_ACCOUNT,
_variant_t(L""),
&pRegisteredTAsk);
if (SUCCEEDED(hr))
{
pRegisteredTAsk->put_Enabled(VARIANT_TRUE);
pRegisteredTAsk->Release();
}
return hr;
}
HRESULT CreateModifiedTaskCopy(const std::wstring& fullTaskName, const std::wstring& copyName, unsigned seconds_to_start)
{
ITaskService* pService = nullptr;
ITaskDefinition* pTaskDef = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
hr = GetTaskDefinition(pService, fullTaskName, &pTaskDef);
if (FAILED(hr))
{
pService->Release();
return hr;
}
hr = ChangeTaskSettings(pTaskDef);
SYSTEMTIME st;
GetLocalTime(&st);
const std::wstring launchStr = GetTaskLaunchTimeWstring(st, seconds_to_start);
hr = ChangeTaskTriggers(pTaskDef, launchStr);
hr = RegisterTask(pService, pTaskDef, copyName);
pTaskDef->Release();
pService->Release();
return hr;
}
HRESULT WaitUntilTaskCompleted(const std::wstring& fullTaskName, unsigned taskTimeout, unsigned maxWaitTime)
{
ITaskService* pService = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
{
pService->Release();
return hr;
}
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
ITaskFolder* pFolder = nullptr;
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
IRegisteredTask* pTask = nullptr;
hr = pFolder->GetTask(_bstr_t(taskName.c_str()), &pTask);
if (FAILED(hr))
{
pFolder->Release();
return hr;
}
DATE lastRun;
unsigned tries = 0;
do
{
Sleep(1000);
hr = pTask->get_LastRunTime(&lastRun);
tries++;
if (tries > maxWaitTime)
break;
} while (hr == SCHED_S_TASK_HAS_NOT_RUN);
return tries > maxWaitTime? SCHED_E_INVALID_TASK :S_OK;
}
HRESULT DeleteTask(const std::wstring& fullTaskName)
{
ITaskService* pService = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
{
pService->Release();
return hr;
}
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
ITaskFolder* pFolder = nullptr;
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
hr = pFolder->DeleteTask(_bstr_t(taskName.c_str()), 0);
pFolder->Release();
return hr;
}
HRESULT RunTask(const std::wstring& fullTaskName)
{
ITaskService* pService = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService);
if (FAILED(hr))
return hr;
pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t());
if (FAILED(hr))
{
pService->Release();
return hr;
}
const std::wstring taskFolder = fullTaskName.substr(0, fullTaskName.find_last_of(L'\\'));
const std::wstring taskName = fullTaskName.substr(fullTaskName.find_last_of(L'\\') + 1);
ITaskFolder* pFolder = nullptr;
hr = pService->GetFolder(_bstr_t(taskFolder.c_str()), &pFolder);
pService->Release();
if (FAILED(hr))
return hr;
IRegisteredTask* pTask = nullptr;
hr = pFolder->GetTask(_bstr_t(taskName.c_str()), &pTask);
pFolder->Release();
IRunningTask* pRunTask = nullptr;
pTask->Run(_variant_t(), &pRunTask);
pTask->Release();
pRunTask->Release();
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
return hr;
hr = CoInitializeSecurity(nullptr, -1, nullptr, nullptr, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, 0, nullptr);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
const unsigned seconds_to_start = 30;
hr = CreateModifiedTaskCopy(L"\\Microsoft\\Windows\\Registry\\RegIdleBackup", L"\\Microsoft\\Windows\\Registry\\MyTask", seconds_to_start);
if (FAILED(hr))
{
CoUninitialize();
return hr;
}
RunTask(L"\\Microsoft\\Windows\\Registry\\MyTask");
hr = WaitUntilTaskCompleted(L"\\Microsoft\\Windows\\Registry\\MyTask", seconds_to_start, seconds_to_start * 4);
hr = DeleteTask(L"\\Microsoft\\Windows\\Registry\\MyTask");
CoUninitialize();
printf("All ok!\r\n");
return hr;
}

CreateSnapshot() does not generate a hyper-v virtual machine snapshot?

HRESULT hr;
IWbemClassObject *pInClass = NULL;
IWbemClassObject *pOutClass = NULL;
IWbemContext *pCtx = 0;
IWbemCallResult *pResult = 0;
BSTR snapshotClassPath = SysAllocString(L"Msvm_VirtualSystemSnapshotService");
hr = m_pWbemServices->GetObject(
snapshotClassPath,
0,
NULL,
&m_pWbemClassObject,
NULL);
if (FAILED(hr))
{
std::cout << "Failed to get class object(Msvm_VirtualSystemSnapshotService). Error code = 0x" << hex << hr << std::endl;
return;
}
// Create snapshot method
BSTR MethodNameOne = SysAllocString(L"CreateSnapshot");
hr = m_pWbemClassObject->GetMethod(
MethodNameOne,
0,
&pInClass,
&pOutClass
);
if (FAILED(hr))
{
std::cout << "Failed to get method(CreateSnapshot). Error code = 0x" << hex << hr << endl;
}
cout << "Succeeded to get method(CreateSnapshot)." << endl;
BSTR virtualSystemSnaphotSettingData = SysAllocString(L"Msvm_VirtualSystemSnapshotSettingData");
// Get the Msvm_VirtualSystemSnapshotSettingData Class object
IWbemClassObject * pvirtualSystemSnaphotSettingData = NULL;
hr = m_pWbemServices->GetObject(
virtualSystemSnaphotSettingData,
0,
pCtx,
&pvirtualSystemSnaphotSettingData,
&pResult
);
if (FAILED(hr))
{
wprintf(L"Error GetObject Msvm_VirtualSystemSnapshotSettingData:0x%08lx\n", hr);
}
std::cout << "Succeeded to get object(Msvm_VirtualSystemSnapshotSettingData)." << std::endl;
// Create instance of Msvm_VirtualSystemSnapshotSettingData class
IWbemClassObject * pInpInstOfSnapshotSettingData = NULL;
hr = pvirtualSystemSnaphotSettingData->SpawnInstance(
0,
&pInpInstOfSnapshotSettingData);
if (FAILED(hr))
{
wprintf(L"Error SpawnInstance Msvm_VirtualSystemSnapshotSettingData:0x%08lx\n", hr);
}
std::cout << "Succeeded to created instance(Msvm_VirtualSystemSnapshotSettingData )." << std::endl;
// Set the property(Consistency Level)
BSTR memberOneForVirtualSystemSnapshotSettingData = SysAllocString(L"ConsistencyLevel");
VARIANT consistencyLevel;
VariantInit(&consistencyLevel);
V_VT(&consistencyLevel) = VT_BSTR;
V_BSTR(&consistencyLevel) = SysAllocString(L"1");
hr = pInpInstOfSnapshotSettingData->Put(
memberOneForVirtualSystemSnapshotSettingData,
0,
&consistencyLevel,
0);
if (FAILED(hr))
{
wprintf(L"Error memberOneForVirtualSystemSnapshotSettingData:0x%08lx\n", hr);
}
wprintf(L"Succeeded to set property(ConsistencyLevel), Consistency level:%s\n", consistencyLevel.bstrVal);
VariantClear(&consistencyLevel);
The CreateSnapshot method was called on Windows Hyper-V 2016 and the execution was successful, but the generated virtual machine snapshot was not visible in the Hyper-V GUI.
// Set the property(ElementName)
BSTR memberThreeForVirtualSystemSnapshotSettingData = SysAllocString(L"ElementName");
VARIANT elementName;
VariantInit(&elementName);
V_VT(&elementName) = VT_BSTR;
V_BSTR(&elementName) = SysAllocString(vmName);
hr = pInpInstOfSnapshotSettingData->Put(
memberThreeForVirtualSystemSnapshotSettingData,
0,
&elementName,
0);
if (FAILED(hr))
{
wprintf(L"Failed to set property(ElementName), Erorr code:0x%08lx\n", hr);
}
wprintf(L"Succeeded to set property(ElementName):%s\n", elementName.bstrVal);
VariantClear(&elementName);
// Set the property(ignore disks that aren't compatible with snapshots)
BSTR memberTwoForVirtualSystemSnapshotSettingData = SysAllocString(L"IgnoreNonSnapshottableDisks");
VARIANT ignoreNonSnapshottableDisks;
ignoreNonSnapshottableDisks.vt = VT_BOOL;
ignoreNonSnapshottableDisks.boolVal = true;
hr = pInpInstOfSnapshotSettingData->Put(
memberTwoForVirtualSystemSnapshotSettingData,
0,
&ignoreNonSnapshottableDisks,
0);
if (FAILED(hr))
{
wprintf(L"Error memberTwoForVirtualSystemSnapshotSettingData:0x%08lx\n", hr);
}
wprintf(L"Succeeded to set property(IgnoreNonSnapshottableDisks):%d\n", ignoreNonSnapshottableDisks.boolVal);
VariantClear(&ignoreNonSnapshottableDisks);
// Create or update instance
hr = m_pWbemServices->PutInstance(
pInpInstOfSnapshotSettingData,
0,
pCtx,
&pResult);
if (FAILED(hr))
{
wprintf(L"Error PutInstance:0x%08lx\n", hr);
}
wprintf(L"Succeeded to update the instance.\n");
// Get textual rendering of the object in the MOF syntax
BSTR objString = NULL;
hr = pInpInstOfSnapshotSettingData->GetObjectText(0, &objString);
if (FAILED(hr))
{
wprintf(L"Error GetObjectText:0x%08lx\n", hr);
}
wprintf(L"Succeeded to get textual rendering.\n");
BSTR ArgNameTwo = SysAllocString(L"SnapshotSettings");
VARIANT v;
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = objString;
wprintf(L"Object text: %s\n", objString);
// Pass the second Argument to CreateSnapshot method
hr = pInClass->Put(ArgNameTwo, 0, &v, 0);
if (FAILED(hr))
{
wprintf(L"Error ArgNameTwo:0x%08lx\n", hr);
}
VariantClear(&v);
wprintf(L"Succeeded to set property(SnapshotSettings).\n");
// set property(AffectedSystem)
VARIANT vtProp;
m_pWbemClassObject->Get(L"__Path", 0, &vtProp, 0, 0);
hr = pInClass->Put(L"AffectedSystem", 0, &vtProp, NULL);
if (FAILED(hr))
{
std::cout << "Failed to set property(AffectedSystem)." << std::endl;
}
wprintf(L"AffectedSystem: %s\n", vtProp.bstrVal);
VariantClear(&vtProp);
// Pass the Third Argument to CreateSnapshot method
BSTR ArgNameThree = SysAllocString(L"SnapshotType");
VARIANT var;
VariantInit(&var);
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = SysAllocString(L"32768");
hr = pInClass->Put(ArgNameThree, 0, &var, 0);
if (FAILED(hr))
{
std::cout << "Failed to set property(SnapshotType)." << std::endl;
}
wprintf(L"SnapshotType: %s\n", var.bstrVal);
VariantClear(&var);
// Call the CreateSnapshot method.
IEnumWbemClassObject* pEnumOb1 = NULL;
hr = m_pWbemServices->ExecQuery(
BSTR(L"WQL"),
BSTR(L"SELECT * FROM Msvm_VirtualSystemSnapshotService"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumOb1
);
if (FAILED(hr)) {
std::cout << "SELECT * FROM Msvm_VirtualSystemSnapshotService, Error code:0x%08lx" << hex << hr << endl;
}
std::cout << "Succeeded to query snapshot." << std::endl;
IWbemClassObject *pclsObj1 = NULL;
ULONG uReturn1 = 0;
std::cout << "Create snapshot..." << std::endl;
while (1)
{
HRESULT hr = pEnumOb1->Next(WBEM_INFINITE, 1, &pclsObj1, &uReturn1);
if (FAILED(hr) || !uReturn1)
{
break;
}
VARIANT vt;
// Get the value of the path property from Msvm_VirtualSystemSnapshotService Class
hr = pclsObj1->Get(L"__Path", 0, &vt, 0, 0);
if (FAILED(hr))
{
std::wcout << "Failed to get vm's path." << std::endl;
break;
}
wprintf(L"__PATH:%s \n", vt.bstrVal);
//Call the CreateSnapshot method
hr = m_pWbemServices->ExecMethod(
vt.bstrVal,
MethodNameOne,
0,
NULL,
pInClass,
&pOutClass,
NULL);
if (FAILED(hr))
{
wprintf(L"Failed to execute(CreateSnapshot), Erorr code:0x%08lx\n", hr);
break;
}
wprintf(L"Succeeded to create snapshot.\n");
Sleep(10);
pclsObj1->Release();
pclsObj1 = NULL;
}
The return value of ExecMethod() is 0, that is, the call succeeds, but I did not see the snapshot just created on Hyper-V.
I use this PowerShell script and it works. The only problem is to set snapshot name:
function Create-VMSnapshot{
$vm = Get-WmiObject -Namespace $Namespace -ComputerName $ComputerName -Query "select * from msvm_computersystem where elementname='$VMName'"
if($vm -eq $null){
throw "Failed to get VM with display name '$VMName'"
}
$Msvm_VirtualSystemSnapshotService = Get-WmiObject -Namespace $Namespace -ComputerName $ComputerName -Class Msvm_VirtualSystemSnapshotService
if($Msvm_VirtualSystemSnapshotService -eq $null)
{
throw "Failed to get Msvm_VirtualSystemSnapshotService instance"
}
[WMI]$Msvm_VirtualSystemSnapshotSettingData = ([WMIClass]"\\.\root\virtualization\v2:Msvm_VirtualSystemSnapshotSettingData").CreateInstance()
if($Msvm_VirtualSystemSnapshotSettingData -eq $null)
{
throw "Failed to get Msvm_VirtualSystemSnapshotSettingData instance"
}
$Msvm_VirtualSystemSnapshotSettingData.ConsistencyLevel = 1
$Msvm_VirtualSystemSnapshotSettingData.IgnoreNonSnapshottableDisks = $true
$Msvm_VirtualSystemSnapshotSettingData.ElementName = $SnapshotName
$Msvm_VirtualSystemSnapshotSettingData.Description = $SnapshotDescription
$Msvm_VirtualSystemSnapshotSettingData
[System.Management.ManagementBaseObject]$result = $Msvm_VirtualSystemSnapshotService.CreateSnapshot(
$vm,
$Msvm_VirtualSystemSnapshotSettingData.GetText(2),
32768)
[int]$res = Job-Observation -WMIJobResult $result -JobAction "Creating snapshot" -JobProgressCaption "Create snapshot"
$snapshot = (([WMI]$result.Job).GetRelated("Msvm_VirtualSystemSettingData") | % {$_})
$snapshot
}

AcquireNextFrame not working (Desktop Duplication API & D3D11)

I've put together this code that takes a screenshot of the desktop and maps it for raw pixel data access, but the output is all zeros. I have no idea what i've done wrong. After looking at many examples of the Desktop Duplication Api online I don't see any differences between them and mine.
This is my method to initialize everything, and no errors are raised.
BOOL init()
{
CHECKHR(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, gFeatureLevels, gNumFeatureLevels, D3D11_SDK_VERSION, &lDevice, &FeatureLevel, &lImmediateContext))
IDXGIDevice* lDxgiDevice;
CHECKHR(lDevice->QueryInterface(IID_PPV_ARGS(&lDxgiDevice)))
IDXGIAdapter* lDxgiAdapter;
CHECKHR(lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&lDxgiAdapter))
lDxgiDevice->Release();
IDXGIOutput* lDxgiOutput;
CHECKHR(lDxgiAdapter->EnumOutputs(0, &lDxgiOutput))
lDxgiAdapter->Release();
CHECKHR(lDxgiOutput->GetDesc(&OutputDesc))
IDXGIOutput1* lDxgiOutput1;
CHECKHR(lDxgiOutput->QueryInterface(IID_PPV_ARGS(&lDxgiOutput1)))
lDxgiOutput->Release();
CHECKHR(lDxgiOutput1->DuplicateOutput(lDevice, &lDeskDupl))
lDxgiOutput1->Release();
lDeskDupl->GetDesc(&OutputDuplDesc);
D3D11_TEXTURE2D_DESC desc;
desc.Width = OutputDuplDesc.ModeDesc.Width;
desc.Height = OutputDuplDesc.ModeDesc.Height;
desc.Format = OutputDuplDesc.ModeDesc.Format;
desc.ArraySize = 1;
desc.BindFlags = 0;
desc.MiscFlags = 0;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.MipLevels = 1;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.Usage = D3D11_USAGE_STAGING;
CHECKHR(lDevice->CreateTexture2D(&desc, NULL, &lDestImage))
return TRUE;
}
the CHECKHR macro i'm using was tested by me and works, just to clarify that it is not the problem.
This is the code that I use to actually grab the frame:
int main()
{
init();
HRESULT hr;
IDXGIResource* lDesktopResource;
ID3D11Texture2D* lAcquiredDesktopImage;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
while (true)
{
if (SUCCEEDED(lDeskDupl->AcquireNextFrame(INFINITE, &FrameInfo, &lDesktopResource)))
{
break;
}
}
hr = lDesktopResource->QueryInterface(IID_PPV_ARGS(&lAcquiredDesktopImage));
if (FAILED(hr))
{
cout << "QueryInterface failed!" << endl;
system("pause");
}
lDesktopResource->Release();
lImmediateContext->CopyResource(lDestImage, lAcquiredDesktopImage);
lAcquiredDesktopImage->Release();
lDeskDupl->ReleaseFrame();
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
hr = lImmediateContext->Map(lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
if (FAILED(hr))
{
cout << "Map failed!" << endl;
system("pause");
}
BYTE* pb = (BYTE*)(resource.pData);
for (int i = 0; i < 2000000; i++)
{
cout << (int)pb[i] << endl;
}
system("pause");
return 0;
}
All that happens is 2000000 zeros get printed to the console. Is there something i'm missing or that I cant see?
First, call D3D11CreateDevice against specific adapter which output you are about to duplicate:
BOOL init()
{
IDXGIFactory* lDxgiFactory;
CHECKHR(CreateDXGIFactory1(__uuidof(IDXGIFactory), (void**)&lDxgiFactory))
IDXGIAdapter* lDxgiAdapter;
CHECKHR(lDxgiFactory->EnumAdapters(0, &lDxgiAdapter))
lDxgiFactory->Release();
CHECKHR(D3D11CreateDevice(lDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, gFeatureLevels, gNumFeatureLevels, D3D11_SDK_VERSION, &lDevice, &FeatureLevel, &lImmediateContext))
IDXGIDevice* lDxgiDevice;
CHECKHR(lDevice->QueryInterface(IID_PPV_ARGS(&lDxgiDevice)))
//IDXGIAdapter* lDxgiAdapter;
//CHECKHR(lDxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&lDxgiAdapter))
lDxgiDevice->Release();
IDXGIOutput* lDxgiOutput;
CHECKHR(lDxgiAdapter->EnumOutputs(0, &lDxgiOutput))
lDxgiAdapter->Release();
CHECKHR(lDxgiOutput->GetDesc(&OutputDesc))
IDXGIOutput1* lDxgiOutput1;
CHECKHR(lDxgiOutput->QueryInterface(IID_PPV_ARGS(&lDxgiOutput1)))
lDxgiOutput->Release();
CHECKHR(lDxgiOutput1->DuplicateOutput(lDevice, &lDeskDupl))
// ...
Then, your code is not quite accurate around AcquireNextFrame. You need to wait for actual frame and do ReleaseFrame in the loop while you are skipping.
// ...
while (true)
{
if (SUCCEEDED(lDeskDupl->AcquireNextFrame(INFINITE, &FrameInfo, &lDesktopResource)) && FrameInfo.LastPresentTime.QuadPart)
{
break;
}
lDeskDupl->ReleaseFrame();
}
// ...

Setting default format on capture device via WinAPI

In an application I've been using the piece of code below to automatically set the 'Default Format' of the microphone to '2 channel, 16 bit, 48000Hz'.
This code works in Windows 7 an 8 en until recently also in Windows 10. Since some update of Windows 10 this year the code doesn't work anymore as expected. When I manually set the format to another value, like 44.1KHz in Sound - Mic - Advanced and I run the code, then the format is changed to '2 channel, 16 bit, 48000Hz', but I get no sound from the microphone. When I set the format manually to the correct value, then there are no problems.
Here is the piece of code:
IMMDevice* pEndpointRead = NULL;
IMMDevice* pEndpointWrite = NULL;
IMMDeviceEnumerator* pEnumerator = NULL;
IPropertyStore* propertyStoreRead = NULL;
IPropertyStore* propertyStoreWrite = NULL;
IAudioClient *audioClient = NULL;
PROPVARIANT propRead;
HRESULT hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pEnumerator);
hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &pEndpointRead);
hr = pEndpointRead->OpenPropertyStore(STGM_READ, &propertyStoreRead);
if (FAILED(hr))
{
std::cout << "OpenPropertyStore failed!" << std::endl;
}
hr = propertyStoreRead->GetValue(PKEY_AudioEngine_DeviceFormat, &propRead);
if (FAILED(hr))
{
std::cout << "GetValue failed!" << std::endl;
}
deviceFormatProperties =(WAVEFORMATEXTENSIBLE *)propRead.blob.pBlobData;
deviceFormatProperties->Format.nChannels = 2;
deviceFormatProperties->Format.nSamplesPerSec = 48000;
deviceFormatProperties->Format.wBitsPerSample = 16;
deviceFormatProperties->Samples.wValidBitsPerSample = deviceFormatProperties->Format.wBitsPerSample;
deviceFormatProperties->Format.nBlockAlign = (deviceFormatProperties->Format.nChannels*deviceFormatProperties->Format.wBitsPerSample) / 8;
deviceFormatProperties->Format.nAvgBytesPerSec = deviceFormatProperties->Format.nSamplesPerSec*deviceFormatProperties->Format.nBlockAlign;
deviceFormatProperties->dwChannelMask = KSAUDIO_SPEAKER_STEREO;
deviceFormatProperties->Format.cbSize = 22;
deviceFormatProperties->SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
hr = pEndpointRead->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (void**)&audioClient);
if (FAILED(hr))
{
std::cout << "pDevice->Activate failed!" << std::endl;
}
hr = audioClient->IsFormatSupported(/*AUDCLNT_SHAREMODE_SHARED*/AUDCLNT_SHAREMODE_EXCLUSIVE, (PWAVEFORMATEX)&deviceFormatProperties->Format, NULL);
if (FAILED(hr))
{
std::cout << "IsFormatSupported failed" << std::endl;
}
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID *)&pEnumerator);
hr = pEnumerator->GetDefaultAudioEndpoint(eCapture, eMultimedia, &pEndpointWrite);
hr= pEndpointWrite->OpenPropertyStore(STGM_WRITE, &propertyStoreWrite);
if (FAILED(hr))
{
std::cout << "OpenPropertyStore failed!" << std::endl;
}
hr = propertyStoreWrite->SetValue(PKEY_AudioEngine_DeviceFormat, propRead);
if (FAILED(hr))
{
std::cout << "SetValue failed!" << std::endl;
}
hr = propertyStoreWrite->Commit();
pEndpointWrite->Release();
pEnumerator->Release();
propertyStoreWrite->Release();
pEndpointRead->Release();
propertyStoreRead->Release();
pEndpointRead = NULL;
PropVariantClear(&propRead);
Any idea what could be the problem?

IMMDevice::Activate() with IBaseFilter return REGDB_E_CLASSNOTREG Class not registered

I want to get interface IBaseFilter system mixer, but get an error
REGDB_E_CLASSNOTREG Class not registered in:
hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);
Earlier this code to work.
Fully code:
filterName = "Stereo mixer (IDT High Definition Audio CODEC)"
HRESULT CCapture::GetAudioCaptureFilterByName(wstring *filterName, IBaseFilter **ppFilter)
{
HRESULT hr = S_OK;
IMMDeviceEnumerator *pEnumerator = 0;
IMMDeviceCollection *pCollection = 0;
IMMDevice *pEndpoint = 0;
IPropertyStore *pProps = 0;
LPWSTR pwszID = 0;
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
if (FAILED(hr)) return hr;
hr = pEnumerator->EnumAudioEndpoints(eCapture, DEVICE_STATE_ACTIVE, &pCollection);
if (FAILED(hr))
{
if (pEnumerator) pEnumerator->Release();
return hr;
}
UINT count;
hr = pCollection->GetCount(&count);
if (FAILED(hr))
{
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
if (count == 0)
{
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
for (ULONG i = 0; i < count; i++)
{
hr = pCollection->Item(i, &pEndpoint);
if (FAILED(hr))
{
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
// Получаем ID устройства.
hr = pEndpoint->GetId(&pwszID);
if (FAILED(hr))
{
if (pEndpoint) pEndpoint->Release();
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
hr = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);
if (FAILED(hr))
{
CoTaskMemFree(pwszID);
if (pEndpoint) pEndpoint->Release();
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
PROPVARIANT varName;
PropVariantInit(&varName);
// Получаем дружественное имя устройства.
hr = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
if (FAILED(hr))
{
CoTaskMemFree(pwszID);
if (pProps) pProps->Release();
if (pEndpoint) pEndpoint->Release();
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
wstring *wstr = new wstring(varName.pwszVal);
if (wstr->compare(*filterName) == 0)
{
DIRECTX_AUDIO_ACTIVATION_PARAMS daap;
daap.cbDirectXAudioActivationParams = sizeof(daap);
daap.guidAudioSession = guidAudioSessionId;
daap.dwAudioStreamFlags = AUDCLNT_STREAMFLAGS_CROSSPROCESS;
PROPVARIANT var;
PropVariantInit(&var);
var.vt = VT_BLOB;
var.blob.cbSize = sizeof(daap);
var.blob.pBlobData = (BYTE*)&daap;
hr = pEndpoint->Activate(__uuidof(IBaseFilter), CLSCTX_ALL, /*&var*/ NULL, (void**)ppFilter);
delete wstr;
CoTaskMemFree(pwszID);
PropVariantClear(&varName);
if (pProps) pProps->Release();
if (pEndpoint) pEndpoint->Release();
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
delete wstr;
CoTaskMemFree(pwszID);
pwszID = NULL;
PropVariantClear(&varName);
if (pProps) pProps->Release();
if (pEndpoint) pEndpoint->Release();
pProps = 0;
pEndpoint = 0;
}
hr = E_FAIL;
if (pProps) pProps->Release();
if (pEndpoint) pEndpoint->Release();
if (pCollection) pCollection->Release();
if (pEnumerator) pEnumerator->Release();
return hr;
}
The problem is caused by conflict with installed DirectShowSpy tool.
MMDevice's Activate for IBaseFilter presumably does the following:
if(interface is IBaseFilter)
{
IMMDeviceActivator pMmDeviceActivator;
CoCreateInstace(CLSID_SystemDeviceEnum, ..., &pMmDeviceActivator);
return pMmDeviceActivator->Activate(pMmDevice, ...)
}
Implementation of IMMDeviceActivator by System Device Enumerator CLSID_SystemDeviceEnum is undocumented (the interface is reserved for internal use) and DirectShowSpy did not handle it well. Since version 1.0.0.2106 it does it right.