Window manipulation using window-handle from different process on MS Windows(XP) - winapi

Is it possible to do some operations with a window from other process having it's handle? What I would like to do is:
-remove window decoration
-move window to any position of the screen
-let window stay on top without making it modal
A link to a command line tool, script or C/C++ code snippet be great.
Thank you very much!

I decided to take another shot, so I experimented with your code and added what was missing: a -naked option.
The key to remove the decoration came from here. Though it works, you will eventually find out that the application who got naked might start displaying a few bugs after it.
Enjoy:
#include "windows.h"
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <limits>
using namespace std;
#ifdef min
#undef min
#endif
int main(int argc, char* argv[])
{
char** param = argv;
unsigned int x = numeric_limits<int>::min(), y=numeric_limits<int>::min(), w=numeric_limits<int>::min(), h=numeric_limits<int>::min();
HWND z = HWND_NOTOPMOST;
unsigned int flags = (SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER);
++param;
wstring winTitle;
bool close = false;
bool naked = false;
while (*param)
{
string sparam(*param);
if (sparam == "-title")
{
++param;
if (!*param) break;
sparam = *param;
winTitle.resize(sparam.size());
copy(sparam.begin(), sparam.end(), winTitle.begin());
}
else if (sparam == "-move")
{
++param;
if (!*param) break;
sparam =*param;
stringstream sstr(sparam);
char sep;
sstr >> x >>sep >> y;
if (x != numeric_limits<int>::min() && y != numeric_limits<int>::min())
{
flags &= ~SWP_NOMOVE;
}
}
else if (sparam == "-resize")
{
++param;
if (!*param) break;
sparam = *param;
stringstream sstr(sparam);
char sep;
sstr >> w >>sep >> h;
if (h != numeric_limits<int>::min() && w != numeric_limits<int>::min() )
{
flags &= ~SWP_NOSIZE;
}
}
else if (sparam == "-top")
{
z = HWND_TOP;
flags &= ~SWP_NOZORDER;
}
else if (sparam == "-staytop")
{
z = HWND_TOPMOST;
flags &= ~SWP_NOZORDER;
}
else if (sparam == "-bottom")
{
z = HWND_BOTTOM;
flags &= ~SWP_NOZORDER;
}
else if (sparam == "-hide")
{
flags |= SWP_HIDEWINDOW;
}
else if (sparam == "-close")
{
close = true;
}
else if (sparam == "-naked")
{
naked = true;
}
++param;
}
if (winTitle.empty())
{
return -1;
}
HWND win_handle = FindWindow(0, winTitle.c_str());
if (win_handle != 0)
{
if (close)
{
TerminateProcess( (HANDLE )GetProcessId( win_handle ), 0);
return 0;
}
SetWindowPos( win_handle, z, x, y, w, h, flags );
if (naked)
{
SetWindowLong(win_handle, GWL_STYLE, GetWindowLong(win_handle, GWL_EXSTYLE) | WS_EX_TOPMOST);
ShowWindow(win_handle, SW_SHOW);
}
}
else
{
cout << "!!! FindWindow failed" << endl;
}
return 0;
}

Remove window decoration is a bit tricky. I guess you will probably have to set up a bounty for your question.
Check the Windows API to see what functions you should be calling.
Anyway, this snippet should get you started:
HWND win_handle = FindWindow (0, "Title Of The Window");
if (win_handle != 0)
{
/* Do your magic */
// MoveWindow params: handle, x=100, y=200, width=400, height=450, repaint
MoveWindow(win_handle, 100, 200, 400, 450, TRUE);
}
else
{
std::cout << "!!! FindWindow failed" << std::endl;
}

