Qt - get all opened windows title - windows

how can i check whether a specific window is open or not. I only got part of the window's name. i thinking of using EnumWindows() in QT console app but i get a few errors stating "main.obj:-1: error: unresolved external symbol imp__GetWindowTextW#12 referenced in function "int __stdcall EnumWindowsProc(struct HWND *,long)" (?EnumWindowsProc##YGHPAUHWND__##J#Z)"
Below is my sample code
BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam) {
char buff[255];
if (IsWindowVisible(hWnd)) {
GetWindowText(hWnd, (LPWSTR) buff, 254);
}
return TRUE;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
EnumWindows(EnumWindowsProc, 0);
return 0;
}

That's a linker error rather than a compile error.
You have correctly included windows.h but you also need to add the import libraries to your linker options. All three Win32 functions in your sample code require you to link user32.lib.

EnumWindowsProc is not from Qt, it's a windows API function, you need to include windows.h
I did not use Qt, and the code can pass complie, but the output seems NOT right. Anyway, here's my code
#include <conio.h>
#include <iostream>
#include <windows.h>
using namespace std;
char buff[255];
BOOL CALLBACK EnumWindowsProc(HWND hWnd, long lParam)
{
if (IsWindowVisible(hWnd))
{
GetWindowText(hWnd, (LPWSTR) buff, 254);
}
return TRUE;
}
int main()
{
EnumWindows(EnumWindowsProc, 0);
for(int i = 0; i != 254; ++i)
cout << buff[i];
getch();
return 0;
}

You can use:
Application.OpenForms["FormName"]
To check if the form is open or not.

Related

Listening to messages in another Windows app

I'd like my program to listen to messages in another Windows app.
I am aware of SetWindowsHook, but am concerned about this line:
If the dwThreadId parameter is zero or specifies the identifier of a
thread created by a different process, the lpfn parameter must point
to a hook procedure in a DLL.
I don't know which hook procedures are in Windows DLLs, so am at a loss.
(I'm using Python with ctypes to use the WinAPI.)
Question: How can I get my program to listen for messages in another Windows process?
You need to create a DLL and add hook functions to the DLL.
I will use the following code in C++ to create the DLL:
#include <windows.h>
#include <iostream>
HINSTANCE hThisDLL;
HHOOK hMsgHook;
BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
hThisDLL = hinstDLL;
return TRUE;
}
LRESULT CALLBACK GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//do what you want to do
return CallNextHookEx(NULL, nCode, wParam, lParam);
}
extern "C" __declspec(dllexport) BOOL InstallHook()
{
if (!hMsgHook)
hMsgHook = SetWindowsHookEx(WH_GETMESSAGE, &GetMsgProc, hThisDLL, 0);
return (hMsgHook != NULL);
}
extern "C" __declspec(dllexport) VOID UninstallHook()
{
if (hMsgHook)
{
UnhookWindowsHookEx(hMsgHook);
hMsgHook = NULL;
}
}
After generating the .dll file, you can load the dynamic library through the LoadLibrary function, and use the GetProcAddress function to get the function address in the dynamic library. Then call the hook function.
Here is the code with C++:
#include <iostream>
#include <windows.h>
typedef BOOL(WINAPI* LPInstallHook)();
typedef VOID(WINAPI* LPUninstallHook)();
int main()
{
HMODULE dll_handle;
LPInstallHook installProc;
LPUninstallHook uninstallProc;
HHOOK process_hook;
dll_handle = LoadLibrary(L"test.dll");
if (dll_handle)
{
installProc = (LPInstallHook)GetProcAddress(dll_handle, "InstallHook");
uninstallProc = (LPUninstallHook)GetProcAddress(dll_handle, "UninstallHook");
}
MSG msg;
installProc();
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
uninstallProc();
if(dll_handle) FreeLibrary(dll_handle);
}
This is part of the code implemented in python, you can refer to it:
import ctypes
import os
from ctypes import *
user32 = ctypes.windll.user32
kernel32 = ctypes.windll.kernel32
if __name__ == '__main__':
dllpath = os.path.join(path,"test.dll")
pDll = ctypes.WinDLL(dllpath)
pDll.InstallHook()
msg = ctypes.wintypes.MSG()
while user32.GetMessageW(ctypes.byref(msg), 0, 0, 0) != 0:
user32.TranslateMessage(msg)
user32.DispatchMessageW(msg)
Of course, according to the documentation, you can set dwThreadId as the identifier of other threads. You can refer to the similar thread.

calling native(Nt) API in user mode

