Text Services Framework AdviseSink failed for global compartment if application runs as SYSTEM user - com

When I try to advise a ITfCompartmentEventSink for a global compartment in a process that has started as a SYSTEM user, the AdviseSink fails with E_FAIL. I tried with impersonating as normal user, but it doesn't seem to help.
And the compartment GetValue will succeed, but SetValue will also fail with E_FAIL.
However when the process is started as normal user, the AdviseSink works correctly.
The AdviseSink in following sample code also fails for SYSTEM user.
Windows-classic-samples\Samples\Win7Samples\winui\tsf\tsfcompart\monitor.cpp
So do I have to somehow set a security descriptor or initialize COM library with a particular option to make this work?
Thanks.
HRESULT CCompartmentMonitor::Initialize( const GUID *pguidCompartment,
PCOMPARTMENTMONITORPROC pCallback,
LPARAM lParam)
{
if(!IsEqualGUID(m_guidCompartment, GUID_NULL))
{
//Initialize() has already been called
return E_UNEXPECTED;
}
m_guidCompartment = *pguidCompartment;
m_pCallback = pCallback;
m_lParam = lParam;
HRESULT hr;
ITfThreadMgr *pThreadMgr;
//create a thread manager object
hr = CoCreateInstance(CLSID_TF_ThreadMgr,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITfThreadMgr,
(void**)&pThreadMgr);
if(SUCCEEDED(hr))
{
ITfCompartmentMgr *pCompMgr;
//get the global compartment manager
hr = pThreadMgr->GetGlobalCompartment(&pCompMgr);
if(SUCCEEDED(hr))
{
//get the Speech UI compartment
hr = pCompMgr->GetCompartment(m_guidCompartment,
&m_pCompartment);
if(SUCCEEDED(hr))
{
ITfSource *pSource;
//install the advise sink
hr = m_pCompartment->QueryInterface(IID_ITfSource,
(LPVOID*)&pSource);
if(SUCCEEDED(hr))
{
hr = pSource->AdviseSink(IID_ITfCompartmentEventSink,
(ITfCompartmentEventSink*)this,
&m_dwCookie);
// AdviseSink fails with E_FAIL
}
//if something went wrong, release the member interface
if(FAILED(hr))
{
m_pCompartment->Release();
m_pCompartment = NULL;
}
}
//release the compartment manager
pCompMgr->Release();
}
//release the thread manager
pThreadMgr->Release();
}
return hr;
}

Related

DLL Code injection to third party process using QueueUserAPC

