Enumerating application's process name only - winapi

How to list process names only? I looked at Enumerating All Modules For a Process. The example code works with process names and modules, but I want only process names.
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <iostream>
using namespace std;
int main()
{
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
HANDLE hProcess;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
{
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
for (i = 0; i < cProcesses; i++)
{
DWORD processID = aProcesses[i];
cout << processID << endl;
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
}
CloseHandle(hProcess);
return 0;
}

Get the process ids using your code and then use EnumProcessModules in combination with GetModuleBaseName to print the name of all the executables.
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <psapi.h>
void PrintProcessName( DWORD processID )
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
// Get a handle to the process.
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
// Get the process name.
if (NULL != hProcess )
{
HMODULE hMod;
DWORD cbNeeded;
if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod),
&cbNeeded) )
{
GetModuleBaseName( hProcess, hMod, szProcessName,
sizeof(szProcessName)/sizeof(TCHAR) );
}
}
// Print the process name and identifier.
_tprintf( TEXT("%s\n"), szProcessName );
// Release the handle to the process.
CloseHandle( hProcess );
}
int main( void )
{
// Get the list of process identifiers.
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
{
return 1;
}
// Calculate how many process identifiers were returned.
cProcesses = cbNeeded / sizeof(DWORD);
// Print the name and process identifier for each process.
for ( i = 0; i < cProcesses; i++ )
{
if( aProcesses[i] != 0 )
{
PrintProcessName( aProcesses[i] );
}
}
return 0;
}

Related

NT Security API: SECURITY_DESCRIPTOR.Control, when can I see SE_OWNER_DEFAULTED?

From Windows NT security API, SE_OWNER_DEFAULTED is a flag bit from SECURITY_DESCRIPTOR_CONTROL.
MSDN states it quite briefly:
(SE_OWNER_DEFAULTED) Indicates that the SID of the owner of the security descriptor was provided by a default mechanism. This flag can be used by a resource manager to identify objects whose owner was set by a default mechanism.
I'm curious that when I can see this flag set.
I write NtfsOwner.cpp to display owner SID of an NTFS file/directory's security descriptor, and use GetSecurityDescriptorOwner to query that SE_OWNER_DEFAULTED flag, but have no chance seeing it even once.
Could somebody give me some clue. Could it be possible that SE_OWNER_DEFAULTED exhibits on other type of NT objects(not on a file/directory)?
#include <Windows.h>
#include <AclAPI.h>
#include <sddl.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <locale.h>
template<typename T1, typename T2>
bool IsSameBool(T1 a, T2 b)
{
if(a && b)
return true;
else if(!a && !b)
return true;
else
return false;
}
void myDisplayNtfsOwner(const TCHAR *szfn)
{
DWORD succ = 0;
HANDLE hFile = CreateFile(szfn,
READ_CONTROL, // dwDesiredAccess=GENERIC_READ etc
FILE_SHARE_READ|FILE_SHARE_WRITE, // shareMode
NULL, // SecuAttr, no need bcz we are opening existing file
OPEN_EXISTING, // dwCreationDisposition
FILE_FLAG_BACKUP_SEMANTICS, // this is required for open a directory
NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
_tprintf(_T("Warning: CreateFile() failed!(WinErr=%d) But I will go on calling GetSecurityInfo(0xFFFFffff, ...)\n"),
GetLastError());
}
SECURITY_DESCRIPTOR *pSD = nullptr;
DWORD winerr = GetSecurityInfo(hFile, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION,
NULL, NULL, NULL, NULL,
(PSECURITY_DESCRIPTOR*)&pSD);
assert(winerr==0);
SID* psidOwner = nullptr;
BOOL isOwnerDefaulted = 0;
succ = GetSecurityDescriptorOwner(pSD, (PSID*)&psidOwner, &isOwnerDefaulted);
assert(succ);
PTSTR strOwner = nullptr;
succ = ConvertSidToStringSid(psidOwner, &strOwner);
assert(succ);
_tprintf(_T("Owner SID is: %s\n"), strOwner);
_tprintf(_T("Is owner SID defaulted? %s\n"), isOwnerDefaulted?_T("yes"):_T("no"));
assert(IsSameBool(pSD->Control & SE_OWNER_DEFAULTED, isOwnerDefaulted));
LocalFree(strOwner);
LocalFree(pSD);
CloseHandle(hFile);
}
int _tmain(int argc, TCHAR* argv[])
{
setlocale(LC_ALL, "");
if(argc==1)
{
const TCHAR *s = _T("D:\\test\\foo.txt");
_tprintf(_T("Missing parameters.\n"));
_tprintf(_T("Example:\n"));
_tprintf(_T(" NtfsOwner1 %s\n"), s);
exit(1);
}
const TCHAR *szfn = argv[1];
myDisplayNtfsOwner(szfn);
return 0;
}

