Some Service interface are not supported in the MFGetService helper function - c++

I'm trying to get a pointer to the IDirect3DSurface9 and I use the the helper function MFGetService and I pass MR_BUFFER_SERVICE to the second parameter.While linking,I received a "unresolved external symbol _MR_BUFFER_SERVICE" error.
I looked up the definition of MR_BUFFER_SERVICE in evr.h and found a macro describing it:
DEFINE_GUID(MR_BUFFER_SERVICE,
0xa562248c,
0x9ac6,
0x4ffc,
0x9f, 0xba, 0x3a, 0xf8, 0xf8, 0xad, 0x1a, 0x4d
);
And then I decided to make this GUID on my own and passed to the MFGetService, but then I get the error code E_NOINTERFACE while debugging.
//Here are the GUID struct I made:
const GUID FAR MR_BUFFER_SERVICE = { 0xa562248c,0x9ac6,0x4ffc, {0x9f, 0xba, 0x3a, 0xf8, 0xf8, 0xad, 0x1a, 0x4d} };
//The main code of getting a pointer to IDirect3DSurface9:
IDirect3DSurface9 *d3dsurface9;
IMFMediaBuffer* pBuffer = NULL;
hr = MFCreateMemoryBuffer(1024 * 10, &pBuffer);
if (FAILED(hr))
{
MessageBox(NULL, L"fail in creating Media Buffer", NULL, NULL);
}
hr = MFGetService(pBuffer, MR_BUFFER_SERVICE,
IID_PPV_ARGS(&d3dsurface9));
if (FAILED(hr))
{
MessageBox(NULL, L"failed in getting IDirect3DSurface9", NULL, NULL);
}

Linker error is to be resolved by additionally linking strmiids.lib
#pragma comment(lib, "strmiids.lib")
MR_BUFFER_SERVICE is not available from generic system memory backed buffers you create by MFCreateMemoryBuffer. This service is only available from buffers which are wrapping respective D3D9 surface, esp. created with MFCreateDXSurfaceBuffer function.
The details are documented here: DirectX Surface Buffer.

Related

Disable Aeroshake minimize by GPO