I am trying to call native API(NtOpenKey) in user mode. I am seeing linker problem. I am really confused, what is missing here. How can I achieve doing this? I am attaching my code here. ntdll.lib is added to the project(link)
Error 58 error LNK2001: unresolved external symbol "__declspec(dllimport) long __cdecl NtOpenKey(void * *,unsigned long,struct _OBJECT_ATTRIBUTES *)" (__imp_?NtOpenKey##YAJPEAPEAXKPEAU_OBJECT_ATTRIBUTES###Z) C:\Users\santhi.ragipati\documents\visual studio 2013\Projects\NtRegistry\NtRegistry\NtRegistry.obj NtRegistry
Thanks
Santhi
`// NtRegistry.cpp : Defines the entry point for the console application.
//
#include <tchar.h>
#include <Windows.h>
#include <Winternl.h>
#include <ntstatus.h>
NTSYSAPI NTSTATUS NTAPI NtOpenKey(
_Out_ PHANDLE KeyHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes
);
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE handleRegKey = NULL;
for (int n = 0; n < 1; n++)
{
NTSTATUS status = NULL;
UNICODE_STRING RegistryKeyName;
OBJECT_ATTRIBUTES ObjectAttributes;
RtlInitUnicodeString(&RegistryKeyName, L"\\Registry\\Machine\\Software\\MyCompany\\MyApp");
InitializeObjectAttributes(&ObjectAttributes,
&RegistryKeyName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, // handle
NULL);
status = NtOpenKey(&handleRegKey, (ACCESS_MASK)KEY_READ, &ObjectAttributes);
if (NT_SUCCESS(status) == FALSE)
{
break;
}
} // Get the Frame location from the registry key.
// All done with the registry.
if (NULL != handleRegKey)
{
NtClose(handleRegKey);
}
return 0;
}
`
This was the giveaway:
NtOpenKey##YAJPEAPEAXKPEAU_OBJECT_ATTRIBUTES###Z
That's typical of C++ name mangling; since functions can be overloaded, but the function name used when exporting and importing must be unique, the name is modified to include a description of the argument list.
Adding extern "c" to the declaration will resolve the problem.
Incidentally, you probably don't want to set the OBJ_KERNEL_HANDLE flag, since it asks for a handle that you won't be able to use. I'm guessing Windows will ignore it, and give you a user-mode handle anyway, but better safe than sorry.

The keyboad hook dll can't work well

The code of keyhook.cpp in dll:
// KeyHook.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "stdio.h"
#include "Windows.h"
#pragma comment(linker, "/SECTION:.SHARED,RWS")
#pragma data_seg(".SHARED")
#define DEF_PROCESS_NAME "notepad.exe"
HINSTANCE g_hInstance = NULL;
HHOOK g_hHook = NULL;
HWND g_hWnd = NULL;
#pragma data_seg()
BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
printf("main function in dll\n");
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hInstance = hModule;
printf("max=%d\n", MAX_PATH);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
//OutputDebugString("what the hell\n");
char szPath[MAX_PATH] = { 0, };
char *p = NULL;
//printf("the callback function");
int shift = nCode;
if (shift = 0)
{
if (!(lParam & 0x80000000))
{
GetModuleFileNameA(NULL, szPath, MAX_PATH);
p = strrchr(szPath, '\\');
//printf("szPath=%s\n", szPath);
OutputDebugString("what the hell\n");
if (!_stricmp(p + 1, DEF_PROCESS_NAME))
return 1;
}
}
return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
#ifdef __cplusplus
extern "C" {
#endif // DEBUG
__declspec(dllexport) void HookStart()
{
printf("hookstart function\n");
g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);
if (g_hHook == NULL)
printf("failed to install the keyboard hook");
else
{
printf("Succeed in installing the keyboard hook");
}
}
__declspec(dllexport) void HookStop()
{
if (g_hHook)
{
UnhookWindowsHookEx(g_hHook);
g_hHook = NULL;
}
printf("hookstop function\n");
}
#ifdef __cplusplus
}
#endif // DEBUG
The calling application code:
// hkeybi.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include<stdio.h>
#include<conio.h>
#include<Windows.h>
#define DEF_DLL_NAME "KeyHook.dll"
#define DEF_HOOKSTART "HookStart"
#define DEF_HOOKSTOP "HookStop"
typedef void(*PFN_HOOKSTART)();
typedef void(*PFN_HOOKSTOP)();
int main()
{
int ch = -1;
HMODULE hDll = NULL;
PFN_HOOKSTART HookStart = NULL;
PFN_HOOKSTOP HookStop = NULL;
hDll = LoadLibraryA(DEF_DLL_NAME);
HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);
HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);
if ((HookStart != NULL) && (HookStop != NULL))
printf("hello start\n");
HookStart();
printf("press q to exit!\n");
while (_getch() != 'q');
HookStop();
FreeLibrary(hDll);
return 0;
}
When I run the app,after I input several words,it will go down. I spent long time in solving the problem.
There are several problems in your KeyboardProc function. The first one being that your shift variable is assigned instead of tested:
if (shift = 0)
The variable is assigned 0, the condition is therefore always false. Effectively, the only code executed after the test is the return CallNextHookEx(...). If the condition would be true, you may run into problems because the GetModuleFileNameA result is not tested. In case of an error, the following strrchr will likely fail and the p pointer will be NULL. This will result in a crash at the _stricmp. And why do you specifically use the ANSI version of GetModuleFileName, are you sure you're not using Unicode? Finally, returning the hook proc without calling CallNextHookEx is a bad idea. Here's what the documentation says:
If code is greater than or equal to zero, and the hook procedure did
not process the message, it is highly recommended that you call
CallNextHookEx and return the value it returns