Finally, with the help of karlphillip I was able to write a tool that moves, resizes and sticks a window on top. What I am missing is how to remove decoration and close. Here is the code:
#include "windows.h"
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <limits>
using namespace std;
#ifdef min
#undef min
#endif
int main(int argc, char* argv[])
{
char **param= argv;
wstring winTitle;
bool close = false;
unsigned int x=numeric_limits<int>::min(), y=numeric_limits<int>::min(), w=numeric_limits<int>::min(), h=numeric_limits<int>::min();
HWND z=HWND_NOTOPMOST;
unsigned int flags=SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER;
++param;
while ( *param )
{
string sparam(*param);
if ( sparam == "-title" )
{
++param; if (!*param) break;
sparam =*param;
winTitle.resize(sparam.size());
copy (sparam.begin(), sparam.end(), winTitle.begin());
}
else if ( sparam == "-move" )
{
++param; if (!*param) break;
sparam =*param;
stringstream sstr( sparam );
char sep;
sstr >> x >>sep >> y;
if ( x != numeric_limits<int>::min() && y != numeric_limits<int>::min() )
{
flags &= ~SWP_NOMOVE;
}
}
else if ( sparam == "-resize" )
{
++param; if (!*param) break;
sparam =*param;
stringstream sstr( sparam );
char sep;
sstr >> w >>sep >> h;
if ( h != numeric_limits<int>::min() && w != numeric_limits<int>::min() )
{
flags &= ~SWP_NOSIZE;
}
}
else if ( sparam == "-top" )
{
z = HWND_TOP;
flags &= ~SWP_NOZORDER;
}
else if ( sparam == "-staytop" )
{
z = HWND_TOPMOST;
flags &= ~SWP_NOZORDER;
}
else if ( sparam == "-bottom" )
{
z = HWND_BOTTOM;
flags &= ~SWP_NOZORDER;
}
else if ( sparam == "-hide" )
{
flags |= SWP_HIDEWINDOW;
}
else if ( sparam == "-close" )
{
close=true;
}
++param;
}
if ( winTitle.empty() )
{
return 1;
}
HWND win_handle = FindWindow (0, winTitle.c_str());
if (win_handle != 0)
{
if(close)
{
TerminateProcess( (HANDLE )GetProcessId( win_handle ), 0 );
return 0;
}
SetWindowPos( win_handle, z, x, y, w, h, flags );
}
else
{
cout << "!!! FindWindow failed" << endl;
}
//system("pause");
return 0;
}

Related

Why does ReadProcessMemory fail so often with ERROR_PARTIAL_COPY?