I want to inject my dll in to 64 bit application and I have tried the logic explained in the given link using QueueUserAPC. I am getting success message for every API but when I see in ProcessExplorer I am not able to see my dll in the process.
Below is my code :
bool FindProcess(PCWSTR exeName, DWORD& pid, vector<DWORD>& tids) {
auto hSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
return false;
pid = 0;
PROCESSENTRY32 pe = { sizeof(pe) };
if (::Process32First(hSnapshot, &pe)) {
do {
if (_wcsicmp(pe.szExeFile, exeName) == 0) {
pid = pe.th32ProcessID;
THREADENTRY32 te = { sizeof(te) };
if (::Thread32First(hSnapshot, &te)) {
do {
if (te.th32OwnerProcessID == pid) {
tids.push_back(te.th32ThreadID);
}
} while (::Thread32Next(hSnapshot, &te));
}
break;
}
} while (::Process32Next(hSnapshot, &pe));
}
::CloseHandle(hSnapshot);
return pid > 0 && !tids.empty();}
void main(){
DWORD pid;
vector<DWORD> tids;
if (FindProcess(L"DataGrid.exe", pid, tids))
{
printf("OpenProcess\n");
HANDLE hProcess = ::OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid);
printf("VirtualAllocEx\n");
auto p = ::VirtualAllocEx(hProcess, nullptr, 1 << 12, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
wchar_t buffer[] = L"C:\\Users\\sbhuma\\Documents\\Visual Studio 2015\\Projects\\GalaxyHook\\Debug\\GalaxyHook.dll";
printf("WriteProcessMemory\n");
::WriteProcessMemory(hProcess, p, buffer, sizeof(buffer), nullptr);
for (const auto& tid : tids)
{
printf("OpenThread\n");
HANDLE hThread = ::OpenThread(THREAD_SET_CONTEXT, FALSE, tid);
if (hThread)
{
printf("GetProcAddress\n");
DWORD word = ::QueueUserAPC((PAPCFUNC)::GetProcAddress(GetModuleHandle(L"kernel32"), "LoadLibraryW"), hThread, (ULONG_PTR)p);
if (word)
{
printf("insdie if\n");
}
printf("End of IF\n");
}
}
printf("VirtualFreeEx\n");
::VirtualFreeEx(hProcess, p, 0, MEM_RELEASE | MEM_DECOMMIT);
}}
Any help related to inject the dll in to 64 bit application is helpful as I am new to this topic.
Regards,
Sowmya.
First of all, ensure you’re building your injector app as 64 bit.
One possible reason is you’re releasing the buffer too early. QueueUserAPC doesn’t wait; it enqueues the call and returns immediately. Can be your injector process ends running that for loop, calls VirtualFreeEx, then your target process receives the APC, tries to load your DLL but the name buffer is already released by then, so LoadLibrary fails. To verify, comment out the call to VirtualFreeEx. If your DLL will load OK, one way to fix the memory leak is use a named event, CreateEvent in injector app before any calls to QueueUserAPC(), OpenEvent, SetEvent and CloseHandle in DllMain(DLL_PROCESS_ATTACH) of the DLL you’re injecting, WaitForSingleObject in injector app before VirtualFreeEx, I recommend using a timeout for the wait, CloseHandle at the end. As a side effect, your injector app will be able to find out, and report somewhere, whether the injection was successful.
Another possible reason is your target app never enters alertable state. Not all apps use APC, there’re multiple alternative methods to implement asynchronous stuff in Windows. So, not all apps ever call these SleepEx / WaitForMultipleObjectsEx functions. Such app will never receive that APC. If that’s the case, you should use another method of DLL injection. DataGrid.exe name hints your target app is probably a GUI app. You can EnumWindows or FindWindow to find its top-level window, GetWindowThreadProcessId to get thread ID who owns that window, SetWindowsHookEx to inject your DLL into the target process.

windows 8 set as desktop background

I'm writing a small program to change desktop background with one or two mouse clicks..
I know that I can right click on any Image file and set it as Desktop Background..
And exactly there is where the problem starts. I cant find the proper entry in any dll which would have the entry Set As Desktop Background or even New Desktop Background.
I know how I can create those in registry, but I don't want to edit registry for this, rather I would like to have it set right in my Tiny Program so with two clicks I would get control over all image files on my Computer to display them as Desktop Background. and this from any folder or even from any connected drive, without to have to return to Personalization menu.
If anyone of you knows where I can find the entry's of above mentioned Context menu Strings, so I would be very thankful.
This is just for personal use, neither to sell or give away..
Thank you Chris
P.S. Please forgive me my bad English, I'm from a non English speaking European country.
If you look at, for example, HKEY_CLASSES_ROOT\SystemFileAssociations.jpg\Shell\setdesktopwallpaper\Command
You'll notice that it has the DelegateExecute member set. This means that windows will attempt to use the IExecuteCommand interface in the specified DLL. Reading up on what that does on MSDN, and attempting to emulate explorer, I came up with this, which works.
I'm not sure why that Sleep() is needed though, I'd love if anyone could elaborate on that.
void SetWallpaper(LPCWSTR path)
{
const GUID CLSID_SetWallpaper = { 0xFF609CC7, 0xD34D, 0x4049, { 0xA1, 0xAA, 0x22, 0x93, 0x51, 0x7F, 0xFC, 0xC6 } };
HRESULT hr;
IExecuteCommand *executeCommand = nullptr;
IObjectWithSelection *objectWithSelection = nullptr;
IShellItemArray *shellItemArray = nullptr;
IShellFolder *rootFolder = nullptr;
LPITEMIDLIST idlist = nullptr;
// Initalize COM, probably shouldn't be done in this function
hr = CoInitialize(nullptr);
if (SUCCEEDED(hr))
{
// Get the IExecuteCommand interface of the DLL
hr = CoCreateInstance(CLSID_SetWallpaper, nullptr, CLSCTX_INPROC_SERVER, IID_IExecuteCommand, reinterpret_cast<LPVOID*>(&executeCommand));
// Get the IObjectWithSelection interface
if (SUCCEEDED(hr))
{
hr = executeCommand->QueryInterface(IID_IObjectWithSelection, reinterpret_cast<LPVOID*>(&objectWithSelection));
}
//
if (SUCCEEDED(hr))
{
hr = SHGetDesktopFolder(&rootFolder);
}
if (SUCCEEDED(hr))
{
hr = rootFolder->ParseDisplayName(nullptr, nullptr, (LPWSTR)path, nullptr, &idlist, NULL);
}
if (SUCCEEDED(hr))
{
hr = SHCreateShellItemArrayFromIDLists(1, (LPCITEMIDLIST*)&idlist, &shellItemArray);
}
if (SUCCEEDED(hr))
{
hr = objectWithSelection->SetSelection(shellItemArray);
}
if (SUCCEEDED(hr))
{
hr = executeCommand->Execute();
}
// There is probably some event, or something to wait for here, but we
// need to wait and relinquish control of the CPU, or the wallpaper won't
// change.
Sleep(2000);
// Release interfaces and memory
if (idlist)
{
CoTaskMemFree(idlist);
}
if (executeCommand)
{
executeCommand->Release();
}
if (objectWithSelection)
{
objectWithSelection->Release();
}
if (shellItemArray)
{
shellItemArray->Release();
}
if (rootFolder)
{
rootFolder->Release();
}
CoUninitialize();
}
}
Edit: After doing some more research on this, for my own sake, I realized that stobject.dll actually just uses the IDesktopWallpaper interface; which is part of CLSID_DesktopWallpaper
http://msdn.microsoft.com/en-us/library/windows/desktop/hh706946(v=vs.85).aspx