How to get the name of a console in Windows?

Is possible to get the name of a console in Windows? Just like is done by the C function ttyname in Unix systems
You can use the WinAPI GetConsoleTitle function to retrieve it.
You might find links to all of the console functions useful.
You didn't specify a language, so here's the one in C++ from MSDN
#include <windows.h>
#include <tchar.h>
#include <conio.h>
#include <strsafe.h>
int main( void )
{
TCHAR szOldTitle[MAX_PATH];
TCHAR szNewTitle[MAX_PATH];
// Save current console title.
if( GetConsoleTitle(szOldTitle, MAX_PATH) )
{
// Build new console title string.
StringCchPrintf(szNewTitle, MAX_PATH, TEXT("TEST: %s"), szOldTitle);
// Set console title to new title
if( !SetConsoleTitle(szNewTitle) )
{
_tprintf(TEXT("SetConsoleTitle failed (%d)\n"), GetLastError());
return 1;
}
else
{
_tprintf(TEXT("SetConsoleTitle succeeded.\n"));
}
}
return 0;
}

SetWindowsHookEx, CBTProc and g++3.4.5 (mingw)

I'm currently working on an application that needs to add a menu
to each application's system menu. I can accomplish that for the existing
windows with the EnumWindows function.
For the new windows (applications starting up after mine)
I'm trying to do this with windows hooks. More specifically with CBTProc.
This is where I'm stuck.
I've stripped about everything possible in the app,
but I've got the impression the procedure in my dll just doesn't
get called at all.
Here's the code for the dll:
#include <string>
using std::string;
#include <fstream>
using std::ofstream;
#include <windows.h>
// ---------------------------------------------------
extern "C"
{
void log(const string & msg)
{
ofstream out("out.log", std::ios_base::app);
out << msg;
out.flush();
out.close();
}
// ---------------------------------------------------
LRESULT CALLBACK CBTProc(int nCode, WPARAM wParam, LPARAM lParam)
{
log("CBTProc");
return CallNextHookEx(0, nCode, wParam, lParam);
}
// ---------------------------------------------------
}
I compile this with g++ 3.4.5 on a windows xp sp3 32bit machine:
g++ -shared -otest.dll test_dll.cpp
And here's the code for the application
#include <iostream>
using std::cout;
using std::cin;
using std::cerr;
using std::endl;
#include <string>
using std::string;
#include <windows.h>
typedef void (*func)();
void run()
{
cout << "press enter to exit" << endl;
cin.get();
}
void * loadProc(HMODULE mod, const char * procname)
{
void * retval = (void *)GetProcAddress(mod, procname);
if (retval == NULL)
cerr << "GetProcAddress(" << procname << ") failed" << endl;
return retval;
}
int main(int argc, char ** argv)
{
HMODULE dll = LoadLibrary("test.dll");
if (dll == NULL)
{
cerr << "LoadLibrary failed" << endl;
return 1;
}
HOOKPROC proc = (HOOKPROC)loadProc(dll, "CBTProc#12");
if (!proc)
return 1;
HHOOK callwnd = SetWindowsHookEx(WH_CBT, proc, dll, 0);
if (callwnd == NULL)
{
cerr << "SetWindowsHookEx failed for CBTProc" << endl;
return 1;
}
run();
UnhookWindowsHookEx(callwnd);
return 0;
}
I compile this with the same setup:
g++ -otest.exe test.cpp
When I run, I get no errors, but when I start up new applications I get nothing
in my logfile.
Any ideas?
gr,
ldx
Edit: spelling errors
I'd suggest you to check the following:
ensure that your DLL has an export
(can be checked with dumpbin tool). I
don't know about g++, but in MSVC it
is necessary to either use
__declspec(dllexport) or explicitly state exports in DEF file.
ensure that your host application
uses the correct name of the
exported function (the same as
"dumpbin /EXPORTS test.dll"
displays)
keep in mind that you are are using relative file name out.log - when DLL gets loaded to other processes it would write relatively to the host process' current directory. For testing purposes it would be better to use OutputDebugString API and inspect results with DbgView tool.
Chances are that your solution works already.
PS: it's not generally a good idea to use STL in an injected DLL. Make sure you are aware of the risks.

Resources