Getting process description with given process-id

I've got a program that enumerates all processes with the Toolhelp API. With my Sysinternals Process Explorer I also can see a description of all processes. Is this description coming from the executable ? How do I get its name ?
That's my current code to enumerate the processes:
#include <Windows.h>
#include <TlHelp32.h>
#include <iostream>
#include <vector>
#include <system_error>
#include <memory>
using namespace std;
vector<PROCESSENTRY32W> getAllProcesses();
int main()
{
for( PROCESSENTRY32W &pe : getAllProcesses() )
wcout << pe.szExeFile << endl;
}
using XHANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( h ); })>;
vector<PROCESSENTRY32W> getAllProcesses()
{
auto throwSysErr = []() { throw system_error( (int)GetLastError(), system_category(), "error enumerating processes" ); };
vector<PROCESSENTRY32W> processes;
XHANDLE xhSnapshot( CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ) );
if( xhSnapshot.get() == INVALID_HANDLE_VALUE )
throwSysErr();;
PROCESSENTRY32W pe;
pe.dwSize = sizeof pe;
if( !Process32FirstW( xhSnapshot.get(), &pe ) )
throwSysErr();
for( ; ; )
{
processes.emplace_back( pe );
pe.dwSize = sizeof pe;
if( !Process32NextW( xhSnapshot.get(), &pe ) )
if( GetLastError() == ERROR_NO_MORE_FILES )
break;
else
throwSysErr();
}
return processes;
}
#RemyLebeau 's way with code implement which is adapted from VerQueryValueA document sample. And as OpenProcess states,
If the specified process is the System Idle Process (0x00000000), the
function fails and the last error code is ERROR_INVALID_PARAMETER. If
the specified process is the System process or one of the Client
Server Run-Time Subsystem (CSRSS) processes, this function fails and
the last error code is ERROR_ACCESS_DENIED because their access
restrictions prevent user-level code from opening them.
int main()
{
TCHAR szFile[MAX_PATH] = {};
DWORD dwSize = MAX_PATH;
for (PROCESSENTRY32W& pe : getAllProcesses())
{
wcout << pe.szExeFile << endl;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE, pe.th32ProcessID);
if (hProcess == NULL)
{
//ErrorExit(TEXT("OpenProcess"));
}
else
{
memset(szFile, 0, MAX_PATH);
dwSize = MAX_PATH;
QueryFullProcessImageName(hProcess,0, szFile,&dwSize);
DWORD s = GetFileVersionInfoSize(szFile,NULL);
if (s != 0)
{
LPVOID lpData = HeapAlloc(GetProcessHeap(), 0, s);
GetFileVersionInfo(szFile,0,s, lpData);
HRESULT hr;
UINT cbTranslate;
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
} *lpTranslate;
// Read the list of languages and code pages.
VerQueryValue(lpData,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID*)&lpTranslate,
&cbTranslate);
// Read the file description for each language and code page.
LPVOID lpBuffer;
UINT dwBytes;
for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++)
{
TCHAR SubBlock[255] = {};
hr = StringCchPrintf(SubBlock, 50,
TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
if (FAILED(hr))
{
// TODO: write error handler.
}
// Retrieve file description for language and code page "i".
VerQueryValue(lpData,
SubBlock,
&lpBuffer,
&dwBytes);
wcout << (TCHAR*)(lpBuffer) << endl;
}
HeapFree(GetProcessHeap(), 0, lpData);
}
//GetProcessImageFileName(hProcess, szFile, dwSize);
}
}
}

Getting Enviroment Variable with cpp

