since Win-7 drag and drop implementation has changed, to make it work I need to enable some stuff using ChangeWindowMessageFilter.
There is a problem. ChangeWindowMessageFilter is valid since Vista, however I need solution for XP as well.
Well, you should try call it dynamically, for that you need LoadLibrary and GetProcAddress.
Sample usage
if (/*IsVista()*/)
{
typedef BOOL (WINAPI *ChangeMessageFilter)(UINT message, DWORD dwFlag);
#define MSGFLT_ADD 1
#define MSGFLT_REMOVE 2
BOOL res = FALSE;
HMODULE user32 = LoadLibrary(L"User32.dll");
if (user32 != NULL)
{
ChangeMessageFilter filter = (ChangeMessageFilter)::GetProcAddress(user32, "ChangeWindowMessageFilter");
if (filter != NULL)
{
res = filter(/*your value*/, MSGFLT_ADD);
}
::FreeLibrary(user32);
}
}
Another thing, you should better use ChangeWindowMessageFilterEx as it is enables messages receiving for only one window, not all project.
Related
I tried creating a mutant in my process that closes the process when it is created more than once with this code:
HANDLE m;
OBJECT_ATTRIBUTES attr;
attr.Length = sizeof(OBJECT_ATTRIBUTES);
UNICODE_STRING str;
RtlInitUnicodeString(&str, L"123");
attr.ObjectName = &str;
long stats;
if (!(stats = NtCreateMutant(&m, MUTANT_ALL_ACCESS, &attr, false))) {
if (0xC0000035 == stats) {
return false;
}
return true;
}
All of the functions have the correct address
When I remove the code attr.ObjectName = &str; the mutant handle is not null, but the second process does not exit since the NTSTATUS is 0
When I keep the code, NTSTATUS returns STATUS_OBJECT_PATH_SYNTAX_BAD, which I have no idea what has to do with NtCreateMutant
I want to know if it is even possible to do this using NtCreateMutex in usermode and to fix these issues or if I should just stop trying and just use CreateMutex (I dont want to use it for no reason other than I wanted to try using NtCreateMutex)
I know it's 1 year late but considering how many questions are on stack overflow, better later than never.
I`m quite surprised why #Raymond Chen made that comment, because you can use undocumented API's just fine. They are everywhere in Windows, and they hardly changed for the last decade.
They are also used in literally every Windows kernel driver possible, so they are not really "undocumented" and "unsupported".
First of all, that's not how you initialise OBJECT_ATTRIBUTES; if you want to do it that way you would do:
OBJECT_ATTRIBUTES ObjectAttributes; = { sizeof(ObjectAttributes) };
The recommended and official way is to use the InitializeObjectAttributes macro.
Second, the mutex name cannot be "123" inside the NT namespace. That's why you get STATUS_OBJECT_PATH_SYNTAX_BAD.
Third, your code is just ugly written and the usage is bad. What you want to create (from what it sounds) is a "process barrier".
I will give you a working full sample code:
BOOL CreateProcessBarrier()
{
NTSTATUS Result;
UNICODE_STRING MutantName;
OBJECT_ATTRIBUTES ObjectAttributes;
HANDLE MutantHandle;
WCHAR MutantNameNT[] = L"\\??\\40691290-71d5-45bc-b86a-e714496f4bf2";
WCHAR MutantNameWin[] = L"40691290-71d5-45bc-b86a-e714496f4bf2";
RtlInitUnicodeString(&MutantName, MutantNameNT);
InitializeObjectAttributes(&ObjectAttributes, &MutantName, 0, NULL, NULL);
// ALL OK
if (0 <= (Result = ZwCreateMutant(&MutantHandle, MUTANT_ALL_ACCESS, &ObjectAttributes, TRUE)))
{
// Banana
return TRUE;
}
// Already exists
else if (Result == STATUS_OBJECT_NAME_COLLISION || Result == STATUS_OBJECT_NAME_EXISTS)
{
// Que paso ?
return FALSE;
}
// Mutex creation failed, fallback to winapi
else
{
// Papaya
CreateMutexW(NULL, TRUE, MutantNameWin);
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
return FALSE;
}
}
return TRUE;
}
The function above has support to fallback to normal WinApi in case it fails.
Usage is simple as:
Process A:
CreateProcessBarrier();
Process B,C,D,etc:
if(!CreateProcessBarrier()) ... do whatever.
Enjoy.
I'm trying to enumerate tabs of IE from an extension and from a standalone application. For one of the MSAA nodes get_accChildCount returns 0 when called from extension, while it should return 1 according to inspect and a call from standalone application.
The problem was described previously at StackOverflow, yet it was solved via a hack that doesn't work for me. /clr and /MT are incompatible.
Also there was a topic on MSDN with the same issue. There's no single answer there.
If you run IE with administrator privileges, it works properly.
API Monitor shows several thousand calls in a minimal example, and it's unclear which of these are related. The minimal example is attached below.
What are the undocumented cases when get_accChildCount returns wrong child count?
What other method could I use to activate the tab by URL in most versions of IE?
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <atltypes.h>
#include <atlsafe.h>
#include <io.h>
#include <fcntl.h>
#include <windows.h>
#include <iostream>
#include <string>
#include <vector>
#include <boost/format.hpp>
#include <fstream>
using namespace std;
CComPtr<IAccessible> get_acc_by_hwnd(HWND hwnd) {
CComPtr<IAccessible> ret;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &ret);
if (FAILED(hr) || !ret) {
wcout << L"Accessible::Accessible invalid hwnd" << endl;
}
return ret;
}
std::vector<CComPtr<IAccessible>> get_acc_children(CComPtr<IAccessible> acc) {
std::vector<CComPtr<IAccessible>> ret;
long count;
if (FAILED(acc->get_accChildCount(&count))) return ret;
long count_obtained = 0;
if (!count) return ret;
std::vector<CComVariant> accessors(count);
if (FAILED(::AccessibleChildren(acc, 0, count, &*accessors.begin(), &count_obtained))) return ret;
accessors.resize(count_obtained);
for (auto vtChild : accessors) {
if (vtChild.vt != VT_DISPATCH) continue;
CComQIPtr<IAccessible> pChild = vtChild.pdispVal;
if (pChild) ret.push_back(pChild);
}
return ret;
}
bool is_client(CComPtr<IAccessible> acc) {
CComVariant var;
HRESULT hr = acc->get_accRole(CComVariant(CHILDID_SELF), &var);
return SUCCEEDED(hr) && var.vt == VT_I4 && var.lVal == 0xA;
}
std::wstring get_descr(CComPtr<IAccessible> acc) {
CComBSTR str;
HRESULT hr = acc->get_accDescription(CComVariant(CHILDID_SELF), &str);
return SUCCEEDED(hr) && str ? std::wstring(str) : L"";
}
int main() {
::CoInitialize(nullptr);
_setmode(_fileno(stdout), _O_U16TEXT);
// put HWND of the window that contains tab labels
// it's hardcoded to minimize quantity of API calls
HWND hwnd = reinterpret_cast<HWND>(0x002D0696);
CComPtr<IAccessible> iaccessible;
HRESULT hr = ::AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, (void**) &iaccessible);
if (FAILED(hr) || !iaccessible) {
wcout << L"AccessibleBrowser::activate_tab " L"failed to get IAccessible for IE" << endl;
return EXIT_FAILURE;
}
wstring const sentinel = L"\r\n";
for (auto child : get_acc_children(iaccessible)) if (is_client(child)) {
for (auto child1 : get_acc_children(child)) { // fails here in extension
for (auto child2 : get_acc_children(child1)) {
std::wstring descr = get_descr(child2);
auto pos = descr.find(sentinel);
if (pos == string::npos) continue;
auto tab_url = descr.substr(pos + sentinel.size());
wcout << tab_url << endl;
}
}
}
}
I poked at your program for a while without having much to show for it. Perhaps I realized too late that it was not supposed to reproduce the problem :( I can only provide some possibly helpful hints to get you to look under the right kind of rock.
yet it was solved via a hack that doesn't work for me
These programmers made a simple mistake, they forgot to call CoInitialize/Ex(). A very common oversight. Using the /clr build option works around that mistake because it is now the CLR that calls it. You can easily repro this mishap, just comment out the CoInitialize() call. Unfortunately it works for a while without any loud errors being produced, but you do get 0 for certain accobjects. You'll notice your program no longer finds the tabs.
Not so sure I can cleanly explain this, certain COM-style object models don't actually use the COM infrastructure. DirectX is the best example, we can add UIAutomation to that list. I assume it will silently fail like this when the client app's component is COM-based. Unclear if it is, DirectUIHWnd is quite undocumented.
So stop looking for that as a workaround, you did not forget to call CoInitialize() and it will be taken care of by IE before it activates your extension.
If you run IE with administrator privileges, it works properly.
That's a better rock. Many programmers run VS elevated all the time, the roles might be reversed in the case of UIA. Do keep in mind that your extension runs in a sandbox inside IE. No real idea how elevating IE affects this. One thing you cannot do from code running in the low-integrity sandbox is poke at UI components owned by a code that runs in a higher integrity mode. Google "disable IE enhanced protected mode" and follow the guideline to see what effect that has on your addin.
I want to unload some module in a process .
I use this function :
bool UnInjectDll(const TCHAR* ptszDllFile, DWORD dwProcessId)
{
if (NULL == ptszDllFile || 0 == ::_tcslen(ptszDllFile))
{
return false;
}
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
HANDLE hProcess = NULL;
HANDLE hThread = NULL;
hModuleSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessId);
if (INVALID_HANDLE_VALUE == hModuleSnap)
{
return false;
}
MODULEENTRY32 me32;
memset(&me32, 0, sizeof(MODULEENTRY32));
me32.dwSize = sizeof(MODULEENTRY32);
if(FALSE == ::Module32First(hModuleSnap, &me32))
{
::CloseHandle(hModuleSnap);
return false;
}
bool isFound = false;
do
{
isFound = (0 == ::_tcsicmp(me32.szModule, ptszDllFile) || 0 == ::_tcsicmp(me32.szExePath, ptszDllFile));
if (isFound)
{
break;
}
} while (TRUE == ::Module32Next(hModuleSnap, &me32));
::CloseHandle(hModuleSnap);
if (false == isFound)
{
return false;
}
hProcess = ::OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION, FALSE, dwProcessId);
if (NULL == hProcess)
{
return false;
}
LPTHREAD_START_ROUTINE lpThreadFun = (PTHREAD_START_ROUTINE)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "FreeLibrary");
if (NULL == lpThreadFun)
{
::CloseHandle(hProcess);
return false;
}
hThread = ::CreateRemoteThread(hProcess, NULL, 0, lpThreadFun, me32.modBaseAddr , 0, NULL);
if (NULL == hThread)
{
::CloseHandle(hProcess);
return false;
}
::WaitForSingleObject(hThread, INFINITE);
::CloseHandle(hThread);
::CloseHandle(hProcess);
return true;
}
But when I use this code it can not special module that I want to unload from project.
I also use "process detective" tool for doing this but this tool can not do this also.
Now I want a function that I can be sure will unload a special module from a process I want. for example you create a simple program that only show a messagebox , now if you see the modules of it's process , it has a module ntdll.dll and some other modules , now you can not remove ntdll.dll module or some other module from it. i want a function to force a process to remove any module from process I want.
What your are trying to do is utterly dangerous (and as of my knowledge, luckily, not possible).
Your program or library is linked against certain other DLLs. These libraries in return are referencing others as well, and so on, and so on. When your program or DLL is loaded into memory space by the loader of Windows, these "dependencies" will be loaded also and your import address tables will be patched so that your calls know where to jump when they are to be executed. All of your code will be hard-wired together as an atomic entity.
Unloading a DLL that has been statically linked in that manner (.dlls files can be linked statically also, not to be confused with static .lib files) basically forces your application to crash the second any call is made that depends on that libarary - especially the ntdll.dll which will be the root of most of all the libs you linked against. The calls will be thrown into the void. These libraries cannot be unloaded because they are in a sense part of your program.
If you however loaded a library dynamically at runtime, you are free to unload it any time you want. Since you are probably working via dynamic addresses using GetProcAddress anyway, it is up to you to make sure that your function pointers have a valid target.
You can take a hat on and off any way you desire, but you can't (and shouldn't) rip out your heart ;)
It doesn't fully answer your question though I know, but although this is just a warning that you never should do this without a very very good reason (which I don't know you really have), I am quite positive that you can't do what you are asking - but I am happy to let other people correct me here.
If you want to do something to the loaded libraries, and you are already on this destructive course, just overwrite the library or IATs in memory directly. You can go in with a crowbar, sure, but I don't think you will achive what you are looking for...
I am getting a JavaScript error: Error calling method on NPObject when calling a method in my NPAPI plugin in Chrome & Firefox on XP. Running the same code on Windows 7 with the same browsers was successful.
I have built a Scriptable plugin using the NPAPI, so far I can debug into the Invoke method of my scriptable object. But I don't believe I have any control after it's finished.
Does anyone have any ideas? Is this an issue only in Windows XP?
bool MY_ScriptableObject::Invoke(NPObject* npobj,
NPIdentifier name,
const NPVariant* args,
uint32_t argCount,
NPVariant* result)
{
bool rc = true;
char* wptr = NULL;
rc = false;
wptr = NULL;
if (name == NPN_GetStringIdentifier("getVersion"))
{
wptr = (NPUTF8*)NPN_MemAlloc(strlen("version:1.0.1") + 1); //Should be freed by browser
if (wptr != NULL)
{
rc = true;
memset(wptr,
0x00,
strlen("version:1.0.1")+1);
memcpy(wptr,
"version:1.0.1",
strlen("version:1.0.1"));
STRINGZ_TO_NPVARIANT(wptr,
*result);
}
}
return (rc);
}
Here is the HTML function that I am executing:
function Version()
{
var plugin = document.getElementById("plugin");
if (plugin == undefined)
{
alert("plugin failed");
return;
}
var text = plugin.getVersion(); //Error happens at this line
alert(text);
}
The (sarcasm)awesome(/sarcasm) thing about NPAPI in current versions of the browsers is that if anything goes wrong with the call you automatically get that error message, even if the plugin has otherwise tried to set an exception with NPN_SetException.
My first guess would be that you compiled your code targeting a later version of windows than windows XP; I'm not sure if that would produce this issue or not. I have never seen the issue you're describing, and I've got plugins running on xp, vista, and 7 with no trouble. You might also try playing with a FireBreath plugin and see if the issue occurs there or not.
I would recommend that you attach with a debugger and set some breakpoints. Start in NPN_GetValue and make sure that it's instantiating your NPObject, then set breakpoints in your NPObject's HasMethod and Invoke methods and see what is hit. Likely something in there will show you what is actually happening, or at least tell you what code is or isn't getting hit.
I'm trying to write a function to get the Windows-equivalent of HOME. My C skills are rusty, so don't mind that my example code does not compile. I'm trying to use SHGetKnownFolderPath on Windows Vista and newer, and SHGetFolderPath on Server 2003 and older. Since I expect to encounter users running Windows XP (as it is still the number one deployed version of Windows), I am going to avoid having a reference to SHGetKnownFolderPath in the symbol table (as this would lead to a binary that won't even load on XP). I know to LoadLibrary() shell32 and to GetProcAddress() from there, but my skills on doing function pointers are, well, crap, to say the least.
When I write features, and they are difficult to handle, I isolate them into an separate example file. The broken example I have so far is:
#include <windows.h>
#include <stdio.h>
// Pointerizing this Vista-and-later call for XP/2000 compat, etc.
typedef HRESULT (WINAPI* lpSHGetKnownFolderPath)(
REFKNOWNFOLDERID rfid,
DWORD dwFlags,
HANDLE hToken,
PWSTR *ppszPath
) lpSHGetKnownFolderPath;
int main(int argc, char *argv[])
{
// SHGet(Known)FolderPath() method.
HMODULE hndl_shell32;
lpSHGetKnownFolderPath pSHGetKnownFolderPath;
hndl_shell32 = LoadLibrary("shell32");
pSHGetKnownFolderPath = GetProcAddress(hndl_shell32, "SHGetKnownFolderPathW");
if(pSHGetKnownFolderPath != NULL) {
} else {
}
}
My question is this: Knowing that I'm doing this wrong, how would I go about doing this right? And an explanation as to how to do it right in the future would be appreciated. Thanks.
Here is a small application that shows how to use LoadLibrary() and GetProcAddress() with advice provided in comments:
#include <windows.h>
#include <stdio.h>
#include <shlobj.h>
/* The name of the function pointer type is
'lpSHGetKnownFolderPath', no need for
additional token after ')'. */
typedef HRESULT (WINAPI* lpSHGetKnownFolderPath)(
REFKNOWNFOLDERID rfid,
DWORD dwFlags,
HANDLE hToken,
PWSTR *ppszPath
);
int main()
{
HMODULE hndl_shell32;
lpSHGetKnownFolderPath pSHGetKnownFolderPath;
/* Always check the return value of LoadLibrary. */
hndl_shell32 = LoadLibrary("shell32");
if (NULL != hndl_shell32)
{
/* There is no 'SHGetKnownFolderPathW()'.
You need to cast return value of 'GetProcAddress()'. */
pSHGetKnownFolderPath = (lpSHGetKnownFolderPath)
GetProcAddress(hndl_shell32, "SHGetKnownFolderPath");
if(pSHGetKnownFolderPath != NULL)
{
PWSTR user_dir = 0;
if (SUCCEEDED(pSHGetKnownFolderPath(
FOLDERID_Profile,
0,
NULL,
&user_dir)))
{
/* Use 'user_dir' - remember to:
CoTaskMemFree(user_dir);
when no longer required.
*/
}
}
else
{
fprintf(stderr, "Failed to locate function: %d\n",
GetLastError());
}
/* Always match LoadLibrary with FreeLibrary.
If FreeLibrary() results in the shell32.dll
being unloaded 'pSHGetKnownFolderPath' is
no longer valid.
*/
FreeLibrary(hndl_shell32);
}
else
{
fprintf(stderr, "Failed to load shell32.dll: %d\n", GetLastError());
}
return 0;
}
This was compiled on Windows XP.
Output on Windows XP:
Failed to locate function: 127
where 127 means The specified procedure could not be found.
Output on Windows Vista:
C:\Users\admin
You can always use getenv("HOMEDRIVE") and getenv("HOMEPATH") and concatenate the results.
std::string home = std::string(getenv("HOMEDRIVE")) + getenv("HOMEPATH");
The Windows equivalent of HOME is USERPROFILE. It is an ordinary environment variable just like in Linux. You can make the following call to retrieve it:
char *profilepath = getenv("USERPROFILE");