I'm trying to disable Aeroshake minimize mouse gesture only. Asked a question How to disable Aero Shake minimize only on Windows 7 but no answers. So I continued digging and found another solution by updating user Group Policy.
void aeroshake(DWORD action)
{
HRESULT hr;
IGroupPolicyObject* pLGPO;
HKEY machine_key, dsrkey;
LSTATUS sdf, ds, rStatus;
GUID RegistryId = REGISTRY_EXTENSION_GUID;
GUID ThisAdminToolGuid =
/*{ CLSID_PolicySnapinUser/* */
{
0x0F6B957E,
0x509E,
0x11D1,
{ 0xA7, 0xCC, 0x00, 0x00, 0xF8, 0x75, 0x71, 0xE3 }
};
const IID my_IID_IGroupPolicyObject =
{ 0xea502723, 0xa23d, 0x11d1,{ 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } };
const IID my_CLSID_GroupPolicyObject =
{ 0xea502722, 0xa23d, 0x11d1,{ 0xa7, 0xd3, 0x0, 0x0, 0xf8, 0x75, 0x71, 0xe3 } };
GUID ext_guid = REGISTRY_EXTENSION_GUID;
// This next one can be any GUID you want
GUID snap_guid = { 0x3d271cfc, 0x2bc6, 0x4ac2,{ 0xb6, 0x33, 0x3b, 0xdf, 0xf5, 0xbd, 0xab, 0x2a } };
// Create an instance of the IGroupPolicyObject class
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
CoCreateInstance(my_CLSID_GroupPolicyObject, NULL, CLSCTX_INPROC_SERVER,
my_IID_IGroupPolicyObject, (LPVOID*)&pLGPO);
// We need the machine LGPO (if C++, no need to go through the lpVtbl table)
hr = pLGPO->OpenLocalMachineGPO(GPO_OPEN_LOAD_REGISTRY);
if (hr != S_OK) {
goto release;
}
hr = pLGPO->GetRegistryKey(GPO_SECTION_USER, &machine_key);
if (hr != S_OK) {
goto close;
}
// create key for disable Aeroshake minimise
sdf = RegCreateKeyEx(machine_key, TEXT("Software\\Policies\\Microsoft\\Windows\\Desktop\\NoWindowMinimizingShortcuts"),
0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &dsrkey, NULL);
// Create the value
ds = RegSetKeyValue(dsrkey, NULL, TEXT("NoWindowMinimizingShortcuts"), REG_DWORD, &action, sizeof(action));
RegCloseKey(dsrkey);
// Apply policy and free resources
pLGPO->Save( TRUE, TRUE, &ext_guid, &snap_guid);
rStatus = RegCloseKey(machine_key);
// Write the GPO back to the directory
hr = pLGPO->Save(
FALSE,
TRUE,
&RegistryId,
&ThisAdminToolGuid);
close:
RegCloseKey(machine_key);
release:
pLGPO->Release();
}
This looks like a proper way but I have problem with OpenLocalMachineGPO it always returns E_ACCESSDENIED. Can that be sorted w/o need to run as Admin. Also when the code run as Admin it still doesn't change the required policy.
E_ACCESSDENIED means no access, of course you need enough permissions to modify the GPO.
In addition, The key value NoWindowMinimizingShortcuts is under the Sub Key Software\\Policies\\Microsoft\\Windows\\Explorer
sdf = RegCreateKeyEx(machine_key, TEXT("Software\\Policies\\Microsoft\\Windows\\Explorer"),
0, NULL, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, &dsrkey, NULL);
You'll need to reboot or at least log off, then log in to take effect.(Even you modify in GPO directly)
Then the changes will be updated to HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer:
NoWindowMinimizingShortcuts = 0x00000001
Of course, you can also modify this key directly.(need to create it first if you don't have one)
void aeroshake(DWORD action)
{
// create key for disable Aeroshake minimise
HKEY hKeyRoot, dsrkey;
LSTATUS sdf = RegOpenKey(HKEY_CURRENT_USER, TEXT("Software\\Policies\\Microsoft\\Windows"), &hKeyRoot);
sdf = RegCreateKey(hKeyRoot, TEXT("Explorer"), &dsrkey);
// Create the value
sdf = RegSetKeyValue(dsrkey, NULL, TEXT("NoWindowMinimizingShortcuts"), REG_DWORD, &action, sizeof(action));
RegCloseKey(dsrkey);
}

Why CoCreateInstance can't create an instance of my component?

I am learning COM through the book "Inside COM" of Dale Rogerson. I try to register my component in the registry and then through this info create an instance of my component in the code of my client. But I see ::FormatMessage function writes this: Class not registered. So, ::CoCreateInstance can't create an instance of my component.
My REG-file:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\CLSID\{68584B56-9224-4DCC-AD35-1070CC9B8FDE}]
#="bush_component_01"
[HKEY_CLASSES_ROOT\CLSID\{68584B56-9224-4DCC-AD35-1070CC9B8FDE}\InprocServer32]
#="D:\\projects\\com_sandbox_solution_01\\Debug\\bush_component_01.dll"
[HKEY_CLASSES_ROOT\CLSID\{EB4BFC91-6A6E-43D1-B4CD-7A5DF24DB8D8}]
#="IID_IX"
[HKEY_CLASSES_ROOT\CLSID\{EB4BFC91-6A6E-43D1-B4CD-7A5DF24DB8D8}\InprocServer32]
#="D:\\projects\\com_sandbox_solution_01\\Debug\\bush_component_01.dll"
Piece of code of my client:
...
// GUID of my DLL (it registered in registry (look at my REG-code above))
// {68584B56-9224-4DCC-AD35-1070CC9B8FDE}
static const CLSID CLSID_component_01 =
{ 0x68584b56, 0x9224, 0x4dcc, { 0xad, 0x35, 0x10, 0x70, 0xcc, 0x9b, 0x8f, 0xde } };
// GUID of my some interface (it registered in registry (look at my REG-code above))
// {EB4BFC91-6A6E-43D1-B4CD-7A5DF24DB8D8}
static const IID IID_IX =
{ 0xeb4bfc91, 0x6a6e, 0x43d1, { 0xb4, 0xcd, 0x7a, 0x5d, 0xf2, 0x4d, 0xb8, 0xd8 } };
...
// Code of my client:
::CoInitialize(nullptr);
IUnknown* comp = nullptr;
HRESULT hcri = ::CoCreateInstance(CLSID_component_01, nullptr,
CLSCTX_INPROC_SERVER, IID_IX, (void**)&comp);
if (FAILED(hcri)){
void* msg = nullptr;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
nullptr, hcri, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&msg, 0,
nullptr);
trace("***** TRACE *****");
trace((LPTSTR)msg);
trace("****************");
keep_window_open();
return 1;
}
// But ::FormatMessage function writes this: Class not registered
Why does it happen?
In 64-bit Windows 32-bit applications should use Wow6432Node registry subkey (in terms of 64-bit regedit).
Unfortunately 32-bit book does not cover that.