So I have been trying to figure out how to find an environment variable and print it out on the screen in c++
but for the last 3 hours or so, I have been stuck. When I print out the currentDesktop variable it only prints out "/Desktop". But what I'm looking for is the username in front of it.
I have been reading the documentation on the GetEnviromentVariable function from Microsoft's forum and this is what I have come up with so far.
Help would be greatly appreciated since I'm not so experienced yet, Thx.
#include <iostream>
#include <string>
#include <windows.h>
#include <fstream>
#define BUFSIZE 4096
using namespace std;
int main()
{
LPCWSTR Env = L"%USERPROFILE";
LPTSTR pszOldVal;
string IPADD;
pszOldVal = (LPTSTR)malloc(BUFSIZE * sizeof(TCHAR));
if (NULL == pszOldVal)
{
printf("Out of memory\n");
return FALSE;
}
string currentDesktop = GetEnvironmentVariable(Env,pszOldVal,BUFSIZE) + "\\Desktop";
cout << currentDesktop;
return 0;
}
You are misusing the GetEnvironmentVariable() function. For one thing, you are missing the trailing % on the variable name L"%USERPROFILE". For another thing, the return value is the number of characters copied into the supplied buffer. You are adding that integer to the string literal "\\Desktop", which is not what you want.
Try this instead:
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetEnv(const std::wstring &varName)
{
std::wstring str;
DWORD len = GetEnvironmentVariableW(varName.c_str(), NULL, 0);
if (len > 0)
{
str.resize(len);
str.resize(GetEnvironmentVariableW(varName.c_str(), &str[0], len));
}
return str;
}
std::wstring GetUserDesktopPath()
{
std::wstring path = GetEnv(L"%USERPROFILE%");
if (!path.empty()) path += L"\\Desktop";
return path;
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}
That being said, if you just want the username, use %USERNAME% instead of %USERPROFILE%. Or better, use GetUserName() instead of GetEnvironmentVariable():
#include <iostream>
#include <string>
#include <windows.h>
std::wstring GetUserName()
{
std::wstring str;
DWORD len = 0;
if (!GetUserNameW(NULL, &len))
{
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
str.resize(len);
if (GetUserNameW(&str[0], &len))
str.resize(len-1);
else
str = L"";
}
}
return str;
}
int main()
{
std::wstring currentUser = GetUserName();
std::wcout << currentUser;
return 0;
}
However, the correct way to get the path to the user's desktop is to just ask Windows for that specific path, don't assume it is in the root of the user's profile, or that is is named Desktop. Use SHGetFolderPath() or SHGetKnownFolderPath() for that query, eg:
#include <iostream>
#include <string>
#include <windows.h>
#include <shlobj.h>
std::wstring GetFolderPath(CSIDL folderID)
{
WCHAR path[MAX_PATH] = {};
SHGetFolderPathW(NULL, folderID, NULL, SHGFP_TYPE_CURRENT, path);
return path;
}
/* or:
std::wstring GetFolderPath(REFKNOWNFOLDERID folderID)
{
std::wstring str;
PWSTR path = NULL;
if (SHGetKnownFolderPath(folderID, 0, NULL, &path) == S_OK)
str = path;
CoTaskMemFree(path);
return str;
}
*/
std::wstring GetUserDesktopPath()
{
return GetFolderPath(CSIDL_DESKTOPDIRECTORY);
// or: return GetFolderPath(FOLDERID_Desktop);
}
int main()
{
std::wstring currentDesktop = GetUserDesktopPath();
std::wcout << currentDesktop;
return 0;
}

ReadDirectoryChangesW not notifying when moving the files