hand tracking not working after a reload of openni dynamic library

Our project is (http://www.play4health.com/p4h_eng/) using Ogre 3D
over Ubuntu 11.04. Except for core services all is based in a plugin architecture taking advantage of Ogre 3d plugin facilities.
In our plugin architecture plugins can be:
Videogames
Interaction methods
Users configure their session creating tuples (videogame, interaction
method). The flow is a session is:
* User load his session.
* User click of one of the tuples for the session and play to
videogame with a specific interaction method.
* Repeat it until end all activities of the session.
Plugin are loaded/unloaded dynamically by demand.
One of this interaction methods is hand tracking using openni. What is
the problem?
* Fist time that openni plugin is loading all work perfectly.
* Next time that plugin openni has to be loaded system is able to
detect gestures but not do hand tracking. Note that all plugin are
executed in the same process. Right now only solution is to reboot
platform.
This is the code for init and release OpenNI in our plugin
bool IPKinectPlugin::onInitialise()
{
mHandPointer.mId = "KinectHandPointer";
mHandPointer.mHasAbsolute = true;
mHandPointer.mHasRelative = false;
XnStatus nRetVal = XN_STATUS_OK;
nRetVal = gContext.InitFromXmlFile(String(this->getPluginInfo()-
>getResPath() + "SamplesConfig.xml").c_str());
CHECK_RC(nRetVal, bContext, "InitFromXml");
#if SHOW_DEPTH
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_DEPTH,gDepthGenerator);
bDepthGenerator = (nRetVal != XN_STATUS_OK);
if (bDepthGenerator)
{
nRetVal = gDepthGenerator.Create(gContext);
CHECK_RC(nRetVal, bDepthGenerator, "Find Depth generator");
}
#endif
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_USER, gUserGenerator);
bUserGenerator = (nRetVal != XN_STATUS_OK);
if (/*bUserGenerator*/false)
{
nRetVal = gUserGenerator.Create(gContext);
CHECK_RC(nRetVal, bUserGenerator, "Find user generator");
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_GESTURE, gGestureGenerator);
bGestureGenerator = (nRetVal != XN_STATUS_OK);
if (bGestureGenerator)
{
nRetVal = gGestureGenerator.Create(gContext);
CHECK_RC(nRetVal, bGestureGenerator, "Find gesture generator");
XnCallbackHandle hGestureCallbacks;
gGestureGenerator.RegisterGestureCallbacks(gestureRecognized, gestureProcess, 0,
hGestureCallbacks);
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_HANDS,gHandsGenerator);
bHandsGenerator = (nRetVal != XN_STATUS_OK);
if (bHandsGenerator)
{
nRetVal = gHandsGenerator.Create(gContext);
CHECK_RC(nRetVal, bHandsGenerator, "Find hands generator");
XnCallbackHandle hHandsCallbacks;
gHandsGenerator.RegisterHandCallbacks(handsNew, handsMove,handsLost, 0, hHandsCallbacks);
}
nRetVal = gContext.FindExistingNode(XN_NODE_TYPE_DEVICE, gDevice);
bDevice = (nRetVal != XN_STATUS_OK);
gContext.RegisterToErrorStateChange(onErrorStateChanged, NULL, hDummyCallbackHandle);
//Preparo la textura para la webcam
if (bGenerateRGBTexture)
mWebcamTexture = KinectTools::createDepthTexture("KinectWebCamTexture", sPluginName);
return true;
}
//-----------------------------------------------------------------------------
bool IPKinectPlugin::onShutdown()
{
if (bContext)
{
if (bHandsGenerator)
{
gHandsGenerator.StopTrackingAll();
}
if (bGestureGenerator)
{
gGestureGenerator.RemoveGesture(GESTURE_TO_USE);
gGestureGenerator.RemoveGesture(GESTURE_TO_START);
}
gContext.StopGeneratingAll();
gContext.Shutdown();
}
return true;
}
Any idea about this issue? Any wrong with this code?
Maybe you already found a solution in the meantime...
I normally work with the Java Wrapper, but what I see as difference to my code is that I call contect.startGeneratingAll() after creating the generators (Depth, Hands and so on). I had also problems when I did this multiple times at start up. Another difference is that I use a context.release at shutdown.
My procedure is normally:
Init config (License, Nodes, settings)
Create generators
Start Generating All
Run your code ...
Stop Generating ALL
Context release
From OpenNI Documentation
XN_C_API void XN_C_DECL xnShutdown ( XnContext * pContext )
Shuts down an OpenNI context, destroying all its nodes. Do not call
any function of this context or any correlated node after calling this
method. NOTE: this function destroys the context and all the nodes it
holds and so should be used very carefully. Normally you should just
call xnContextRelease()