Pins avaiable in graphstudio not there in code

I am using a source filter of a webcam. When I use the filter in graphstudio it has two output pins. However in code the call to IEnumPins->next always returns S_FALSE.
I also looked for another interface that could create pins but didn't find such a thing.
How do I add pins to the webcam filter? If they're available in graphstudio they should be in code too, right?
Here is my code.. I checked for return values and returned them if they are not ok. But everything seems to work fine except that the webcam filter doesn't return any pins
CoInitialize(NULL);
IGraphBuilder* graphBuilder = NULL;
IMediaControl* mediaControl = NULL;
IMediaEvent* mediaEvent = NULL;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph, (void **)&graphBuilder);
HANDLE fileHandle = CreateFile(L"D:\\TEMP\\debug1.log", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
graphBuilder->SetLogFile((DWORD_PTR)fileHandle);
graphBuilder->QueryInterface(IID_IMediaControl, (void **)&mediaControl);
graphBuilder->QueryInterface(IID_IMediaEvent, (void **)&mediaEvent);
IBaseFilter* source = NULL;
static const GUID CLSID_Webcam =
{ 0x17CCA71B, 0xECD7, 0x11D0, { 0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } };
hr = CoCreateInstance(CLSID_Webcam, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&source);
if (FAILED(hr))
return hr;
hr = graphBuilder->AddFilter(source, L"logitech");
if (FAILED(hr))
return hr;
IPin* camOut = GetPin(source, PINDIR_OUTPUT);
...
The GetPin function uses EnumPins method to find pin:
IPin *GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{
BOOL bFound = FALSE;
IEnumPins *pEnum;
IPin *pPin;
pFilter->EnumPins(&pEnum);
while (pEnum->Next(1, &pPin, 0) == S_OK)
{
PIN_DIRECTION PinDirThis;
pPin->QueryDirection(&PinDirThis);
if (bFound = (PinDir == PinDirThis))
break;
pPin->Release();
}
pEnum->Release();
return (bFound ? pPin : 0);
}
Also, I don't think that this is 32/64bit problem. I compile to x64 and I also used the 64bit version of graphstudionext. And i also made sure that the guid of the webcam filter is correct. (At least if you can trust graphstudionext)
This is an indication that your code deals with another filter or has bugs otherwise. You normally don't "create" pins, especially on video device backed source filter. Typical reasons are: (a) you are effectively creating a different filter, (b) direct bug in your code, (c) 32/64-bit issue with different filters in the two environments. There can hardly be anything else. Stepping and inspecting your code thoroughly, adding debug output should take you to the solution.
UPDATE. Video capture devices like this cannot be instantiated using CoCreateInstance. You have to create them using monikers. typically through enumeration, as described on MSDN (with source code snippet): Selecting a Capture Device.
The code below is incorrect, FYI this GUID is declared in SDK as CLSID_Proxy.
static const GUID CLSID_Webcam =
{ 0x17CCA71B, 0xECD7, 0x11D0, { 0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96 } };
hr = CoCreateInstance(CLSID_Webcam, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&source);

How to control master mixer volume in windows 7 using mixer api?

In windows XP, it is quite easy to control master volume of a mixer device by setting volume of destination line using mixer api.It can be easily tested by sdk sample application provided by Microsoft.But in case of windows 7 whenever I open a mixer device in my application it shows it as new volume application and I am able to control only volume of my application.Not able to control complete sound of system.Can anyone suggest me how to control complete sound of speaker which will affect sound of all running application.
How can I change speakers volume using my application in windows 7 ?
I believe that the method you're looking for is SetMasterVolumeLevelScalar.
A short example in C (sorry for the lpVtbls):
BOOL AddMasterVolumeLevelScalar(float fMasterVolumeAdd)
{
IMMDeviceEnumerator *deviceEnumerator = NULL;
IMMDevice *defaultDevice = NULL;
IAudioEndpointVolume *endpointVolume = NULL;
HRESULT hr;
float fMasterVolume;
BOOL bSuccess = FALSE;
hr = CoCreateInstance(&XIID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &XIID_IMMDeviceEnumerator, (LPVOID *)&deviceEnumerator);
if(SUCCEEDED(hr))
{
hr = deviceEnumerator->lpVtbl->GetDefaultAudioEndpoint(deviceEnumerator, eRender, eConsole, &defaultDevice);
if(SUCCEEDED(hr))
{
hr = defaultDevice->lpVtbl->Activate(defaultDevice, &XIID_IAudioEndpointVolume, CLSCTX_INPROC_SERVER, NULL, (LPVOID *)&endpointVolume);
if(SUCCEEDED(hr))
{
if(SUCCEEDED(endpointVolume->lpVtbl->GetMasterVolumeLevelScalar(endpointVolume, &fMasterVolume)))
{
fMasterVolume += fMasterVolumeAdd;
if(fMasterVolume < 0.0)
fMasterVolume = 0.0;
else if(fMasterVolume > 1.0)
fMasterVolume = 1.0;
if(SUCCEEDED(endpointVolume->lpVtbl->SetMasterVolumeLevelScalar(endpointVolume, fMasterVolume, NULL)))
bSuccess = TRUE;
}
endpointVolume->lpVtbl->Release(endpointVolume);
}
defaultDevice->lpVtbl->Release(defaultDevice);
}
deviceEnumerator->lpVtbl->Release(deviceEnumerator);
}
return bSuccess;
}
In case the GUIDs are not defined:
const static GUID XIID_IMMDeviceEnumerator = { 0xA95664D2, 0x9614, 0x4F35, { 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6 } };
const static GUID XIID_MMDeviceEnumerator = { 0xBCDE0395, 0xE52F, 0x467C, { 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E } };
const static GUID XIID_IAudioEndpointVolume = { 0x5CDF2C82, 0x841E, 0x4546, { 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A } };

SetupDiEnumDeviceInterfaces error 259 for display

I am trying to retrieve a set of display related interfaces and seem always to get the 259 error. Since I am very unexperienced with WinApi I could need some hints :)
#include <atlstr.h>
#include <SetupApi.h>
#pragma comment(lib, "setupapi.lib")
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <devguid.h>
#include <regstr.h>
const GUID GUID_CLASS_MONITOR = {0x4d36e96e, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18};
const GUID GUID_DEVINTERFACE_MONITOR = {0xe6f07b5f, 0xee97, 0x4a90, 0xb0, 0x76, 0x33, 0xf5, 0x7b, 0xf4, 0xea, 0xa7};
int main( int argc, char *argv[ ] )
{
HDEVINFO hDevInfo;
SP_DEVICE_INTERFACE_DATA ifData;
ifData.cbSize = sizeof(ifData);
DWORD dwError;
hDevInfo = SetupDiGetClassDevs(NULL /*&GUID_CLASS_MONITOR*/, NULL, NULL, DIGCF_ALLCLASSES);
dwError = GetLastError();
BOOL bRtn = SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_CLASS_MONITOR, 0, &ifData); // GUID_DEVINTERFACE_MONITOR did not work either
dwError = GetLastError();
return 0;
}
I cannot see what I am doing wrong SetupDiGetClassDevs has no errors but everything I try regarding SetupDiEnumDeviceInterfaces returns 259.
I've been trying both device setup as well the device interface GUID with no luck.
Edit: Clarification: bRtn returns 0 which means that SetupDiEnumDeviceInterfaces has failed. The 259 error means no more items but my system has two screens attached and since I am calling SetupDiGetClassDevs with no GUID I have expected to get at least my two screen items.
Edit: Added cbSize as suggested
Do you know that ifData.cbSize must be set properly before you call SetupDiEnumDeviceInterfaces?
(http://msdn.microsoft.com/en-us/library/windows/hardware/ff551015(v=vs.85).aspx)
The caller must set DeviceInterfaceData.cbSize to sizeof(SP_DEVICE_INTERFACE_DATA) before calling this function.
(http://msdn.microsoft.com/en-us/library/windows/hardware/ff552342(v=vs.85).aspx)
A SetupAPI function that takes an instance of the SP_DEVICE_INTERFACE_DATA structure as a parameter verifies whether the cbSize member of the supplied structure is equal to the size, in bytes, of the structure.
You did not show setting this value in your code.
For some reason the answer I found by try and error is not intuitive for me but it seems to work.
As I am unable to retrieve the device setup GUID but I had to add DIGCF_DEVICEINTERFACE with conjunction to device interface GUID GUID_DEVINTERFACE_MONITOR to be able to retrieve the interfaces.
Thanks for the hints as missing cbSize would have resulted in another error too :/