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();
}
Related
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
I'm maintaining a C++ program that uses Win32. It's been working fine for years, but now I am having problems with the "select file" or "select folder" functions on 2 computers both running Windows 8, yet not on 2 other computers running Windows 8.
The problem is that the program crashes in the "select file" or "select folder" functions, deep in Microsoft code. It crashes immediately after displaying the dialog, before the user has a chance to touch anything.
I've done a lot of experimentation, and I've got it to randomly work, but then recompiling the same code will make the bug reappear. Finally I produced a tiny program that calls the function 10 times in succession, without any other code, and the first time always succeeds but the 2nd time the program crashes. Linked in with my full program, it sometimes crashes on the first call, sometimes on the 2nd. My code is below:
#include <windows.h>
int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance,
LPSTR args, int nCmdShow)
{
for (int i=0; i < 10; i++) {
OPENFILENAME OFN;
char buf[1024];
memset(&OFN, 0, sizeof(OFN));
OFN.lStructSize = sizeof(OFN);
OFN.hwndOwner = NULL;
OFN.hInstance = NULL;
OFN.lpstrFilter = "PTN files\0*.ptn\0\0\0";//overkill
OFN.lpstrCustomFilter = NULL;
OFN.nMaxCustFilter = 0;
OFN.nFilterIndex = 1;
OFN.nMaxFile = sizeof(buf);
OFN.lpstrFileTitle = NULL;
OFN.nMaxFileTitle = 0;
OFN.lpstrTitle = NULL;
OFN.nFileOffset = 0;
OFN.nFileExtension = 0;
OFN.lpstrDefExt = "ptn";
OFN.lCustData = 0;
OFN.lpfnHook = 0;
OFN.lpTemplateName = NULL;
OFN.lpstrInitialDir = NULL;
strcpy(buf, "\0");//overkill
OFN.lpstrFile = buf;
OFN.Flags = OFN_LONGNAMES | OFN_HIDEREADONLY | OFN_EXPLORER;
//NB: tried both with and without OFN_EXPLORER
GetSaveFileName(&OFN);
}
return 0;
}
Any ideas?
I cannot see any error in your code.
I doubt that anybody will be able to answer your question.
Just some ideas:
1.)
You compile your project as MBCS ?
Does Windows 8 still support that Ansi stuff ?
Did you try if the same happens with the Unicode version?
2.)
I have had also a lot of troubles with these functions already in Windows XP.
They are definitely buggy and it seems that in Windows 8 they are still or even more. I found out for example that an invalid value for lpstrFile may result in the dialog not opening. Also other parameters are critical.
3.)
What value did you define for _WIN32_WINNT ?
I recommend at least 0x0502 or higher to assure that OPENFILENAME structure is not a version from the age of Windows NT which might not be supported on Windows 8.
4.)
What happens if you try out the MFC version:
CFileDialog dlg(FALSE);
dlg.DoModal();
Let all parameters in their default value. If this works you know that it is not a Windows 8 bug. Then study what parameters differ in the OFN from your code. Also have a look at the value of sizeof(OFN) which may influence the behavior of Windows 8.
5.) It may be required that your application / Dll has an embedded manifest for Shell32 to work correctly.
#pragma comment(linker,"\"/manifestdependency:type='win32' processorArchitecture='X86' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*'\"")
6.)
If all this does not help you have to experiment until you found what parameter causes the problem: Is hwndOwner required on Windows 8 ? Is hInstance required on Windows 8 ? Is there a flag missing ? Is lpstrInitialDir required ?
7.) I have had very very weird crashes that happened from time to time, very difficult to reproduce. After WEEKS of frustrating search I finally found out that this is a bug in Visual Studio. The solution to avoid the crashy code was to select "*Re*build Solution" in the menu of Visual Studio. I have this effect only in one of my projects.
I'm writing up David Heffernan's answer which he provided as a question comment. (David, if you provide a proper answer, I'll upvote it and try to delete this one).
"Try disabling shell extensions on the machines which fail. There are tools around that allow you to temporarily disable shell extensions. For instance: nirsoft.net/utils/shexview.html It's just a hunch that a shell extension is screwing with your program."
I am tring to create a Remote thread that will load a DLL I wrote, and run a function from it.
The DLL is working fine (Checked) but from some reason, the Remote thread fails and the proccess in which it was created stop responding.
I used ollyDebug to try and see what is going wrong and I noticed two things...
My strings (dll name and function name) are passed to the remote thread correctly
The thread fails on LoadLibrary with lasterror code 87 "ERROR_INVALID_PARAMETER"
My best guess is that somehow, The remote thread can't find LoadLibrary (Is this because the linker is done with repspect to my proccess???, Just a guess...)
What am I doing wrong?
This is the code to the remote function:
static DWORD WINAPI SetRemoteHook (DATA *data)
{
HINSTANCE dll;
HHOOK WINAPI hook;
HOOK_PROC hookAdress;
dll = LoadLibrary(data->dll);
hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
if (hookAdress != NULL)
{
(hookAdress)();
}
return 1;
}
Edit:
This is the part in which I allocate the memory to the remote proccess:
typedef struct
{
char* dll;
char* func;
} DATA;
char* dllName = "C:\\Windows\\System32\\cptnhook.dll";
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );
Edit:
It looks like the problem is that the remote thread is calling a "garbage" address
instead of LoadLibrary base address. Is there a possibily Visual studio linked
the remote proccess LoadLibrary address wrong?
Edit:
when I try to run the same exact code as a local thread (I use a handle to the current procces in CreateRemoteThread) the entire thing works just fine. What can cause this?
Should I add the calling function code? It seems to be doing its job as
the code is being executed in the remote thread with the correct parameters...
The code is compiled under VS2010.
data is a simple struct with char* 's to the names. (As explicetly writing the strings in code would lead to pointers to my original proccess).
What am I doing wrong?
Failing with ERROR_INVALID_PARAMETER indicates that there is a problem with the parameters passed.
So one should look at data->dll which represents the only parameter in question.
It is initialised here:
lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);
So let's add a check whether the allocation of the memory which's reference should be store into lData.dll really succeded.
if (!lData.dll) {
// do some error logging/handling/whatsoever
}
Having done so, you might have detected that the call as implemented failed because (verbatim from MSDN for VirtualAllocEx()):
The function fails if you attempt to commit a page that has not been
reserved. The resulting error code is ERROR_INVALID_ADDRESS.
So you might like to modifiy the fourth parameter of the call in question as recommended (again verbatim from MSDN):
To reserve and commit pages in one step, call VirtualAllocEx with
MEM_COMMIT | MEM_RESERVE.
PS: Repeat this exercise for the call to allocate lData.func. ;-)
It's possible that LoadLibrary is actually aliasing LoadLibraryW (depending on project settings), which is the Unicode version. Whenever you use the Windows API with "char" strings instead of "TCHAR", you should explicitly use ANSI version names. This will prevent debugging hassles when the code is written, and also in the future for you or somebody else in case the project ever flips to Unicode.
So, in addition to fixing that horrible unterminated string problem, make sure to use:
LoadLibraryA(data->dll);
I'm looking for some random crashes in an old c++ application. Using sysinternals process explorer, I noticed the app losing handles, and extracted the exact situation, where the program is losing handles to a very short piece of code.
DWORD WINAPI MyTestThread( void* PThread)
{
_endthreadex(0);
return 0;
}
int WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR PParameter, int)
{
for (int i=0;i<10000;i++)
{
unsigned int threadID;
HANDLE hThread= (HANDLE)_beginthreadex( (void*)NULL, (unsigned int)32768, (unsigned int (__stdcall *)(void *))MyTestThread, (void*)NULL, (unsigned int)0, &threadID);
WaitForSingleObject((HANDLE)hThread, 1000);
CloseHandle((HANDLE)hThread);
}
return 0;
}
My problem: I can't figure out what's wrong with this code. It loses exactly 5 handles on every iteration, but it looks OK to me.
Funny thing: it seems not to lose handles on windows vista, but I'd be very surprised if this should be a bug in windows 7.
[Update] I tried using _beginthread/_endthread and CreateThread/ExitThread instead, those two are losing 5 handles, too, just like _beginthreadex.
[2nd Update] the code does run as expected. All return values are good. It is 'just' losing handles like there is no tomorrow.
[3rd Update] Big new Info The code only loses handles, if compiled with /clr! And more, if I call GC::Collect() on each iteration the handles will be reclaimed!
So, how do I find what clr-objects are being collected there?
Check whether some DLL which is linked to your exe is doing something strange in its DLLMain in response to DLL_THREAD_ATTACH notifications.
Have you checked if the functions succeed? The return values and GetLastError() could give some hints what's going wrong.
From http://msdn.microsoft.com/en-us/library/kdzttdcb.aspx
"If successful, each of these functions returns a handle to the newly created thread; however, if the newly created thread exits too quickly, _beginthread might not return a valid handle (see the discussion in the Remarks section). _beginthread returns -1L on an error, in which case errno is set to EAGAIN if there are too many threads, to EINVAL if the argument is invalid or the stack size is incorrect, or to EACCES in the case of insufficient resources (such as memory). _beginthreadex returns 0 on an error, in which case errno and _doserrno are set. "
Your thread does exit kind of quickly doesn't it.
Have you tried testing this with Win32's CreateThread? That could possibly narrow down the problem to the CRT.
How would you program a C/C++ application that could run without opening a window or console?
When you write a WinMain program, you automatically get the /SUBSYSTEM option to be windows in the compiler. (Assuming you use Visual Studio). For any other compiler a similar option might be present but the flag name might be different.
This causes the compiler to create an entry in the executable file format (PE format) that marks the executable as a windows executable.
Once this information is present in the executable, the system loader that starts the program will treat your binary as a windows executable and not a console program and therefore it does not cause console windows to automatically open when it runs.
But a windows program need not create any windows if it need not want to, much like all those programs and services that you see running in the taskbar, but do not see any corresponding windows for them. This can also happen if you create a window but opt not to show it.
All you need to do, to achieve all this is,
#include <Windows.h>
int WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int cmdShow)
{
/* do your stuff here. If you return from this function the program ends */
}
The reason you require a WinMain itself is that once you mark the subsystem as Windows, the linker assumes that your entry point function (which is called after the program loads and the C Run TIme library initializes) will be WinMain and not main. If you do not provide a WinMain in such a program you will get an un-resolved symbol error during the linking process.
In windows:
#include <windows.h>
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// <-- Program logic here
return 0;
}
Be sure to use the /SUBSYSTEM linker switch as mentioned by Adam Mitz.
On other platforms:
int main(int argc, char**argv)
{
// <-- Program logic here
return 0;
}
If you have a need to contiguously run your program without having console or window you might find useful deamon on *NIX or services on Windows, this .NET example if you need plain win32 just google a little bit for sample.
Since your question tagged as win32 i assume that services are more relevant for you.
This also processes messages:
#include <windows.h>
#include <stdio.h>
int CALLBACK WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
MSG msg;
DWORD curThreadId;
curThreadId = GetCurrentThreadId();
// Send messages to self:
PostThreadMessage(curThreadId, WM_USER, 1, 2);
PostThreadMessage(curThreadId, WM_USER+1, 3, 4);
PostThreadMessage(curThreadId, WM_USER+2, 5, 6);
PostThreadMessage(curThreadId, WM_USER+3, 7, 8);
PostThreadMessage(curThreadId, WM_QUIT, 9, 10);
while (GetMessage(&msg, NULL, 0, 0)) {
printf("message: %d; wParam: %d; lParam: %d\n", msg.message, msg.wParam, msg.lParam);
}
return (int) msg.wParam;
}
In Visual Studio Express 2010 after setting the subsystem to windows (as suggested by user17224), alternatively to changing the main to WinMain (as suggested by user17224 and Brian R. Bondy), one can set the entry function to main in properties, linker, advanced, entry point: just type main in the text box.
Use Visual Studio wizard to create the Win32 Application. But don't create the window i.e., you remove the window creation function.
Alternatively we can create Win Service application.
If you are using MSVC or Visual Studio just use the new Project Wizard and select the Console Application.