com : use an unregistered dll

I have hooked the cocreateinstance() function.
When it's called with a specific CLSID, I want to use my dll instead the dll system.
So here is my code :
HOOK_CoCreateInstance(rclsid,pUnkOuter,dwClsContext,riid,*ppv){
...
if(myCLSID){
module = LoadLibrary(mydll);
dllGetClassObject = (FUNC)GetProcAddress(module,"DllGetClassObject");
hr = dllGetClassObject(rclsid, IID_IClassFactory, &pClassFactory);
hr = pClassFactory->CreateInstance(NULL,IID_IUnknown, (void**)&data_source);
return hr;
}
else{
hr = CoCreateInstanceReal(rclsid,pUnkOuter,dwClsContext,riid,ppv);
return hr;
}
}
But it's not working.
I think the problem is in pClassFactory::CreateInstance(), with the second parameter :
I don't know how to retrieve automatically the REFIID of my dll.
And if I use riid it's not working either.
So if anyone has an idea,
Thanks !
If you want to follow proper COM conventions, you'll need to handle the CoCreateInstance parameters correct (as documented here).
The __in REFIID riid parameter is the GUID of the interface you want to use, not the DLL itself. The CLSID parameter is the class of the object, which you should know ahead of time. Because you want to return the expected interface, you really only need to know the CLSID of your new implementation (coclass) and call using that.
A simpler, but not quite COM-spec, method would be to export a factory from your DLL:
__declspec(dllexport) MyObject * CreateObject()
{
return new MyObject();
}
and call that from your wrapper:
HOOK_CoCreateInstance(rclsid,pUnkOuter,dwClsContext,riid,*ppv)
{
if(myCLSID)
{
module = LoadLibrary(mydll);
dllCreate = (FUNC)GetProcAddress(module,"CreateObject");
*ppv = dllCreate();
return S_OK;
} else {
hr = CoCreateInstanceReal(rclsid,pUnkOuter,dwClsContext,riid,ppv);
return hr;
}
}

IAudioSessionManager2 notifications not sent

