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
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;
}
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
}
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();
}
// ...
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?
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.