The following program tries to scan read/write pages of a foreign application with ReadProcessMemory():
#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>
#include <sstream>
#include <cctype>
#include <fstream>
#include <cmath>
using namespace std;
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, DWORD dwMask );
using XHANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( h ); })>;
int main( int argc, char **argv )
{
if( argc < 2 )
return EXIT_FAILURE;
try
{
DWORD dwProcessId = [&]() -> DWORD
{
DWORD dwRet;
if( from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet ); fcr.ec != errc() || *fcr.ptr )
throw invalid_argument( "process-id unparseable" );
return dwRet;
}();
XHANDLE hProcess( [&]() -> HANDLE
{
HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if( !hRet )
throw system_error( (int)GetLastError(), system_category(), "can't open process" );
return hRet;
}() );
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( hProcess.get(), PAGE_READWRITE );
vector<char> processRegion;
size_t
succs = 0, partialErrs = 0, errs = 0,
total = 0, read = 0, skipped = 0;
for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
for( MEMORY_BASIC_INFORMATION const &vmbi : vmbi )
{
processRegion.resize( vmbi.RegionSize );
size_t actuallyRead;
bool succ = ReadProcessMemory( hProcess.get(), vmbi.BaseAddress, to_address( processRegion.begin() ), vmbi.RegionSize, &actuallyRead );
succs += succ;
partialErrs += !succ && GetLastError() == ERROR_PARTIAL_COPY;
errs += !succ;
bool bytesCopied = succ || GetLastError() == ERROR_PARTIAL_COPY;
actuallyRead = bytesCopied ? actuallyRead : 0;
total += processRegion.size(),
read += actuallyRead;
skipped += bytesCopied ? processRegion.size() - actuallyRead : processRegion.size();
}
cout << "successes: " << succs << endl;
cout << "partial errs: " << partialErrs << endl;
cout << "errs: " << errs << endl;
cout << "read: " << read << endl;
cout << "skipped: " << skipped;
auto pct = []( double a, double b ) -> double { return trunc( a / b * 1000.0 + 0.5 ) / 10.0; };
cout << " (" << pct( (double)(ptrdiff_t)skipped, (double)(ptrdiff_t)total ) << "%)" << endl;
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, DWORD dwMask )
{
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
{
if( !(mbi.AllocationProtect & dwMask) )
return true;
if( !vvmbis.size() || vvmbis.back().back().BaseAddress != mbi.BaseAddress )
vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
vvmbis.back().emplace_back( mbi );
return true;
} );
return vvmbis;
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
MEMORY_BASIC_INFORMATION mbi;
for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + mbi.RegionSize )
{
size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
if( nBytes != sizeof mbi )
if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
break;
else
throw system_error( (int)dwErr, system_category(), "can't query process pages" );
if( !fn( mbi ) )
break;
}
}
This is the result from scanning explorer.exe:
successes: 316
partial errs: 282
errs: 282
read: 139862016
skipped: 4452511744 (97%)
I.e. 316 copies from the foreign address space are successful, 282 are errors with partial reads, the same number are errors at all (i.e. all errors are partial reads), and the given number of bytes are read and skipped. The total memory that has skipped is 97%.
Why does ReadProcessMemory() fail so often, or what am I doing wrong here?
Remy was mostly right. Here's the corrected code with a filter-callback on pageTree instead of a protection mask.
#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>
#include <sstream>
#include <cctype>
#include <fstream>
#include <cmath>
using namespace std;
template<typename FilterFn>
requires requires( FilterFn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, FilterFn filterFn );
using XHANDLE = unique_ptr<void, decltype([]( HANDLE h ) { h && h != INVALID_HANDLE_VALUE && CloseHandle( h ); })>;
int main( int argc, char **argv )
{
if( argc < 2 )
return EXIT_FAILURE;
try
{
DWORD dwProcessId = [&]() -> DWORD
{
DWORD dwRet;
if( from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet ); fcr.ec != errc() || *fcr.ptr )
throw invalid_argument( "process-id unparseable" );
return dwRet;
}();
XHANDLE hProcess( [&]() -> HANDLE
{
HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if( !hRet )
throw system_error( (int)GetLastError(), system_category(), "can't open process" );
return hRet;
}() );
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( hProcess.get(),
[]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
{
return mbi.State == MEM_COMMIT;
} );
vector<char> processRegion;
size_t
succs = 0, partialErrs = 0, errs = 0,
total = 0, read = 0, skipped = 0;
for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
for( MEMORY_BASIC_INFORMATION const &vmbi : vmbi )
{
processRegion.resize( vmbi.RegionSize );
size_t actuallyRead;
bool succ = ReadProcessMemory( hProcess.get(), vmbi.BaseAddress, to_address( processRegion.begin() ), vmbi.RegionSize, &actuallyRead );
succs += succ;
partialErrs += !succ && GetLastError() == ERROR_PARTIAL_COPY;
errs += !succ;
bool bytesCopied = succ || GetLastError() == ERROR_PARTIAL_COPY;
actuallyRead = bytesCopied ? actuallyRead : 0;
total += processRegion.size(),
read += actuallyRead;
skipped += bytesCopied ? processRegion.size() - actuallyRead : processRegion.size();
}
cout << "successes: " << succs << endl;
cout << "partial errs: " << partialErrs << endl;
cout << "errs: " << errs << endl;
cout << "read: " << read << endl;
cout << "skipped: " << skipped;
auto pct = []( double a, double b ) -> double { return trunc( a / b * 1000.0 + 0.5 ) / 10.0; };
cout << " (" << pct( (double)(ptrdiff_t)skipped, (double)(ptrdiff_t)total ) << "%)" << endl;
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );
template<typename FilterFn>
requires requires( FilterFn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess, FilterFn filterFn )
{
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
{
if( !filterFn( mbi ) )
return true;
if( !vvmbis.size() || vvmbis.back().back().BaseAddress != mbi.BaseAddress )
vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
vvmbis.back().emplace_back( mbi );
return true;
} );
return vvmbis;
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
MEMORY_BASIC_INFORMATION mbi;
for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + mbi.RegionSize )
{
size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
if( nBytes != sizeof mbi )
if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
break;
else
throw system_error( (int)dwErr, system_category(), "can't query process pages" );
if( !fn( mbi ) )
break;
}
}
Unfortunately I still get about 6% skipped memory:
successes: 2159
partial errs: 225
errs: 225
read: 706748416
skipped: 42897408 (5.7%)
Why is that ?

VirtualQueryEx() returns mostly useless data

