SendMessage to 64bit application is not working - c++

I use the following function to send message to application. It seems to work find for a 32bit application but doesn't work for a 64bit application (the 64bit application does not seem to get any message). What is wrong and how can I fix it? Thank you.
void MyTest::SendCmd(HWND hwnd, QString cmd)
{
COPYDATASTRUCT data;
data.dwData = FIXHEADER;
data.cbData = cmd.size()+1;
data.lpData = cmd.toLocal8Bit().data();
LPARAM lpdwResult;
LRESULT err = SendMessageTimeout(hwnd, WM_COPYDATA, 0, (LPARAM)&data, SMTO_ABORTIFHUNG, 2000, &lpdwResult);
}
//FIXHEADER is a fixed hex value that the application checks against to make sure the message is sent intentional for it.

You need to compile your application in 64-bit mode otherwise this cannot work and 64-bit handles are truncated making them invalid.
Some reading for you:
https://learn.microsoft.com/en-us/windows/desktop/winauto/32-bit-and-64-bit-interoperability

Related

GlobalSize function used on Clipboard Data cause error

The first thing I want to say is my English is pretty bad so if my description become a chunk of nonsense text please comment so I can try to clarify my question.
The situation
I'm trying to access clipboard and store all of it's data from all formats possible. I listen to WM_CLIPBOARDUPDATE message then loop through all the format available, get the data for each of the format, get the size then allocate a new memory for them. My googling tell me to use the GlobalSize() function to do that. There the problem arise.
The environment
I am developing a Win32 desktop application using C++ on Visual C++ 2017 version 4.7.02556. I am using Windows 10 64 bits if that matter.
Reproducing the error
Here is my function used to process Windows messages, I remove other message like WM_CREATE or WM_DESTROY because they don't relate to the problem. The consoleOutput() function is used for debugging and they works just fine.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CLIPBOARDUPDATE: {
try {
if (OpenClipboard(hWnd)){
UINT uFormat = EnumClipboardFormats(0); // Get the first clipboard format available
HANDLE hContent;
while (uFormat) { //Iterate through all formats
hContent = GetClipboardData(uFormat); // Get the clipboard data of that format
if (hContent) {
SIZE_T size = GlobalSize(hContent); // Get the size of the data I just got
//ERROR
}
uFormat = EnumClipboardFormats(uFormat); // Get the next format
}
}
CloseClipboard();
}
catch (int error) {
CloseClipboard(); // Attempt to close clipboard if thing went wrong
consoleOutput(GetLastError());
throw;
}
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
The code works fine with everything I tried to copy from text to some random files/directories. But my program gave me an error when I tried to copy a image, for example:
Open an image using MS Paint, select any portion of the image and copy it and the error appears.
Open an image using Picasa, right click and select copy and the error appears.
Press PrntScr button and the error appears.
The error is throwed at SIZE_T size = GlobalSize(hContent); line, and it is either:
Critical error detected c0000374 YClipboard.exe has triggered a breakpoint.
or
Exception thrown at 0x77E17ECC (ntdll.dll) in YClipboard.exe: 0xC0000005: Access violation reading location 0xDD46116F.
The error is not persistent, most of the time it appeared right in the first copy, sometime I can copy the image, but do it multiple times with that same image cause the error. Above all, only attempt to copy "image" data cause the problem.
What I have tried so far
I am a novice about developing desktop app, and I my searching don't find the problem anywhere else. When I peek at the clipboard data using a third-party app, I found out the error only appear when my program met the CF_BITMAP or CF_METAFILEPICT format, and (not so) coincidentally both of those formats have a memory of size 0. Still I am unable to fix my problem.
What I need
Someone please enlighten me about this problem: what is the problem, the cause of it, how to fix it or just a suggestion about another method that help me read the size of clipboard data to replace GlobalSize() function.
Thanks in advance.
Not all clipboard formats present an HGLOBAL that you can use with functions like GlobalSize().
For example, CF_BITMAP presents a handle to a bitmap; an HBITMAP that you can use with functions like GetObject().
You'll need to handle those formats specially. See the Standard Clipboard Formats list on MSDN for more information.