I’m new to this windows API. I’m a GUI developer in my project i need to monitor a particular folder . I have followed every steps in the Windows API using ReadDirectoryChangeW but ReadDirectoryChangeW is not notifying me when the file is moved to other directory (cut/paste or delete to move to trash).at least it should notify as FILE_ACTION_RENAMED
It is windows 7 and ReadDirectorChangeW is working on normal copy,paset,shift+delete,rename
this code is written in Qt c++ where QString is char *
this is my code
#include <windows.h>
#include <Winbase.h>
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <qDebug>
#include <QThread>
#define MAX_DIRS 200
#define MAX_FILES 255
#define MAX_BUFFER 4096
#if 0
extern "C" {
WINBASEAPI BOOL WINAPI
ReadDirectoryChangesW( HANDLE hDirectory,
LPVOID lpBuffer, DWORD nBufferLength,
BOOL bWatchSubtree, DWORD dwNotifyFilter,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped,
LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
}
#endif
class WatcherThread : public QThread
{
Q_OBJECT
public:
WatcherThread(LPCWSTR dir)
{
path = dir;
}
void run() Q_DECL_OVERRIDE {
QString newDirName;
char buf[2048];
DWORD nRet;
BOOL result=TRUE;
char filename[MAX_PATH];
//path = L"K:/Demo/bb";
wchar_t* arr = (wchar_t*)path;
printf("\nThe file directory: [%s] \n", path);
qDebug() << "WatchDirectory Watcher Path " << QString::fromWCharArray(arr);
DirInfo[0].hDir = CreateFile (path, GENERIC_READ|FILE_LIST_DIRECTORY,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if(DirInfo[0].hDir == INVALID_HANDLE_VALUE)
{
qDebug() << "Can not open";
return;
}
lstrcpy( DirInfo[0].lpszDirName, path);
OVERLAPPED PollingOverlap;
FILE_NOTIFY_INFORMATION pNotify[1024];
int offset;
PollingOverlap.OffsetHigh = 0;
PollingOverlap.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
while(result)
{
result = ReadDirectoryChangesW(
DirInfo[0].hDir,// handle to the directory to be watched
(LPVOID)&pNotify,// pointer to the buffer to receive the read results
sizeof(pNotify),// length of lpBuffer
1,// flag for monitoring directory or directory tree
FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_SIZE ,
&nRet,// number of bytes returned
&PollingOverlap,// pointer to structure needed for overlapped I/O
NULL);
WaitForSingleObject(PollingOverlap.hEvent,INFINITE);
// if(result)
// {
offset = 0;
int rename = 0;
char oldName[260];
char newName[260];
do
{
//pNotify = (FILE_NOTIFY_INFORMATION*)((char*)buf + offset);
strcpy(filename, "");
int filenamelen = WideCharToMultiByte(CP_ACP, 0, pNotify[offset].FileName, pNotify[offset].FileNameLength/2, filename, sizeof(filename), NULL, NULL);
//filename[pNotify->FileNameLength/2] = ' ';
switch(pNotify[offset].Action)
{
case FILE_ACTION_ADDED:
qDebug() << "The FILE_ACTION_ADDED***********" << QString(filename).left(filenamelen);
emit onFileCopy(QString(filename).left(filenamelen));
break;
case FILE_ACTION_MODIFIED:
qDebug() << "The FILE_ACTION_MODIFIED" << QString(filename).left(filenamelen);
break;
case FILE_ACTION_REMOVED:
qDebug() << "The FILE_ACTION_REMOVED" << QString(filename).left(filenamelen);
emit onFileRemove(QString(filename).left(filenamelen));
break;
case FILE_ACTION_RENAMED_OLD_NAME:
qDebug() << "The FILE_ACTION_RENAMED_OLD_NAME" << QString(filename).left(filenamelen);
break;
case FILE_ACTION_RENAMED_NEW_NAME:
newDirName = QString(filename).left(filenamelen);
qDebug() << "The FILE_ACTION_RENAMED_NEW_NAME" << newDirName;
emit onDirRename(newDirName);
break;
default:
printf("\nDefault error.\n");
break;
}
//qDebug() << "pNotify->NextEntryOffset" << pNotify[offset].NextEntryOffset <<" offset "<< offset << nRet ;
offset += pNotify[offset].NextEntryOffset;
}while(pNotify[offset].NextEntryOffset); //(offset != 0)
ResetEvent(PollingOverlap.hEvent);
}
CloseHandle( DirInfo[0].hDir );
}
public:
signals:
void onDirRename(QString Dir);
void onFileRemove(QString name);
void onFileCopy(QString name);
private:
LPCWSTR path;
typedef struct _DIRECTORY_INFO {
HANDLE hDir;
TCHAR lpszDirName[MAX_PATH];
CHAR lpBuffer[MAX_BUFFER];
DWORD dwBufLength;
OVERLAPPED Overlapped;
}DIRECTORY_INFO, *PDIRECTORY_INFO, *LPDIRECTORY_INFO;
DIRECTORY_INFO DirInfo[MAX_DIRS];
TCHAR FileList[MAX_FILES*MAX_PATH];
DWORD numDirs;
};
It is a Qt based object. the path is the directory i will monitor and update any changes happens.

Possible to capture unhandled exception in win32 user application ? (setunhandledexceptionfilter())

I spent much time to capture unhandled exceptions in my process (win32) using API so called setunhandledexceptionfilter().
But I haven't captured exception when WER(Windows Error Report - which is well know for DR.watson) is showed.
Is impossible to catch all of exceptions without third-party in my APP?
I think that there is method for handling, but I don't get it.
I am not accustomed to Windows DEV environment. that's why I lost my mental in googling.
Below is my test-case in vc110(Visual Studio 2012).
chat test[65];
int main() {
// after attaching unhandled exception call-back using setunhandledexceptionfilter()
// die point (ACCESS_VIOLATION c0000005)
for (int k=0; k<1000000; k++)
test[k]=65;
My callback isn't called after WER(windows Error Report) occurs. It doesn't work as my intend.
*But strcpy(NULL, "TEST") which is okay (SUCCESS)*
Below is my source code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/stat.h>
#include <assert.h>
#include <process.h>
#include <direct.h>
#include <conio.h>
#include <time.h>
#include <Windows.h>
#include <tchar.h>
#include <dbghelp.h>
#include <stdio.h>
#include <crtdbg.h>
#include <WinBase.h>
#pragma comment ( lib, "dbghelp.lib" )
void CreateMiniDump( EXCEPTION_POINTERS* pep );
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
);
///////////////////////////////////////////////////////////////////////////////
// Minidump creation function
//
#if 0
LONG WINAPI lpTopLevelExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo);
#endif
void CreateMiniDump( EXCEPTION_POINTERS* pep )
{
time_t t;
struct tm *tinfo;
wchar_t dump_name[128];
HANDLE hFile;
time(&t);
tinfo = localtime(&t);
wcsftime(dump_name, 128, L"MiniDump[%Y%m%d][%H_%M_%S].dmp", tinfo);
// file format MiniDump[YYYYMMDD][HH_MM_SEC]
hFile = CreateFile(dump_name, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
if( ( hFile != NULL ) && ( hFile != INVALID_HANDLE_VALUE ) )
{
// Create the minidump
MINIDUMP_EXCEPTION_INFORMATION mdei;
MINIDUMP_CALLBACK_INFORMATION mci;
MINIDUMP_TYPE mdt;
BOOL rv;
mdei.ThreadId = GetCurrentThreadId();
mdei.ExceptionPointers = pep;
mdei.ClientPointers = FALSE;
mci.CallbackRoutine = (MINIDUMP_CALLBACK_ROUTINE)MyMiniDumpCallback;
mci.CallbackParam = 0;
mdt = (MINIDUMP_TYPE)(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory| MiniDumpWithThreadInfo);
rv = MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(),
hFile, mdt, (pep != 0) ? &mdei : 0, 0, &mci );
if( !rv )
_tprintf( _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError() );
else
_tprintf( _T("Minidump created.\n") );
// Close the file
CloseHandle( hFile );
}
else
{
_tprintf( _T("CreateFile failed. Error: %u \n"), GetLastError() );
}
}
///////////////////////////////////////////////////////////////////////////////
// Custom minidump callback
//
BOOL CALLBACK MyMiniDumpCallback(
PVOID pParam,
const PMINIDUMP_CALLBACK_INPUT pInput,
PMINIDUMP_CALLBACK_OUTPUT pOutput
)
{
BOOL bRet = FALSE;
// Check parameters
if( pInput == 0 )
return FALSE;
if( pOutput == 0 )
return FALSE;
// Process the callbacks
switch( pInput->CallbackType )
{
case IncludeModuleCallback:
{
// Include the module into the dump
bRet = TRUE;
}
break;
case IncludeThreadCallback:
{
// Include the thread into the dump
bRet = TRUE;
}
break;
case ModuleCallback:
{
// Does the module have ModuleReferencedByMemory flag set ?
if( !(pOutput->ModuleWriteFlags & ModuleReferencedByMemory) )
{
// No, it does not - exclude it
wprintf( L"Excluding module: %s \n", pInput->Module.FullPath );
pOutput->ModuleWriteFlags &= (~ModuleWriteModule);
}
bRet = TRUE;
}
break;
case ThreadCallback:
{
// Include all thread information into the minidump
bRet = TRUE;
}
break;
case ThreadExCallback:
{
// Include this information
bRet = TRUE;
}
break;
case MemoryCallback:
{
// We do not include any information here -> return FALSE
bRet = FALSE;
}
break;
case CancelCallback:
break;
}
return bRet;
}
LONG WINAPI exception_filter_func(EXCEPTION_POINTERS* pep)
{
if (pep == NULL) {
return EXCEPTION_EXECUTE_HANDLER;
}
if (pep->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) {
HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CreateMiniDump, pep, 0, NULL);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
} else {
CreateMiniDump(pep);
}
return EXCEPTION_EXECUTE_HANDLER;
}
char test[65];
int main(int argc, char **argv)
{
int k;
SetUnhandledExceptionFilter(exception_filter_func);
// exception occured (ACCESS_VIOLATION)
for (k=0; k<1000000; k++)
test[k]=65;
}

Resources