I've written a little program to query the page-map of a process:
#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <stdexcept>
using namespace std;
int main( int argc, char **argv )
{
if( argc < 2 )
return EXIT_FAILURE;
try
{
DWORD dwProcessId = [&]() -> DWORD
{
DWORD dwRet;
from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
if( fcr.ec != errc() || *fcr.ptr )
throw invalid_argument( "process-id unparseable" );
return dwRet;
}();
HANDLE hProcess = [&]() -> HANDLE
{
HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
if( !hRet )
throw system_error( (int)GetLastError(), system_category(), "can't open process" );
return hRet;
}();
size_t pageSize = []() -> size_t
{
SYSTEM_INFO si;
GetSystemInfo( &si );
return si.dwPageSize;
}();
using mbi_t = MEMORY_BASIC_INFORMATION;
vector<mbi_t> mbis( 0x100 );
size_t nRegions;
while( !(nRegions = VirtualQueryEx( hProcess, nullptr, to_address( mbis.begin() ), mbis.size() * sizeof(mbi_t) )) )
if( GetLastError() == ERROR_BAD_LENGTH )
mbis.resize( mbis.size() * 2 );
else
throw system_error( (int)GetLastError(), system_category(), "can't query process pages" );
mbis.resize( nRegions );
for( mbi_t const &mbi : mbis )
{
cout << "base address: " << hex << mbi.BaseAddress << endl;
cout << "allocation base: " << hex << mbi.AllocationBase << endl;
cout << dec << mbi.RegionSize / pageSize << " pages" << endl;
static struct
{
DWORD dwProtect;
char const *str;
} const protectMaps[] =
{
{ PAGE_EXECUTE, "PAGE_EXECUTE" },
{ PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
{ PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
{ PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
{ PAGE_NOACCESS, "PAGE_NOACCESS" },
{ PAGE_READONLY, "PAGE_READONLY" },
{ PAGE_READWRITE, "PAGE_READWRITE" },
{ PAGE_WRITECOPY, "PAGE_WRITECOPY" }
};
for( auto const &pm : protectMaps )
if( pm.dwProtect == mbi.AllocationProtect )
{
cout << "state: " << pm.str << endl;
break;
}
if( mbi.Type == MEM_IMAGE )
cout << "image";
else if( mbi.Type == MEM_MAPPED )
cout << "mapped";
else if( mbi.Type == MEM_PRIVATE )
cout << "private";
cout << endl << endl;
}
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}
Unfortunately the program returns mostly null-data except from the number of pages with the first entry, which is the number of logical pages of the process minus 32.
What am I doing wrong here ?
The process I tried to query runs under the same token, so there coudln't be any privilege issues.
Thank you Hans ! You were right. I thoughth VirtualQueryEx() fills just a number of MEMORY_BASIC_INFORMATION. If you don't see something obvious you say in Germany that you've got tomatoes on your eyes, and yes, I had tomatoes on my eyes (not because of my style ;-)).
Here's the working code:
#include <Windows.h>
#include <iostream>
#include <vector>
#include <charconv>
#include <cstring>
#include <vector>
#include <stdexcept>
using namespace std;
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess );
int main( int argc, char **argv )
{
if( argc < 2 )
return EXIT_FAILURE;
try
{
DWORD dwProcessId = [&]() -> DWORD
{
DWORD dwRet;
from_chars_result fcr = from_chars( argv[1], argv[1] + strlen( argv[1] ), dwRet );
if( fcr.ec != errc() || *fcr.ptr )
throw invalid_argument( "process-id unparseable" );
return dwRet;
}();
HANDLE hProcess = [&]() -> HANDLE
{
HANDLE hRet = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, dwProcessId );
if( !hRet )
throw system_error( (int)GetLastError(), system_category(), "can't open process" );
return hRet;
}();
size_t pageSize = []() -> size_t
{
SYSTEM_INFO si;
GetSystemInfo( &si );
return si.dwPageSize;
}();
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbi = pageTree( hProcess );
for( vector<MEMORY_BASIC_INFORMATION> const &vmbi : vvmbi )
{
cout << "allocation base: " << hex << vmbi.front().AllocationBase << endl;
for( MEMORY_BASIC_INFORMATION const &mbi : vmbi )
{
cout << "\tbase address: " << hex << mbi.BaseAddress << endl;
cout << "\t" << dec << mbi.RegionSize / pageSize << " pages" << endl;
static struct
{
DWORD dwProtect;
char const *str;
} const protectMaps[] =
{
{ PAGE_EXECUTE, "PAGE_EXECUTE" },
{ PAGE_EXECUTE_READ, "PAGE_EXECUTE_READ" },
{ PAGE_EXECUTE_READWRITE, "PAGE_EXECUTE_READWRITE" },
{ PAGE_EXECUTE_WRITECOPY, "PAGE_EXECUTE_WRITECOPY" },
{ PAGE_NOACCESS, "PAGE_NOACCESS" },
{ PAGE_READONLY, "PAGE_READONLY" },
{ PAGE_READWRITE, "PAGE_READWRITE" },
{ PAGE_WRITECOPY, "PAGE_WRITECOPY" }
};
for( auto const &pm : protectMaps )
if( pm.dwProtect == mbi.AllocationProtect )
{
cout << "\tstate: " << pm.str << endl;
break;
}
if( mbi.Type == MEM_IMAGE )
cout << "\timage" << endl;
else if( mbi.Type == MEM_MAPPED )
cout << "\tmapped" << endl;
else if( mbi.Type == MEM_PRIVATE )
cout << "\tprivate" << endl;
cout << endl;
}
}
}
catch( exception const &exc )
{
cout << exc.what() << endl;
}
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn );
vector<vector<MEMORY_BASIC_INFORMATION>> pageTree( HANDLE hProcess )
{
vector<vector<MEMORY_BASIC_INFORMATION>> vvmbis;
enumProcessMemory( hProcess, [&]( MEMORY_BASIC_INFORMATION &mbi ) -> bool
{
if( !vvmbis.size() || vvmbis.back().back().BaseAddress != mbi.BaseAddress )
vvmbis.emplace_back( vector<MEMORY_BASIC_INFORMATION>() );
vvmbis.back().emplace_back( mbi );
return true;
} );
return vvmbis;
}
template<typename Fn>
requires requires( Fn fn, MEMORY_BASIC_INFORMATION &mbi ) { { fn( mbi ) } -> std::convertible_to<bool>; }
void enumProcessMemory( HANDLE hProcess, Fn fn )
{
MEMORY_BASIC_INFORMATION mbi;
for( char *last = nullptr; ; last = (char *)mbi.BaseAddress + mbi.RegionSize )
{
size_t nBytes = VirtualQueryEx( hProcess, last, &mbi, sizeof mbi );
if( nBytes != sizeof mbi )
if( DWORD dwErr = GetLastError(); dwErr == ERROR_INVALID_PARAMETER )
break;
else
throw system_error( (int)dwErr, system_category(), "can't query process pages" );
if( !fn( mbi ) )
break;
}
}
The code now groups the allocation bases. Its segemented that parts can be extended without changing the framework.

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);
}
}
}

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;
}