Random crashes on Windows 10 64bit with ATL subclassing

Just from the start: Since March 1st 2017 this is a bug confirmed by Microsoft. Read comments at the end.
Short description:
I have random crashes in larger application using MFC, ATL. In all such cases after ATL subclassing was used for a window upon simple actions with a window (moving, resizing, setting the focus, painting etc.) I get a crash on a random execution address.
First it looked like a wild pointer or heap corruption but I narrowed the complete scenario down to a very simple application using pure ATL and only Windows API.
Requirements / my used scenarios:
The application was created with VS 2015 Enterprise Update 3.
The program should be compiled as 32bit.
Test application uses CRT as a shared DLL.
The application runs under Windows 10 Build 14393.693 64bit (but we have repros under Windows 8.1 and Windows Server 2012 R2, all 64bit)
atlthunk.dll has version 10.0.14393.0
What the application does:
It simply creates a frame window and tries to create many static windows with the windows API.
After the static window is created, this window is subclassed with the ATL CWindowImpl::SubclassWindow method.
After the subclass operation a simple window message is sent.
What happens:
Not on every run, but very often the application crashes upon SendMessage to the subclassed window.
On the 257 window ( or another multiple of 256+1) the subclass fails in some way. The ATL thunk that is created is invalid. It seems that the stored execution address of the new subclass-function isn't correct.
Sending any the message to the window causes a crash.
The callstack is always the same. The last visible and known address in the callstack is in the atlthunk.dll
atlthunk.dll!AtlThunk_Call(unsigned int,unsigned int,unsigned int,long) Unknown
atlthunk.dll!AtlThunk_0x00(struct HWND__ *,unsigned int,unsigned int,long) Unknown
user32.dll!__InternalCallWinProc#20() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!SendMessageWorker() Unknown
user32.dll!SendMessageW() Unknown
CrashAtlThunk.exe!WindowCheck() Line 52 C++
The thrown exception in the debugger is shown as:
Exception thrown at 0x0BF67000 in CrashAtlThunk.exe:
0xC0000005: Access violation executing location 0x0BF67000.
or another sample
Exception thrown at 0x2D75E06D in CrashAtlThunk.exe:
0xC0000005: Access violation executing location 0x2D75E06D.
What I know about atlthunk.dll:
Atlthunk.dll seems to be only part of 64bit OS. I found it on a Win 8.1 and Win 10 systems.
If atlthunk.dll is available (all Windows 10 machines), this DLL cares about the thunking. If the DLL isn't present, thunking is done in the standard way: allocating a block on the heap, marking it as executable, adding some load and a jump statement.
If the DLL is present. It contains 256 predefined slots for subclassing. If 256 subclasses are done, the DLL reloads itself a second time into memory and uses the next 256 available slots in the DLL.
As far as I see, the atlthunk.dll belongs to the Windows 10 and isn't exchangeable or redistributable.
Things checked:
Antivirus system was turned of or on, no change
Data execution protection doesn't matter. (/NXCOMPAT:NO and the EXE is defined as an exclusion in the system settings, crashes too)
Additional calls to FlushInstructionCache or Sleep calls after the subclass doesn't have any effect.
Heap integrity isn't a problem here, I rechecked it with more than one tool.
and a thousands more (I may already forgot what I tested)... ;)
Reproducibility:
The problem is somehow reproducible. It doesn't crashes all the time, it crashes randomly. I have a machine were the code crashes on every third execution.
I can repro it on two desktop stations with i7-4770 and a i7-6700.
Other machines seem not to be affected at all (works always on a Laptop i3-3217, or desktop with i7-870)
About the sample:
For simplicity I use a SEH handler to catch the error. If you debug the application the debugger will show the callstack mentioned above.
The program can be launched with an integer on the command line.In this case the program launches itself again with the count decremented by 1.So if you launch CrashAtlThunk 100 it will launch the application 100 times. Upon an error the SEH handler will catch the error and shows the text "Crash" in a message box. If the application runs without errors, the application shows "Succeeded" in a message box.
If the application is started without a parameter it is just executed once.
Questions:
Does anybody else can repro this?
Does anybody saw similar effects?
Does anybody know or can imagine a reason for this?
Does anybody know how to get around this problem?
Notes:
2017-01-20 Support case at Microsoft opened.
The code
// CrashAtlThunk.cpp : Defines the entry point for the application.
//
// Windows Header Files:
#include <windows.h>
// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
#include <atlbase.h>
#include <atlstr.h>
#include <atlwin.h>
// Global Variables:
HINSTANCE hInst; // current instance
const int NUM_WINDOWS = 1000;
//------------------------------------------------------
// The problematic code
// After the 256th subclass the application randomly crashes.
class CMyWindow : public CWindowImpl<CMyWindow>
{
public:
virtual BOOL ProcessWindowMessage(_In_ HWND hWnd, _In_ UINT uMsg, _In_ WPARAM wParam, _In_ LPARAM lParam, _Inout_ LRESULT& lResult, _In_ DWORD dwMsgMapID) override
{
return FALSE;
}
};
void WindowCheck()
{
HWND ahwnd[NUM_WINDOWS];
CMyWindow subclass[_countof(ahwnd)];
HWND hwndFrame;
ATLVERIFY(hwndFrame = ::CreateWindow(_T("Static"), _T("Frame"), SS_SIMPLE, 0, 0, 10, 10, NULL, NULL, hInst, NULL));
for (int i = 0; i<_countof(ahwnd); ++i)
{
ATLVERIFY(ahwnd[i] = ::CreateWindow(_T("Static"), _T("DummyWindow"), SS_SIMPLE|WS_CHILD, 0, 0, 10, 10, hwndFrame, NULL, hInst, NULL));
if (ahwnd[i])
{
subclass[i].SubclassWindow(ahwnd[i]);
ATLVERIFY(SendMessage(ahwnd[i], WM_GETTEXTLENGTH, 0, 0)!=0);
}
}
for (int i = 0; i<_countof(ahwnd); ++i)
{
if (ahwnd[i])
::DestroyWindow(ahwnd[i]);
}
::DestroyWindow(hwndFrame);
}
//------------------------------------------------------
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
hInst = hInstance;
int iCount = _tcstol(lpCmdLine, nullptr, 10);
__try
{
WindowCheck();
if (iCount==0)
{
::MessageBox(NULL, _T("Succeeded"), _T("CrashAtlThunk"), MB_OK|MB_ICONINFORMATION);
}
else
{
TCHAR szFileName[_MAX_PATH];
TCHAR szCount[16];
_itot_s(--iCount, szCount, 10);
::GetModuleFileName(NULL, szFileName, _countof(szFileName));
::ShellExecute(NULL, _T("open"), szFileName, szCount, nullptr, SW_SHOW);
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
::MessageBox(NULL, _T("Crash"), _T("CrashAtlThunk"), MB_OK|MB_ICONWARNING);
return FALSE;
}
return 0;
}
Comment after answered by Eugene (Feb. 24th 2017):
I don't want to change my original question, but I want to add some additional information how to get this into a 100% Repro.
1, Change the main function to
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
// Get the load address of ATLTHUNK.DLL
// HMODULE hMod = LoadLibrary(_T("atlThunk.dll"));
// Now allocate a page at the prefered start address
void* pMem = VirtualAlloc(reinterpret_cast<void*>(0x0f370000), 0x10000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
DWORD dwLastError = ::GetLastError();
hInst = hInstance;
WindowCheck();
return 0;
}
Uncomment the LoadLibrary call. Compile.
Run the programm once and stop in the debugger. Note the address where the library was loaded (hMod).
Stop the program. Now comment the Library call again and change the VirtualAlloc call to the address of the previous hMod value, this is the prefered load address in this window session.
Recompile and run. CRASH!
Thanks to eugene.
Up to now. Microsoft ist still investigating about this. They have dumps and all code. But I don't have a final answer. Fact is we have a fatal bug in some Windows 64bit OS.
I currently made the following changes to get around this
Open atlstdthunk.h of VS-2015.
Uncomment the #ifdef block completely that defines USE_ATL_THUNK2. Code lines 25 to 27.
Recompile your program.
This enables the old thunking mechanism well known from VC-2010, VC-2013... and this works crash free for me. As long as there are no other already compiled libraries involved that may subclass or use 256 windows via ATL in any way.
Comment (Mar. 1st 2017):
Microsoft confirmed that this is a bug. It should be fixed in Windows 10 RS2.
Mircrosoft agrees that editing the headers in the atlstdthunk.h is a workaround for the problem.
In fact this says. As long as there is no stable patch I can never use the normal ATL thunking again, because I will never know what Window versions out in the world will use my program. Because Windows 8 and Windows 8.1 and Windows 10 prior to RS2 will suffer on this bug.
Final Comment (Mar. 9th 2017):
Builds with VS-2017 are affected too, there is no difference between VS-2015 and VS-2017
Microsoft decided that there will be no fix for older OS, regarding this case.
Neither Windows 8.1, Windows Server 2012 RC2 or other Windows 10 builds will get a patch to fix this issue.
The issue is to rare and the impact for our company is to small. Also the fix from our side is to simple. Other reports of this bug are not known.
The case is closed.
My advice for all programers: Change the the atlstdthunk.h in your Visual Studio version VS-2015, VS-2017 (see above). I don't understand Microsoft. This bug is a serious problem in the ATL thunking. It may hit every programmer that uses a greater number of windows and/or subclassing.
We only know of a fix in Windows 10 RS2. So all older OS are affected! So I recommend to disable the use of the atlthunk.dll by commenting out the define noted above.
This is the bug inside atlthunk.dll. When it loads itself second time and further this happens manually via MapViewOfFile call. In this case not every address relative to the module base is properly changed (when DLL loaded by LoadLibarary/LoadLibraryEx calls system loader does this automatically). Then if the first time DLL was loaded on preferred base address everything works fine as unchanged addresses point to the similar code or data. But if not you got crash when 257th subclassed window handles messages.
Since Vista we have "address space layout randomization" feature this explains why your code crashes randomly. To have crash every time you have to discover atlthunk.dll base address on your OS (it differs on different OS versions) and do one memory page address space reservation at this address using VirtualAlloc call before the first subclass. To find the base address you can use dumpbin /headers atlthunk.dll command or parse PE headers manually.
My test shows that on Windows 10 build 14393.693 x32 version is affected but x64 is not. On Server 2012R2 with latest updates both (x32 and x64) versions are affected.
BTW, atlthunk.dll code has around 10 times more CPU instructions per thunk call as previous implementation. It may be not very significant but it slows down the message processing.
Slightly more automatic form of what was already described:
// A minimum ATL program with more than 256 windows. In practise they would not be toplevel, but e.g. buttons.
// Thanks to https://www.codeguru.com/cpp/com-tech/atl/article.php/c3605/Using-the-ATL-Windowing-Classes.htm
// for helping with ATL.
// You need to be up to date, like have KB3030947 or KB3061512. Otherwise asserts will fail instead.
#undef _DEBUG
#include <atlbase.h>
ATL::CComModule _Module;
#include <atlwin.h>
#include <assert.h>
#include <string>
BEGIN_OBJECT_MAP(ObjectMap) END_OBJECT_MAP()
struct CMyWindow : CWindowImpl<CMyWindow>
{
BEGIN_MSG_MAP(CMyWindow) END_MSG_MAP()
};
int __cdecl wmain()
{
// Exacerbate the problem, which can happen more like if by chance.
PROCESS_INFORMATION process = { 0 };
{
// Be sure another process has atlthunk loaded.
WCHAR cmd[] = L"rundll32 atlthunk,x";
STARTUPINFOW startup = { sizeof(startup) };
BOOL success = CreateProcessW(0, cmd, 0, 0, 0, 0, 0, 0, &startup, &process);
assert(success && process.hProcess);
CloseHandle(process.hThread);
// Get atlthunk's usual address.
HANDLE file = CreateFileW((std::wstring(_wgetenv(L"SystemRoot")) + L"\\system32\\atlthunk.dll").c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
assert(file != INVALID_HANDLE_VALUE);
HANDLE mapping = CreateFileMappingW(file, 0, PAGE_READONLY | SEC_IMAGE, 0, 0, 0);
assert(mapping);
void* view = MapViewOfFile(mapping, 0, 0, 0, 0);
assert(view);
UnmapViewOfFile(view);
VirtualAlloc(view, 1, MEM_COMMIT | MEM_RESERVE, PAGE_NOACCESS);
}
_Module.Init(0, 0);
const int N = 300;
CMyWindow wnd[N];
for (int i = 0; i < N; ++i)
{
wnd[i].Create(0, CWindow::rcDefault, L"Hello", (i < N - 1) ? 0 : (WS_OVERLAPPEDWINDOW | WS_VISIBLE));
wnd[i].DestroyWindow();
}
TerminateProcess(process.hProcess, 0);
CloseHandle(process.hProcess);
MSG msg;
while (GetMessageW(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
_Module.Term();
}

How to use windows raw input in OpenSceneGraph?

I want to use windows raw input to enable two mice input on one computer.
However, I failed to figure out how to get the WM_INPUT message. It seems to get the message, I need to do this:
MainWndProc (HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch (nMsg)
{
...
case WM_INPUT:
{
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize,
sizeof(RAWINPUTHEADER));
.............
}
}
I think the OpenSceneGraph window should be a window's type,but how can I get the WM_INPUT message without using MainWndProc?
It seems I cannot get WM_INPUT message like this:
bool CallbackManager::handle(const GUIEventAdapter& ea, GUIActionAdapter& us)
{
if(ea.getEventType() == WM_INPUT)
Then should I get the windows handle and how to?
OpenSceneGraph is a cross plattform toolkit. The Windows messages are translated internally in OpenSceneGraph and turned into OSG specific types. What you get in the CallbackManager is completely detached from the Windows messages.
Short of diving into the OpenSceneGraph code and adding the multiple pointer device support in OSG's core, there's little you can do about it.

How to get quick launch bar size in Windows XP?

I want to get quick launch bar size, but my code returns false, where is the problem?
REBARBANDINFOW prbi;
memset(&prbi, 0, sizeof(REBARBANDINFOW));
prbi.cbSize = sizeof(REBARBANDINFOW);
prbi.fMask = 892;
HWND hWndTray = ::FindWindow(L"Shell_TrayWnd", 0);
HWND hRebar = ::FindWindowEx(hWndTray, NULL, L"ReBarWindow32", 0);
int i = ::SendMessage(hRebar, RB_GETBANDINFOW, 0, (LPARAM)(LPREBARBANDINFOW)&prbi);
The problem is with the LPARAM of RB_GETBANDINFOW. The address of the structure you are sending is only valid in your own address space, not that of Explorer. Luckily, Explorer detects this and fails gracefully instead of blowing up.
One way to solve this is to use VirtualAllocEx to allocate the REBARBANDINFOW in Explorer's memory, use WriteProcessMemory to initialize it, send the message, and finally call ReadProcessMemory to read the result.
I've successfully used this technique in a Python script to automatically set the Quick Launch's size.
You are trying to get too much info. Place prbi.fMask = 32; or prbi.fMask = 64;.

ERROR_INVALID_HANDLE on TerminateProcess (VS C++)

Disclaimer: This is part of the requirement of the program, so it's not meant for anything bad. Feel free to point out any misuse if you spot one. I'm a beginner in C++.
Basically, I'm trying to restart Outlook.exe on Windows using C++.
And this is the code I used to restart Outlook.
#include <TlHelp32.h>
void RestartOutlook() {
PROCESSENTRY32 Pc = { sizeof(PROCESSENTRY32) };
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
MODULEENTRY32 Mo = {sizeof (MODULEENTRY32) };
if(Process32First(hSnapshot, &Pc)){
do{
if(!_stricmp(Pc.szExeFile, "outlook.exe")) {
DWORD pid = Pc.th32ProcessID;
HANDLE hModuleSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
//kill outlook
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
DWORD fdwExit = 0;
GetExitCodeProcess(process, &fdwExit);
TerminateProcess(process, fdwExit);
char * path;
if (Module32First(hModuleSnapshot, &Mo)) {
path = Mo.szExePath;
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof (si);
CreateProcess(path, NULL, NULL, NULL, false, NORMAL_PRIORITY_CLASS,
NULL, NULL, &si, &pi);
}
}
}while(Process32Next(hSnapshot, &Pc));
}
}
The funny part is, this piece of code works perfectly fine on Windows 7. While on Windows XP (SP3), I get duplicated Outlook. The GetLastError gives me 6: ERROR_INVALID_HANDLE. I am really clueless after hours of research.
Any idea?
Anyway, C++ is not my field. I do webs :)
And the code above is a mixture of the following sources:
1: http://www.istorya.net/forums/programming/107435-how-can-i-kill-a-process-using-c.html
2: http://code.activestate.com/recipes/576362-list-system-process-and-process-information-on-win/
Environment: Windows 7, Windows XP, VS2010, Outlook 2003, Outlook 2007, Outlook 2010
I found the culprit.
The reason lies in this line:
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid);
According to http://msdn.microsoft.com/en-us/library/ms684880(v=vs.85).aspx, PROCESS_ALL_ACCESS is too large for Windows XP/NT system, or more details:
The size of the PROCESS_ALL_ACCESS flag increased on Windows Server 2008 and Windows Vista. If an application compiled for Windows Server 2008 and Windows Vista is run on Windows Server 2003 or Windows XP/2000, the PROCESS_ALL_ACCESS flag is too large and the function specifying this flag fails with ERROR_ACCESS_DENIED. To avoid this problem, specify the minimum set of access rights required for the operation.
Definitely I'm compiling this program on 7, while running on XP definitely causing the problem.
So the solution is, change the PROCESS_ALL_ACCESS to PROCESS_TERMINATE, which
HANDLE process = OpenProcess(PROCESS_TERMINATE, TRUE, pid);
Done!
Thanks #DReJ for quick replies :)
I get that you want Outlook to restart but calling TerminateProcess on Outlook seems like a bad idea in the first place. What if it's in the middle of writing a data file?
A better way would be to find all top-level windows that belong to Outlook, send them a WM_CLOSE and then wait for the process to exit. (You may also have to cope with the user having draft messages open which result in "are you sure" prompts, although if you are doing this in the first place then I assume you know the user isn't in the middle of something?)
An even better way would be to use Outlook's automation interface and tell it to shutdown explicitly.
Your problem maybe related to this piece of code
DWORD fdwExit = 0;
GetExitCodeProcess(process, &fdwExit);
TerminateProcess(process, fdwExit);
First, with GetExitCodeProcess you get status STILL_ACTIVE and after that you terminate process with this status which is not proper I think. Remove GetExitCodeProcess from you code and try TerminateProcess(process, 0); instead.