I'm trying to monitor new audio sessions via Windows 7's IAudioSessionManager2 COM interface (coupled with IAudioSessionNotification). Currently, IAudioSessionNotification::OnSessionCreated() is never called and I've run out of ideas as to why.
Code registering custom IAudioSessionNotification:
#define SAFE_RELEASE(comObj) \
if(comObj != NULL) \
{ (comObj)->Release(); comObj = NULL; }
BOOL success = false;
HRESULT res;
IClassFactory* pFactory;
IMMDevice* pDevice;
IMMDeviceEnumerator* pEnumerator;
SESSION_LISTENER = NULL;
SESSION = NULL;
res = CoInitialize(NULL);
if(res != S_OK && res != S_FALSE)
return false;
res = CoGetClassObject(CLSID_CustomAudioFactory, CLSCTX_ALL, NULL, __uuidof(IClassFactory), (void**)&pFactory);
if(res != S_OK) goto Exit;
res = pFactory->CreateInstance(NULL, CLSID_CustomAudioNotifications, (void**)&SESSION_LISTENER);
if(res != S_OK) goto Exit;
res = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&pEnumerator);
if(res != S_OK) goto Exit;
res = pEnumerator->GetDefaultAudioEndpoint(eRender, eMultimedia, &pDevice);
if(res != S_OK) goto Exit;
res = pDevice->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**)&SESSION);
if(res != S_OK) goto Exit;
res = SESSION->RegisterSessionNotification(SESSION_LISTENER);
if(res != S_OK) goto Exit;
success = true;
Exit:
SAFE_RELEASE(pFactory);
SAFE_RELEASE(pEnumerator);
SAFE_RELEASE(pDevice);
if(!success)
{
SAFE_RELEASE(SESSION_LISTENER);
SAFE_RELEASE(SESSION);
}
CustomAudioNotifications declaration:
class CustomAudioNotifications : public IAudioSessionNotification
{
public:
//Constructors
CustomAudioNotifications() { InterlockedIncrement(&g_notifyCount); m_listener = NULL; }
~CustomAudioNotifications() { InterlockedDecrement(&g_notifyCount); SAFE_RELEASE(m_listener); }
//IUnknown interface
HRESULT __stdcall QueryInterface(
REFIID riid ,
void **ppObj);
ULONG __stdcall AddRef();
ULONG __stdcall Release();
//Notification
HRESULT __stdcall OnSessionCreated(IAudioSessionControl *NewSession);
private:
LONG m_nRefCount;
};
OnSessionCreated just posts a message to a window whenever a session is created for the time being; which never happens. Just in case my assumptions are totally off base, I'm expecting a notification whenever an application that has yet to play audio starts to do so; so launching VLC with a video file should immediately result in a notice, while visiting Pandora via a web browser would also trigger such a notice.
Debugging shows all returned values are S_OK.
My COM experience is pretty limitted, so pointing out general "WTFs?" would also be appreciated.
That's a TON more work than you need to do.
You just need to write a class that derives from IAudioSessionNotifications - you don't need to actually write a whole COM object and register it.
You should also use the eConsole role instead of the eMultimedia role. It doesn't effectively matter (if you have only one audio device) but it's more correct.
The destructor for the CustomAudioNotification class should be private - that way you prevent accidental destruction. So I'd write:
CustomAudioNotification
*customNotification = new CustomAudioNotification();
SESSION->RegisterSessionNotification(customNotification);
I'm also assuming that you've initialized COM before your code snippet.
UPDATED: Kevin sent me his application and there are a couple of other issues with his application that are more fundamental (I'm working to get the documentation for the APIs improve to prevent any confusion in the future)
The first is that his application hasn't retrieved the current list of sessions. This is one of the really subtle things about the session enumeration APIs. In order to prevent a race condition that can occur when a session notification arrives while the application using the session APIs is starting up, the session enumeration API discards new session notifications until the application has first retrieved the list of existing sessions.
The expected usage pattern is:
Application activates a session manager2.
Application registers for session notifications.
Application retrieves the current list of sessions for the endpoint and stores the session control objects into a list (don't forget to addref the session).
When a new session is created, the application takes a reference to the newly created session control object and inserts it into the list if it's not already present. Note that the session control object passed into the notification will be destroyed when the session notification returns - if you call GetSessionEnumerator at this point it will probably NOT hold the newly created session (it might, it all depends on timing).
The application manages the lifetime of the session based on its own criteria - as long as the application has a reference to the session control the session control object will be valid. There is no expiration mechanism for audio session control objects.
In addition, the session APIs require that the MTA be initialized - this is unfortunate but because we create COM objects (which implement IAudioSessionControl) on a worker thread the API requires that the MTA be created before the notification is received.