Find out if UNC path is pointing to local machine

Is there any simple way to tell if UNC path points to a local machine.
I found the following question SO
Is there any WIN32 API that will do the same?
#include <windows.h>
#include <WinSock.h>
#include <string>
#include <algorithm>
#pragma comment(lib, "wsock32.lib")
using namespace std;
std::wstring ExtractHostName( const std::wstring &share )
{
if (share.size() < 3 )
return L"";
size_t pos = share.find( L"\\", 2 );
wstring server = ( pos != string::npos ) ? share.substr( 2, pos - 2 ) : share.substr( 2 );
transform( server.begin(),server.end(), server.begin(), tolower);
return server;
}
bool IsIP( const std::wstring &server )
{
size_t invalid = server.find_first_not_of( L"0123456789." );
bool fIsIP = ( invalid == string::npos );
return fIsIP;
}
bool IsLocalIP( const std::wstring &ipToCheck )
{
if ( ipToCheck == L"127.0.0.1" )
return true;
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 1, 1 );
if ( WSAStartup( wVersionRequested, &wsaData ) != 0 )
return false;
bool fIsLocal = false;
char hostName[255];
if( gethostname ( hostName, sizeof(hostName)) == 0 )
{
PHOSTENT hostinfo;
if(( hostinfo = gethostbyname(hostName)) != NULL )
{
for (int i = 0; hostinfo->h_addr_list[i]; i++)
{
char *ip = inet_ntoa(*( struct in_addr *)hostinfo->h_addr_list[i]);
wchar_t wcIP[100]={0};
::MultiByteToWideChar(CP_ACP, 0, ip, -1, wcIP, _countof(wcIP));
if (ipToCheck == wcIP)
{
fIsLocal = true;
break;
}
}
}
}
WSACleanup();
return fIsLocal;
}
bool IsLocalHost( const std::wstring &server )
{
if (server == L"localhost")
return true;
bool fIsLocalHost = false;
wchar_t buffer[MAX_PATH]={0};
DWORD dwSize = _countof(buffer);
BOOL fRet = GetComputerName( buffer, &dwSize );
transform( buffer, buffer + dwSize, buffer, tolower);
fIsLocalHost = ( server == buffer );
return fIsLocalHost;
}
bool ShareIsLocal( const std::wstring &share )
{
wstring server = ExtractHostName( share );
bool fIsIp = IsIP( server );
if ( fIsIp )
return IsLocalIP( server );
else
return IsLocalHost( server );
}

Resources