So, i've been trying to retrieve the backbuffer data using a EndScene hook, the thing is that for some reason my GetBackBuffer is returning a invalid result (i think) because when i use pSurface->GetDesc() it returns that the backbuffer has Width 1 and height 1, and it always return the pBits filled with 0.
HRESULT WINAPI hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{
IDirect3DSurface9* pSurface = 0;
IDirect3DSurface9* pBBuffer = 0;
D3DLOCKED_RECT Lock;
D3DSURFACE_DESC desc;
if (pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurface) != D3D_OK)
{
logg << "ERROR GetBackBuffer: " << GetLastError() << endl;
return pEndScene(pDevice);
}
pSurface->GetDesc(&desc);
logg << "Size: " << desc.Width << ", " << desc.Height << endl;
HRESULT hRes = pDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &pBBuffer, NULL);
if (hRes != D3D_OK)
{
logg << "ERROR CreateOffscreenPlainSurface: " << GetLastError() << endl;
return pEndScene(pDevice);
}
hRes = pDevice->GetRenderTargetData(pSurface, pBBuffer);
if (hRes != D3D_OK)
{
logg << "ERROR GetRenderTargetData: " << GetLastError() << endl;
return pEndScene(pDevice);
}
pBBuffer->LockRect(&Lock, NULL, D3DLOCK_READONLY);
Com.DrawBuffer(Lock.pBits);
logg << Lock.pBits << endl;
//Usual free memory functions
pSurface->Release();
pBBuffer->UnlockRect();
pBBuffer->Release();
return pEndScene(pDevice);
}
Related
I'm trying to do a quick and dirty POC. I have a raw H264 file (Not mp4, no container whatsoever, just the raw H264 wrapped in NALU's) to simulate the device my application will ultimately be reading from.
I've been following the Media Foundation Docs. I'm simply reading the H264 file in chunks of 1024 bits using a standard fstream. This just simulated the data getting streamed. From there I'm manually creating IMFSamples and sending them to the decoder. It takes a couple passes to get enough data to fill a frame, but eventually it successfully decodes.
Once I try to pass that off to a IMFStreamSink that I got from the EVR, I get the HRESULT "E_NOINTERFACE No such interface supported" I know that the decompressed sample has data in it. I've used the debugger to confirm. I'm really confused why I'm getting this error as there is no additional data to go along with it.
Here is my code Isolated to the run loop:
while (true) {
// My Loop Stuff
IMFMediaBuffer* inputBuffer = CreateMediaBuffer(1024);
IMFSample* compressedSample = CreateMediaSample(inputBuffer);
if (compressedSample == NULL) {
return 1;
}
BYTE* tempBuff;
DWORD tempMaxLength = 0;
DWORD tempCurrentLength = 0;
hr = inputBuffer->Lock(
&tempBuff,
&tempMaxLength,
&tempCurrentLength
);
if (FAILED(hr)) {
std::cout << "Failed to lock buffer" << std::endl;
return 1;
}
inputTestFile.read((char*)tempBuff, tempMaxLength - tempCurrentLength);
hr = inputBuffer->SetCurrentLength(tempMaxLength - tempCurrentLength);
if (FAILED(hr)) {
std::cout << "Failed to set the lenght of the buffer" << std::endl;
return 1;
}
hr = inputBuffer->Unlock();
if (FAILED(hr)) {
std::cout << "FAILED to unlock buffer!" << std::endl;
return 1;
}
hr = pDecoder->ProcessInput(0, compressedSample, 0);
if (FAILED(hr)) {
std::cout << "Failed sending compressedSample to decoder" << std::endl;
IMFMediaBuffer* outputBuffer = CreateMediaBuffer(streamInfo.cbSize);
IMFSample* decompressedSample = CreateMediaSample(outputBuffer);
_MFT_OUTPUT_DATA_BUFFER outBuff = {};
outBuff.dwStreamID = 0;
outBuff.pSample = decompressedSample;
_MFT_OUTPUT_DATA_BUFFER outBuffs[] = { outBuff };
DWORD outStatus = 0;
hr = pDecoder->ProcessOutput(0, 1, outBuffs, &outStatus);
if (FAILED(hr)) {
std::cout << "FAILED TO PROCESS OUTPUT" << std::endl;
continue;
//return 1;
}
else {
std::cout << "Successfully decoded data!!!" << std::endl;
IMFMediaEvent* mediaEvent = NULL;
ssink->GetEvent(0, &mediaEvent);
if (mediaEvent == NULL) {
// Nothing to do.. Wait for a request for more
continue;
}
hr = ssink->ProcessSample(decompressedSample);
if (FAILED(hr)) {
std::cout << "Failed to process sample to sink" << std::endl;
continue;
}
}
}
// END My Loop Stuff
}
Here is my complete code: (Search for "My Stuff" and "My Loop Stuff" to get around all the boilerplate)
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_H264RENDERINGWINDOW, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_H264RENDERINGWINDOW));
MSG msg;
// My Stuff
HRESULT hr = S_OK;
UINT32 count = 0;
hr = MFStartup(MF_VERSION);
if (FAILED(hr)) {
return 1;
}
IMFActivate** ppActivate = NULL; // Array of activation objects.
IMFTransform* pDecoder = NULL; // Pointer to the decoder.
// Match WMV3 video.
MFT_REGISTER_TYPE_INFO info = { MFMediaType_Video, MFVideoFormat_H264 };
UINT32 unFlags = MFT_ENUM_FLAG_SYNCMFT |
MFT_ENUM_FLAG_LOCALMFT |
MFT_ENUM_FLAG_SORTANDFILTER;
hr = MFTEnumEx(
MFT_CATEGORY_VIDEO_DECODER,
unFlags,
&info, // Input type
NULL, // Output type
&ppActivate,
&count
);
if (SUCCEEDED(hr) && count == 0)
{
std::cout << "NOT SUCCESS!!!!" << std::endl;
//hr = MF_E_TOPO_CODEC_NOT_FOUND;
return 1;
}
// Create the first decoder in the list.
if (SUCCEEDED(hr))
{
std::cout << "SUCCESS AGAIN!!!" << std::endl;
hr = ppActivate[0]->ActivateObject(IID_PPV_ARGS(&pDecoder));
}
DWORD pcInputStreamsNum = 0;
DWORD pcOutputStreamsNum = 0;
hr = pDecoder->GetStreamCount(
&pcInputStreamsNum,
&pcOutputStreamsNum
);
if (FAILED(hr)) {
std::cout << "Unable to get stream count" << std::endl;
return 1;
}
std::cout << "Available Input Streams: " << pcInputStreamsNum << " Available Output Streams: " << pcOutputStreamsNum << std::endl;
IMFMediaType* pInMediaType = NULL;
hr = MFCreateMediaType(
&pInMediaType
);
if (FAILED(hr)) {
std::cout << "Unable to create Input Media Type" << std::endl;
return 1;
}
hr = pDecoder->GetInputAvailableType(
0,
0,
&pInMediaType
);
if (FAILED(hr)) {
std::cout << "Unable to get Input Media Type for Decoder" << std::endl;
return 1;
}
hr = pDecoder->SetInputType(
0,
pInMediaType,
0
);
if (FAILED(hr)) {
std::cout << "Unable to set Media Type for Decoder" << std::endl;
return 1;
}
IMFMediaType* pOutMediaType = NULL;
hr = MFCreateMediaType(
&pOutMediaType
);
hr = pDecoder->GetOutputAvailableType(0, 0, &pOutMediaType);
if (FAILED(hr)) {
std::cout << "Unable to get output type" << std::endl;
return 1;
}
GUID v;
hr = pOutMediaType->GetGUID(MF_MT_SUBTYPE, &v);
if (FAILED(hr)) {
std::cout << "Unable to get output media sub-type" << std::endl;
return 1;
}
hr = pDecoder->SetOutputType(0, pOutMediaType, 0);
if (FAILED(hr)) {
std::cout << "Failed setting output type" << std::endl;
return 1;
}
hr = pDecoder->ProcessMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, NULL);
if (FAILED(hr)) {
std::cout << "Failed to send begin streaming message" << std::endl;
return 1;
}
std::cout << "Successfully Initialized the Decoder..." << std::endl;
std::ifstream inputTestFile = std::ifstream("c:\\open\\fbsource\\arvr\\apps\\MagicIsle\\magic-capture.h264", std::ios::binary);
if (!inputTestFile.is_open()) {
std::cout << "unable to open test input file, did run with --capture previously?"
<< std::endl;
return 1;
}
MFT_INPUT_STREAM_INFO inStreamInfo{};
hr = pDecoder->GetInputStreamInfo(
0,
&inStreamInfo
);
if (FAILED(hr)) {
std::cout << "Failed to get the stream info" << std::endl;
return 1;
}
std::cout << "Stream Info: ";
if (inStreamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES" << std::endl;
}
else if (inStreamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_PROVIDES_SAMPLES" << std::endl;
}
MFT_OUTPUT_STREAM_INFO streamInfo{};
hr = pDecoder->GetOutputStreamInfo(
0,
&streamInfo
);
if (FAILED(hr)) {
std::cout << "Failed to get the stream info" << std::endl;
return 1;
}
std::cout << "Stream Info: ";
if (streamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES" << std::endl;
}
else if (streamInfo.dwFlags == MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES) {
std::cout << "MFT_OUTPUT_STREAM_PROVIDES_SAMPLES" << std::endl;
}
else {
std::cout << "NEITHER" << std::endl;
}
IMFPresentationClock* clock = NULL;
hr = MFCreatePresentationClock(&clock);
if (FAILED(hr)) {
return 1;
}
IMFPresentationTimeSource* timeSource = NULL;
hr = MFCreateSystemTimeSource(&timeSource);
if (FAILED(hr)) {
return 1;
}
hr = clock->SetTimeSource(timeSource);
if (FAILED(hr)) {
return 1;
}
hr = clock->Start(0);
if (FAILED(hr)) {
return 1;
}
hr = pRenderer->SetPresentationClock(clock);
if (FAILED(hr)) {
return 1;
}
DWORD rendererCharacteristics = 0;
hr = pRenderer->GetCharacteristics(&rendererCharacteristics);
if ((rendererCharacteristics & MEDIASINK_CANNOT_MATCH_CLOCK) == MEDIASINK_CANNOT_MATCH_CLOCK) {
std::cout << "Cannot Match Clock" << std::endl;
}
if ((rendererCharacteristics & MEDIASINK_RATELESS) == MEDIASINK_RATELESS) {
std::cout << "Rateless" << std::endl;
}
if (FAILED(hr)) {
return 1;
}
IMFStreamSink* ssink = NULL;
hr = pRenderer->GetStreamSinkById(0, &ssink);
if (FAILED(hr)) {
return 1;
}
IMFMediaTypeHandler* ssinkMediaTypeHandler = NULL;
hr = ssink->GetMediaTypeHandler(&ssinkMediaTypeHandler);
if (FAILED(hr)) {
return 1;
}
hr = ssinkMediaTypeHandler->SetCurrentMediaType(pOutMediaType);
// End My Stuff
auto f = [&] {
while (true) {
// My Loop Stuff
IMFMediaBuffer* inputBuffer = CreateMediaBuffer(1024);
IMFSample* compressedSample = CreateMediaSample(inputBuffer);
if (compressedSample == NULL) {
return 1;
}
BYTE* tempBuff;
DWORD tempMaxLength = 0;
DWORD tempCurrentLength = 0;
hr = inputBuffer->Lock(
&tempBuff,
&tempMaxLength,
&tempCurrentLength
);
if (FAILED(hr)) {
std::cout << "Failed to lock buffer" << std::endl;
return 1;
}
inputTestFile.read((char*)tempBuff, tempMaxLength - tempCurrentLength);
hr = inputBuffer->SetCurrentLength(tempMaxLength - tempCurrentLength);
if (FAILED(hr)) {
std::cout << "Failed to set the lenght of the buffer" << std::endl;
return 1;
}
hr = inputBuffer->Unlock();
if (FAILED(hr)) {
std::cout << "FAILED to unlock buffer!" << std::endl;
return 1;
}
hr = pDecoder->ProcessInput(0, compressedSample, 0);
if (FAILED(hr)) {
std::cout << "Failed sending compressedSample to decoder" << std::endl;
IMFMediaBuffer* outputBuffer = CreateMediaBuffer(streamInfo.cbSize);
IMFSample* decompressedSample = CreateMediaSample(outputBuffer);
_MFT_OUTPUT_DATA_BUFFER outBuff = {};
outBuff.dwStreamID = 0;
outBuff.pSample = decompressedSample;
_MFT_OUTPUT_DATA_BUFFER outBuffs[] = { outBuff };
DWORD outStatus = 0;
hr = pDecoder->ProcessOutput(0, 1, outBuffs, &outStatus);
if (FAILED(hr)) {
std::cout << "FAILED TO PROCESS OUTPUT" << std::endl;
continue;
//return 1;
}
else {
std::cout << "Successfully decoded data!!!" << std::endl;
IMFMediaEvent* mediaEvent = NULL;
ssink->GetEvent(0, &mediaEvent);
if (mediaEvent == NULL) {
// Nothing to do.. Wait for a request for more
continue;
}
hr = ssink->ProcessSample(decompressedSample);
if (FAILED(hr)) {
std::cout << "Failed to process sample to sink" << std::endl;
continue;
}
}
}
// END My Loop Stuff
}
};
std::thread t(f);
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
t.join();
return (int) msg.wParam;
}
Once I try to pass that off to a IMFStreamSink that I got from the EVR, I get the HRESULT "E_NOINTERFACE No such interface supported" I know that the decompressed sample has data in it. I've used the debugger to confirm. I'm really confused why I'm getting this error as there is no additional data to go along with it.
You are sending a sample to the sink when it's in wrong state.
Per Media Sinks >> Data Flow #3, you are responsible to work with events and asynchronous model of Media Foundation sinks. Specifically, media sink requests sample first and only then you can send it.
Normally Media Session or other Media Foundation APIs handle this, but in your case it's your responsibility.
I want to control all the app volumes programatically in my cpp program. Basically i would like to be able to control independently each app volume as the windows sound mixer does.
from what I read in the windows api doc, I first need to fetch the default endpoint and then the default audio session.
I'm yet done with this I think, that's what I have :
#include <mmdeviceapi.h>
#include <endpointvolume.h>
#include <Audioclient.h>
#include <audiopolicy.h>
#include <iostream>
int main() {
HRESULT hr = CoInitialize(NULL);
if (hr != S_OK) {
std::cout << "error initializing : " << hr << std::endl;
return -1;
}
else
std::cout << "successfully initialized\n";
IMMDeviceEnumerator* pEnumerator = NULL;
hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (LPVOID*)&pEnumerator);
if (hr != S_OK) {
std::cout << "error creating instance : " << hr << std::endl;
return -1;
}
else {
std::cout << "successfully created instance\n";
}
IMMDevice* pDevice = NULL;
hr = pEnumerator->GetDefaultAudioEndpoint(EDataFlow::eRender, ERole::eConsole, &pDevice);
pEnumerator->Release();
pEnumerator = NULL;
if (hr != S_OK) {
std::cout << "error getting default endpoint device : " << hr << std::endl;
return -1;
}
else {
LPWSTR id = NULL;
pDevice->GetId(&id);
DWORD state = 0;
pDevice->GetState(&state);
std::cout << "found device 0x" << id << " with state " << state << std::endl;
}
IAudioClient* audioClient = NULL;
hr = pDevice->Activate(__uuidof(IAudioClient), CLSCTX_ALL, NULL, (LPVOID*)&audioClient);
if (hr != S_OK) {
std::cout << "failed instantiating audio client " << hr << std::endl;
pDevice->Release();
pDevice = NULL;
return -1;
}
else {
std::cout << "successfully instantiated audio client" << std::endl;
}
IAudioSessionManager2* sessionManager = NULL;
hr = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (LPVOID*) &sessionManager);
pDevice->Release();
pDevice = NULL;
if (hr != S_OK) {
std::cout << "failed instantiating session manager " << hr << std::endl;
return -1;
}
else {
std::cout << "successfully instantiated sessionManager" << std::endl;
}
IAudioSessionControl2* sessionControl = NULL;
hr = sessionManager->GetAudioSessionControl(&GUID_NULL, FALSE, (IAudioSessionControl**)&sessionControl);
if (hr != S_OK) {
std::cout << "failed retrieving session control " << hr << std::endl;
return -1;
}
LPWSTR sessionId = NULL;
hr = sessionControl->GetSessionIdentifier(&sessionId);
if (hr != S_OK) {
std::cout << "failed retrieving session id " << hr << std::endl;
return -1;
}
GUID sessionGuid = {};
hr = CLSIDFromString(sessionId, &sessionGuid);
if (hr != S_OK) {
std::cout << "failed transforming to GUID " << hr << std::endl;
// got fail here the error code is CO_E_CLASSSTRING -> hr = -2147221005
return -1;
}
//need GUID to initialize audio client or get service will fail
IChannelAudioVolume* channelVolume = NULL;
audioClient->GetService(__uuidof(IChannelAudioVolume), (LPVOID*)&channelVolume);
// is there any better way to list all the channels so i can get the name or the process id of each channel
// is channel the right object to use in this case
sessionControl->Release();
sessionControl = NULL;
sessionManager->Release();
sessionManager = NULL;
audioClient->Release();
audioClient = NULL;
CoUninitialize();
return 0;
}
the program fails when it reaches the id to guid part of the code. How to solve that and will the IChannelAudioVolume allow me to change specific app volumes.
I would also appreciate any samples if existing.
I'm using a file that has MBR code at an offset of 54 bytes.
In the main() function, I'm calling OpenMBbrFile(), then ReadMbrData().
However, I'm not able to read MBR in my Buffer Properly. Please Help Me with the Issue..................................................................................................................................................................................................................................................................................................................................................................................................................
BOOL OpenMbrFile(LPWSTR sPath)
{
cout << "OpenMBR: Create Handle" << endl;
m_hMbrFile = CreateFile(sPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL);
if (m_hMbrFile == INVALID_HANDLE_VALUE) return FALSE;
return TRUE;
}
BOOL CloseMbrFile()
{
cout << "CloseMBR: Closing Handle" << endl;
BOOL bReturn = TRUE;
if (m_hMbrFile != INVALID_HANDLE_VALUE)
bReturn = CloseHandle(m_hMbrFile);
m_hMbrFile = NULL;
cout << "Returning from CloseMBR" << endl;
return bReturn;
}
BOOL ReadMbrData()
{
cout << "ReadMBR: Initialization" << endl;
BOOL bReturn = FALSE;
DWORD dwByteRead = 0;
LARGE_INTEGER filepointer;
filepointer.QuadPart = 54; //MBR data in File at offset 54
BYTE* pBuff = NULL;
pBuff = new BYTE[512];
if (!pBuff)
{
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
if (m_hMbrFile == INVALID_HANDLE_VALUE) return FALSE;
cout << "ReadMBR: Setting fp" << endl;
if(!SetFilePointerEx(m_hMbrFile, filepointer, NULL, FILE_BEGIN))
{
cout << "Failed to SetFilePointer ( " << m_hMbrFile << ", " << filepointer.QuadPart << ", 0, FILE_BEGIN)" << endl;
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
cout << "ReadMBR: Starting to read File" << endl;
bReturn = ReadFile(m_hMbrFile, pBuff, sizeof(*pBuff), &dwByteRead, 0);
if (bReturn)
bReturn = (sizeof(*pBuff) == dwByteRead); //Need to check this condition? shd it be 512 or size of wud do??
cout << "ReadMBR: Cleaning Stuff up" << endl;
if (pBuff) delete[] pBuff;
CloseMbrFile();
ClosePhysicalDrive();
return bReturn;
}
Iam trying to find the IntegrationServiceVersionState of the VM's present in hyper V code using wmi object in c++
IntegrationServiceVersionState can be accessed by calling GetSummaryInformation method of the Msvm_VirtualSystemManagementService class present in root\virtualization\v2 namespace
the snippet of code am facing error is
// Set up to call the Msvm_VirtualSystemManagementService::GetSummaryInformation method
BSTR ClassName = SysAllocString(L"Msvm_VirtualSystemManagementService");
BSTR MethodName = SysAllocString(L"GetSummaryInformation");
cout << "setup initialised" << endl;
//get class
IWbemClassObject* pClass = NULL;
hr = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
cout << "class object got" << endl;
GetWMIError(hr);
//to get the path of the class
IEnumWbemClassObject* pEnumerator1 = NULL;
hr = pSvc->ExecQuery(
BSTR(L"WQL"),
BSTR(L"select * from MSVM_VirtualSystemManagementService "),/*where Caption=\"Virtual Machine\"*/
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator1);
IWbemClassObject* pVirtualSystemManagementServiceObj = NULL;
ULONG uReturn1 = 0;
hr = pEnumerator1->Next(WBEM_INFINITE, 1, &pVirtualSystemManagementServiceObj, &uReturn1);
if (uReturn1 == 0)
{
cout << " couldnt load class path " << endl;
}
VARIANT classpath;
hr = pVirtualSystemManagementServiceObj->Get(L"__Path", 0, &classpath, 0, 0);
wcout << " __Path : " << classpath.bstrVal << endl;
// Get Method
IWbemClassObject* pInParamsDefinition = NULL;
hr = pClass->GetMethod(MethodName, 0, &pInParamsDefinition, NULL);
cout << "method object got" << endl;
GetWMIError(hr);
// get spawn instance
IWbemClassObject* pClassInstance = NULL;
hr = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
cout << "SpAwn instanaaace e" << endl;
GetWMIError(hr);
//setting data
VARIANT SetData ;
VariantInit(&SetData);
SetData.vt = VT_NULL;
hr = pClassInstance->Put(L"SettingData", 0, &SetData, 0);
if (FAILED(hr))
{
cout << "failed to load setting data parameter" << endl;
}
GetWMIError(hr);
cout << "1st parameter set" << endl;
//requested information
VARIANT reqInfo;
VariantInit(&reqInfo);
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = 2;
CComSafeArray<int> arr(5);
arr[0] = 1;
arr[1] = 123;
long nIndex = 0;
psa = SafeArrayCreate(VT_I4, 1, rgsabound);
hr = SafeArrayPutElement(psa, &nIndex, &arr[0]);
nIndex++;
SafeArrayPutElement(psa, &nIndex, &arr[1]);
reqInfo.vt = VT_ARRAY | VT_I4;
reqInfo.parray = psa;
hr = pClassInstance->Put(L"RequestedInformation", 0, &reqInfo, 0);
GetWMIError(hr);
cout << "2nd parameter set" << endl;
//execute method
IWbemClassObject* pOutParams = NULL;
hr = pSvc->ExecMethod(classpath.bstrVal, MethodName, 0, NULL, pClassInstance, &pOutParams, NULL);
GetWMIError(hr);
if (FAILED(hr))
{
cout << "Could not execute method. Error code = 0x" << hex << hr << endl;
}
GetWMIError(hr);
cout << "method executed" << endl;
the above code works properly but am facing problem in the below code
VARIANT varReturnValue;
VariantInit(&varReturnValue);
hr = pOutParams->Get(_bstr_t(L"ReturnValue"), 0,&varReturnValue, NULL, 0);
if (SUCCEEDED(hr))
{
if (varReturnValue.vt == VT_I4)
{
CIMTYPE ct;
VARIANT varJob;
VariantInit(&varJob);
hr = pOutParams->Get(_bstr_t(L"SummaryInformation"), 0, &varJob, &ct, 0);
if (SUCCEEDED(hr))
{
if (varJob.vt == VT_ARRAY | VT_UNKNOWN)
{
VARIANT myvar;
myvar.vt = VT_ARRAY | VT_UNKNOWN;
SAFEARRAY* pSafeArray = V_ARRAY(&myvar);
long lBound, uBound;
SafeArrayGetLBound(pSafeArray, 1, &lBound);
SafeArrayGetUBound(pSafeArray, 1, &uBound);
cout << lBound << endl;
cout << uBound << endl;
UINT16 Element = NULL;
for (long i = lBound; i <= uBound; i++)
{
hr = SafeArrayGetElement(pSafeArray, &i, &Element);
wcout << Element << endl;
}
}
}
}
}
I got the number of VM's correctly, but facing error in getting the array elements. It just throws some garbage values.
Please some one help to rectify this issue
I need to receive screenshots from MS Mirror driver, but unexpectedly I noticed, that CreateDC() function returns NULL and GetLastError gives me Error#1801 ("The printer name is invalid")
extern "C" __declspec(dllexport) HDC InitDC() {
DWORD dwAttach = 0;
DEVMODE devmode;
// Make sure we have a display on this thread.
BOOL change = EnumDisplaySettings(NULL,
ENUM_CURRENT_SETTINGS,
&devmode);
LPCWSTR driverName = L"Microsoft Mirror Driver";
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION ;
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
if (change)
{
// query all display devices in the system until we hit a primary
// display device. Using it get the width and height of the primary
// so we can use that for the mirror driver. Also enumerate the
// display devices installed on this machine untill we hit
// our favourate mirrored driver, then extract the device name string
// of the format '\\.\DISPLAY#'
DISPLAY_DEVICE dispDevice;
FillMemory(&dispDevice, sizeof(DISPLAY_DEVICE), 0);
dispDevice.cb = sizeof(DISPLAY_DEVICE);
LPCWSTR deviceName = NULL;
devmode.dmDeviceName[0] = '\0';
INT devNum = 0;
BOOL result;
DWORD cxPrimary = 0xFFFFFFFF;
DWORD cyPrimary = 0xFFFFFFFF;
// First enumerate for Primary display device:
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
wcout << "DriverName: " << dispDevice.DeviceString << endl;
wcout << "DevName: " << dispDevice.DeviceName << endl;
if (dispDevice.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
// Primary device. Find out its dmPelsWidht and dmPelsHeight.
EnumDisplaySettings(dispDevice.DeviceName,
ENUM_CURRENT_SETTINGS,
&devmode);
cxPrimary = devmode.dmPelsWidth;
cyPrimary = devmode.dmPelsHeight;
wcout << "Selected Primary DevName (width, height): " << dispDevice.DeviceName << " (" << cxPrimary << "," << cyPrimary << ")" << endl << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
if (cxPrimary == 0xffffffff || cyPrimary == 0xffffffff)
{
wcout << "cxPrimary or cyPrimary not valid" << endl;
exit(0);
}
// Enumerate again for the mirror driver:
devNum = 0;
while ((result = EnumDisplayDevices(NULL,
devNum,
&dispDevice,
0)) == TRUE)
{
LPCWSTR devString = dispDevice.DeviceString;
wcout << " devString: "<< devString << endl;
if (wcscmp(devString, driverName ) == 0) {
wcout << " Driver selected: "<< driverName << endl;
break;
}
devNum++;
}
// error check
if (!result)
{
wcout << "No " << driverName << " found " << endl;
exit(0);
}
wcout << "DevNum " << devNum << endl <<
"DeviceName: " << dispDevice.DeviceName << endl <<
"DeviceString: " << dispDevice.DeviceString << endl <<
"DeviceID: " << dispDevice.DeviceID << endl <<
"DeviceKey: " << dispDevice.DeviceKey << endl;
CHAR *deviceNum = new CHAR[MAX_PATH];
LPSTR deviceSub;
// Simply extract 'DEVICE#' from registry key. This will depend
// on how many mirrored devices your driver has and which ones
// you intend to use.
_wcsupr(&dispDevice.DeviceKey[0]);
deviceSub = (LPSTR)(wcsstr(&dispDevice.DeviceKey[0],
L"\\DEVICE"));
if (!deviceSub) {
printf("deviceSub - yes \n");
deviceNum[0] = (CHAR)(((string)("DEVICE0")).c_str());
}
else {
printf("!deviceSub \n");
deviceNum[0] = (CHAR)(((string)("DEVICE1")).c_str());
}
// Reset the devmode for mirror driver use:
FillMemory(&devmode, sizeof(DEVMODE), 0);
devmode.dmSize = sizeof(DEVMODE);
devmode.dmDriverExtra = 0;
devmode.dmFields = DM_BITSPERPEL |
DM_PELSWIDTH |
DM_PELSHEIGHT |
DM_POSITION;
//wcscpy( devmode.dmDeviceName, sizeof(devmode.dmDeviceName, L"mirror" );
deviceName = dispDevice.DeviceName;
StringCbCopy(devmode.dmDeviceName, sizeof(devmode.dmDeviceName), dispDevice.DeviceName);
wcout << "dmDeviceName: " << devmode.dmDeviceName << endl;
wcout << "deviceName: " << deviceName << endl;
wcout << "driverName: " << driverName << endl;
/* !!! THE PROBLEM IS HERE !!!*/
HDC hdc = CreateDC(driverName, deviceName, NULL, &devmode );
if ( hdc == NULL ) {
wcout << "CreateDC error: " << GetLastError() << endl;
return NULL;
}
return hdc;
}
return NULL;
}
Thanks for an assistance!
UPD1:
deviceName = "\\.\DISPLAYV1"
driverName = "Microsoft Mirror Driver"
devmode.dmDeviceName = "\\.\DISPLAYV1"