How to call original function after hotpatch - c++

I've written code to patch the "Sleep" function for example from Kernel32.dll. The patching works perfectly fine. The removal of the patch works perfectly fine. However, calling the original function does not work at all. It crashes badly.
#include <windows.h>
#include <iostream>
std::uint8_t* Patch(std::uint8_t* OrigFunc, std::uint8_t* HookFunc)
{
DWORD dwProtect = 0;
const static std::uint8_t jmp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
const static std::int8_t jmp_size = sizeof(jmp) / sizeof(std::uint8_t);
static std::uint8_t HookJump[jmp_size + 1] = {jmp_size};
VirtualProtect(OrigFunc, jmp_size, PAGE_EXECUTE_READWRITE, &dwProtect);
memcpy(&HookJump[1], OrigFunc, jmp_size);
memcpy(OrigFunc, jmp, jmp_size);
memcpy(OrigFunc + 1, &HookFunc, sizeof(void*));
VirtualProtect(OrigFunc, jmp_size, dwProtect, &dwProtect);
return HookJump;
}
void RemovePatch(std::uint8_t* OrigFunc, std::uint8_t* HookJump)
{
DWORD dwProtect = 0;
VirtualProtect(OrigFunc, HookJump[0], PAGE_EXECUTE_READWRITE, &dwProtect);
memcpy(OrigFunc, &HookJump[1], HookJump[0]);
VirtualProtect(OrigFunc, HookJump[0], dwProtect, &dwProtect);
}
typedef void (__stdcall *pSleep)(DWORD);
pSleep oSleep;
void __stdcall hSleep(DWORD MS)
{
std::cout<<"HERE";
oSleep(MS); //Crashes Here.
}
int main()
{
std::uint8_t* OrigFunc = (std::uint8_t*)GetProcAddress(GetModuleHandle("kernel32.dll"), "Sleep");
std::uint8_t* HookFunc = (std::uint8_t*)hSleep;
std::uint8_t* HookJump = Patch(OrigFunc, HookFunc); //Works fine.
oSleep = (pSleep)&HookJump[1];
Sleep(1000); //Prints Here then crashes immediately.
RemovePatch(OrigFunc, HookJump); //Works fine.
Sleep(1000); //Works fine.
}
Any ideas what my code is missing?

In the given code it appears that you store original bytes in a static array called HookJump, return a pointer to that array, then jump to the start of it as if it were valid machine code. It's not followed by the rest of the original function.
A better way to hook functions in Windows is to use Microsoft Detours.
Here's my (working sketch of a) Hook class, using Detours:
[Hook.h]
#pragma once
// Copyright (c) 2013 Alf P. Steinbach
#include <rfc/cppx/core/Non_copyable.h> // cppx::Non_copyable
#include <rfc/cppx/core/macros/ASSERT.h> // CPPX_ASSERT
#include <rfc/detours/Transaction.h> // detours::Transaction
namespace detours {
using cppx::Non_copyable;
template< class Func >
class Hook_
: public Non_copyable
{
private:
Func* original_;
Func* replacement_;
public:
auto original_func() const
-> Func*
{ return original_; }
~Hook_()
{
if( original_ != nullptr )
{
Transaction().detach( original_, replacement_ ).commit();
}
}
Hook_( Func* const original, Func* const replacement )
: original_( original )
, replacement_( replacement )
{
CPPX_ASSERT( original_ != nullptr );
CPPX_ASSERT( replacement_ != nullptr );
Transaction().attach( original_, replacement_ ).commit();
}
Hook_( Hook_&& other )
: original_( other.original_ )
, replacement_( other.replacement_ )
{ other.original_ = nullptr; other.replacement_ = nullptr; }
};
template< class Func >
inline auto hook( Func* const original, Func* const replacement )
-> Hook_<Func>
{ return Hook_<Func>( original, replacement ); }
} // namespace detours
And here's the Transaction class that it uses, which in turn calls the Detours API:
[Transaction.h]
#pragma once
// Copyright (c) 2013 Alf P. Steinbach
#include <rfc/cppx/core/utility/If_.h> // cppx::If
#include <rfc/cppx/core/Non_copyable.h> // cppx::Non_copyable
#include <rfc/cppx/core/Type_.h> // cppx::Type_
#include <thread> // std::thread
#include <type_traits> // std::is_function, std::enable_if
namespace detours {
using cppx::If_;
using cppx::Non_copyable;
using cppx::Type_;
using std::is_function;
using std::thread;
typedef thread::native_handle_type Thread_handle;
class Basic_transaction
: public Non_copyable
{
private:
typedef Type_<void(*)()> Proc;
bool is_committed_;
void raw_attach( Proc& original, Proc const replacement );
void raw_detach( Proc& original, Proc const replacement );
public:
auto is_committed() const
-> bool;
void commit();
auto update_thread( Thread_handle const h )
-> Basic_transaction&;
auto update_this_thread()
-> Basic_transaction&;
template< class Func, class Enabled = If_<is_function<Func>> >
auto attach( Func*& original, Func* const replacement )
-> Basic_transaction&
{
raw_attach(
reinterpret_cast<Proc&>( original ),
reinterpret_cast<Proc>( replacement )
);
return *this;
}
template< class Func, class Enabled = If_<is_function<Func>> >
auto detach( Func*& original, Func* const replacement )
-> Basic_transaction&
{
raw_detach(
reinterpret_cast<Proc&>( original ),
reinterpret_cast<Proc>( replacement )
);
return *this;
}
~Basic_transaction();
Basic_transaction();
};
class Transaction
: public Basic_transaction
{
public:
Transaction()
{ update_this_thread(); }
};
} // namespace detours
[Transaction.cpp]
#include "Transaction.h"
#include <rfc/cppx/core/throwing.h>
#include <rfc/cppx/core/macros/ASSERT.h> // CPPX_ASSERT
#include <rfc/detours_wrappers/detours_h.h>
using cppx::hopefully;
using cppx::fail;
typedef long Error_code;
namespace detours{
auto Basic_transaction::is_committed() const
-> bool
{ return is_committed_; }
void Basic_transaction::commit()
{
CPPX_ASSERT( !is_committed_ );
Error_code const code = ::DetourTransactionCommit();
hopefully( code == 0 )
|| fail( "Basic_transaction::commit: DetourTransactionCommit failed", code );
is_committed_ = true;
}
auto Basic_transaction::update_thread( Thread_handle const h )
-> Basic_transaction&
{
Error_code const code = ::DetourUpdateThread( reinterpret_cast<HANDLE>( h ) );
hopefully(code == 0)
|| fail("Transaction::update_thread: DetourUpdateThread failed", code);
return *this;
}
auto Basic_transaction::update_this_thread()
-> Basic_transaction&
{
return update_thread( Thread_handle( ::GetCurrentThread() ) );
}
void Basic_transaction::raw_attach( Proc& original, Proc const replacement )
{
Error_code const code = ::DetourAttach(
reinterpret_cast<void**>( &original ),
reinterpret_cast<void*>( replacement )
);
hopefully(code == 0)
|| fail("Transaction::attach: DetourAttach failed", code);
}
void Basic_transaction::raw_detach( Proc& original, Proc const replacement )
{
Error_code const code = ::DetourDetach(
reinterpret_cast<void**>( &original ),
reinterpret_cast<void*>( replacement )
);
hopefully(code == 0)
|| fail("Transaction::attach: DetourAttach failed", code);
}
Basic_transaction::~Basic_transaction()
{
if (!is_committed_)
{
Error_code const code = ::DetourTransactionAbort();
hopefully( code == 0 )
|| fail( "Basic_transaction::<destroy>: DetourTransactionAbort failed", code );
}
}
Basic_transaction::Basic_transaction()
: is_committed_( false )
{
Error_code const code = ::DetourTransactionBegin();
hopefully( code == 0 )
|| fail( "Basic_transaction::<init>: DetourTransactionBegin failed", code );
}
} // namespace detours
The Detours wrapper header:
[detours.h]
#pragma once
#include <rfc/winapi_wrappers/windows_h.h>
#include <microsoft_detours/detours.h>
I then use a cpp file to bring in a specific Detours implementation, e.g. for x86:
[detours_cpp.x86-32.cpp]
// Copyright (c) 2013 Alf P. Steinbach
#define DETOURS_INTERNAL // Necessary for DETOUR_TRACE
#include <rfc/detours_wrappers/detours_h.h>
#define DETOURS_X86
#define DETOURS_32BIT
#include <microsoft_detours/detours.cpp> // Source
#include <microsoft_detours/disasm.cpp> // More source, e.g. DetourCopyInstruction

Related

How to avoid using exceptions, as a form of control flow, to jump through through deeply nested function calls?

I've currently been using custom exceptions to achieve the goal of jumping through deeply nested function calls, to get to a specific function in the call chain. For example, consider the following code:
#include <iostream>
struct label {};
void B();
void C();
void D();
void A() {
return B();
}
void B() { // I want to jump to the level of the B function in the call-chain.
try {
return C();
}
catch(const label& e) {
std::cout << "jumped to b function" << std::endl;
}
}
void C() {
return D();
}
void D() {
throw label();
}
int main() {
A();
return 0;
}
Note however that the above example is extremely contrived, and is simply for illustration purposes. In my actual code, I'm using this technique in a recursive-decent parser to recover from syntactical errors. Also note that I'm not using exceptions to jump around to different functions, like a glorified goto. I'm using the custom exception to always jump to one specific function near the top of the call chain.
The above code does work fine, but reading some of the top posts on the question Are exceptions as control flow considered a serious antipattern? If so, Why? (on the Software Engineering site), suggested that using exceptions in such a manner as the above scenario does, is consider an anti-pattern, and there are usually better was to accomplish one's goal.
Is my usage of a custom exception above appropriate? If not, what is a more reasonable way to accomplish my goal while avoiding using exactions as a form control flow? (Also, although I tagged this question as c++ since that's what I'm writing my parser in, I suppose this is a more language-agnostic question.)
Part 1: - Nested Function Stack Calls With Exceptions.
This may not fit your particular or exact needs, however I'm willing to share this example as I think that it may provide some insight and that it is related to your current situation.
I have a set of classes that are integrated together that handle multiple common tasks. The following set of classes include BlockProcess, BlockThread, FileHandlers, ExceptionHandler, Logger and a Utility class. There are several files here and please keep in mind that this light weight project is targeted towards Windows and that I am using Visual Studio 2017 with pre compiled headers.
I'm sure one can strip out any windows dependent code easily and replace with their equivalent system, architecture & environment includes and functionality.
I am also using a namespace called demo that wraps all the classes & functions in this small project; any user should replace this namespace with their own namespace name.
The main purpose of this is the design process of how I typically handle exceptions when the stack calls are nested quite deep.
These sets of classes not only allow control of Logging information, warnings & errors to the console with different settings for different types of messages, but also gives the ability to log the contents to a file.
This type of construct is very handy and versatile while being in the process of developing 3D Graphics Applications which can become very intense in their code base.
I can not take full credit for this code as a majority of this was inspired and designed by Marek A. Krzeminski, MASc which can be seen here yet I believe that it is the concepts and the use of this code that is important.
Main Entry Point:
main.cpp
#include "stdafx.h"
#include "BlockProcess.h"
#include "Logger.h"
#include "Utility.h"
//struct label {}; // Instead of throwing this struct in D() I'm throwing the ExceptionHandler
void B();
void C();
void D();
void A() {
return B();
}
void B() {
using namespace demo;
try {
return C();
} catch ( ... ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " failed for some reason.";
Logger::log( strStream, Logger::TYPE_INFO );
Logger::log( strStream, Logger::TYPE_WARNING );
Logger::log( strStream, Logger::TYPE_ERROR );
Logger::log( strStream, Logger::TYPE_CONSOLE );
}
}
void C() {
return D();
}
void D() {
using namespace demo;
std::ostringstream strStream;
strStream << __FUNCTION__ << " failed for some reason.";
throw ExceptionHandler( strStream ); // By Default will log to file; otherwise pass false for second param.
}
int _tmain( int iNumArgs, _TCHAR* pArugmentText[] ) {
using namespace demo;
try {
Logger log( "logger.txt" );
A();
// Prevent Multiple Start Ups Of This Application
BlockProcess processBlock( "ExceptionManager.exe" );
if ( processBlock.isBlocked() ) {
std::ostringstream strStream;
strStream << "ExceptionManager is already running in another window." << std::endl;
throw ExceptionHandler( strStream, false );
}
Utility::pressAnyKeyToQuit();
} catch ( ExceptionHandler& e ) {
std::cout << "Exception Thrown: " << e.getMessage() << std::endl;
Utility::pressAnyKeyToQuit();
return RETURN_ERROR;
} catch ( ... ) {
std::cout << __FUNCTION__ << " Caught Unknown Exception" << std::endl;
Utility::pressAnyKeyToQuit();
return RETURN_ERROR;
}
return RETURN_OK;
}
As you can see from the images above I was able to generate a log file of the info, warnings, errors etc., and if you look at the 2 consoles they were running simultaneously and the 2nd or lower cmd window is throwing the exception since I used the BlockProcess class to manage only a single instance of this running application. This is a very versatile design. The messages or thrown errors are being generated.
Now if you do not want execution to stop because of a specific value of a variable, the return of a function, if statement etc. instead of throwing an ExceptionHandler you can easily just create an ostringstream object, populate it with the needed iformation and you can pass that to Logger with the default option of saving to the Log file turned on or passing false as the last param. You can even set what type of message through the logger's types.
So to answer your question if this is anti-pattern? I honestly do not think it is if you carefully design your project and know where & when to throw messages.
ExceptionHandler:
ExceptionHandler.h
#ifndef EXCEPTION_HANDLER_H
#define EXCEPTION_HANDLER_H
namespace demo {
class ExceptionHandler final {
private:
std::string strMessage_;
public:
explicit ExceptionHandler( const std::string& strMessage, bool bSaveInLog = true );
explicit ExceptionHandler( const std::ostringstream& strStreamMessage, bool bSaveInLog = true );
~ExceptionHandler() = default;
ExceptionHandler( const ExceptionHandler& c ) = default;
const std::string& getMessage() const;
ExceptionHandler& operator=( const ExceptionHandler& c ) = delete;
};
} // namespace demo
#endif // !EXCEPTION_HANDLER_H
ExceptionHandler.cpp
#include "stdafx.h"
#include "ExceptionHandler.h"
#include "Logger.h"
namespace demo {
ExceptionHandler::ExceptionHandler( const std::string& strMessage, bool bSaveInLog ) :
strMessage_( strMessage ) {
if ( bSaveInLog ) {
Logger::log( strMessage_, Logger::TYPE_ERROR );
}
}
ExceptionHandler::ExceptionHandler( const std::ostringstream& strStreamMessage, bool bSaveInLog ) :
strMessage_( strStreamMessage.str() ) {
if ( bSaveInLog ) {
Logger::log( strMessage_, Logger::TYPE_ERROR );
}
}
const std::string& ExceptionHandler::getMessage() const {
return strMessage_;
}
} // namespace demo
Logger:
Logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include "Singleton.h"
namespace demo {
class Logger final : public Singleton {
public:
enum LoggerType {
TYPE_INFO = 0,
TYPE_WARNING,
TYPE_ERROR,
TYPE_CONSOLE,
}; // LoggerType
private:
std::string strLogFilename_;
unsigned uMaxCharacterLength_;
std::array<std::string, 4> aLogTypes_;
const std::string strUnknownLogType_;
HANDLE hConsoleOutput_;
WORD consoleDefaultColor_;
public:
explicit Logger( const std::string& strLogFilename );
virtual ~Logger();
static void log( const std::string& strText, LoggerType eLogType = TYPE_INFO );
static void log( const std::ostringstream& strStreamText, LoggerType eLogType = TYPE_INFO );
static void log( const char* szText, LoggerType eLogType = TYPE_INFO );
Logger( const Logger& c ) = delete;
Logger& operator=( const Logger& c ) = delete;
};
} // namespace demo
#endif // !LOGGER_H
Logger.cpp
#include "stdafx.h"
#include "Logger.h"
#include "BlockThread.h"
#include "TextFileWriter.h"
namespace demo {
static Logger* s_pLogger = nullptr;
static CRITICAL_SECTION s_criticalSection;
static const WORD WHITE_ON_RED = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY | BACKGROUND_RED; // White Text On Red Background
Logger::Logger( const std::string& strLogFilename ) :
Singleton( TYPE_LOGGER ),
strLogFilename_( strLogFilename ),
uMaxCharacterLength_( 0 ),
strUnknownLogType_( "UNKNOWN" ) {
// Oder must match types defined in Logger::Type enum
aLogTypes_[0] = "Info";
aLogTypes_[1] = "Warning";
aLogTypes_[2] = "Error";
aLogTypes_[3] = ""; // Console
// Find widest log type string
uMaxCharacterLength_ = strUnknownLogType_.size();
for each ( const std::string& strLogType in aLogTypes_ ) {
if ( uMaxCharacterLength_ < strLogType.size() ) {
uMaxCharacterLength_ = strLogType.size();
}
}
InitializeCriticalSection( &s_criticalSection );
BlockThread blockThread( s_criticalSection ); // Enter critical section
// Start log file
TextFileWriter file( strLogFilename_, false, false );
// Prepare console
hConsoleOutput_ = GetStdHandle( STD_OUTPUT_HANDLE );
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
GetConsoleScreenBufferInfo( hConsoleOutput_, &consoleInfo );
consoleDefaultColor_ = consoleInfo.wAttributes;
s_pLogger = this;
logMemoryAllocation( true );
} // Logger()
Logger::~Logger() {
logMemoryAllocation( false );
s_pLogger = nullptr;
DeleteCriticalSection( &s_criticalSection );
} // ~Logger
void Logger::log( const std::string& strText, LoggerType eLogType ) {
log( strText.c_str(), eLogType );
}
void Logger::log( const std::ostringstream& strStreamText, LoggerType eLogType ) {
log( strStreamText.str().c_str(), eLogType );
}
void Logger::log( const char* szText, LoggerType eLogType ) {
if ( nullptr == s_pLogger ) {
std::cout << "Logger has not been initialized, can not log " << szText << std::endl;
return;
}
BlockThread blockThread( s_criticalSection ); // Enter critical section
std::ostringstream strStream;
// Default White Text On Red Background
WORD textColor = WHITE_ON_RED;
// Choose log type text string, display "UNKNOWN" if eLogType is out of range
strStream << std::setfill( ' ' ) << std::setw( s_pLogger->uMaxCharacterLength_ );
try {
if ( TYPE_CONSOLE != eLogType ) {
strStream << s_pLogger->aLogTypes_.at( eLogType );
}
if ( TYPE_WARNING == eLogType ) {
// Yellow
textColor = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN;
} else if ( TYPE_INFO == eLogType ) {
// Green
textColor = FOREGROUND_GREEN;
} else if ( TYPE_CONSOLE == eLogType ) {
// Cyan
textColor = FOREGROUND_GREEN | FOREGROUND_BLUE;
}
} catch ( ... ) {
strStream << s_pLogger->strUnknownLogType_;
}
// Date & Time
if ( TYPE_CONSOLE != eLogType ) {
SYSTEMTIME time;
GetLocalTime( &time );
strStream << " [" << time.wYear << "."
<< std::setfill( '0' ) << std::setw( 2 ) << time.wMonth << "."
<< std::setfill( '0' ) << std::setw( 2 ) << time.wDay << " "
<< std::setfill( ' ' ) << std::setw( 2 ) << time.wHour << ":"
<< std::setfill( '0' ) << std::setw( 2 ) << time.wMinute << ":"
<< std::setfill( '0' ) << std::setw( 2 ) << time.wSecond << "."
<< std::setfill( '0' ) << std::setw( 3 ) << time.wMilliseconds << "] ";
}
strStream << szText << std::endl;
// Log message
SetConsoleTextAttribute( s_pLogger->hConsoleOutput_, textColor );
std::cout << strStream.str();
// Save same message to file
try {
TextFileWriter file( s_pLogger->strLogFilename_, true, false );
file.write( strStream.str() );
} catch ( ... ) {
// Ignore, not saved in log file
std::cout << __FUNCTION__ << " failed to write to file: " << strStream.str() << std::endl;
}
// Reset to default color
SetConsoleTextAttribute( s_pLogger->hConsoleOutput_, s_pLogger->consoleDefaultColor_ );
}
} // namespace demo
Singleton.h
#ifndef SINGLETON_H
#define SINGLETON_H
namespace demo {
class Singleton {
public:
// Number of items in enum type must match the number of items and order of items stored in s_aSingletons
enum SingletonType {
TYPE_LOGGER = 0, // MUST BE FIRST!
}; // enum SingleType
private:
SingletonType eType_;
public:
Singleton( const Singleton& c ) = delete;
Singleton& operator=( const Singleton& c ) = delete;
virtual ~Singleton();
protected:
explicit Singleton( SingletonType eType );
void logMemoryAllocation( bool isAllocated ) const;
};
} // namespace demo
#endif // !SINGLETON_H
Singleton.cpp
#include "stdafx.h"
#include "Singleton.h"
#include "Logger.h"
namespace demo {
struct SingletonInfo {
const std::string strSingletonName;
bool isConstructed;
SingletonInfo( const std::string& strSingletonNameIn ) :
strSingletonName( strSingletonNameIn ),
isConstructed( false )
{}
};
// Order must match types defined in Singleton::SingletonType enum
static std::array<SingletonInfo, 1> s_aSingletons = { SingletonInfo( "Logger" ) };
Singleton::Singleton( SingletonType eType ) :
eType_( eType ) {
bool bSaveInLog = s_aSingletons.at( TYPE_LOGGER ).isConstructed;
try {
if ( !s_aSingletons.at( eType ).isConstructed ) {
// Test Initialize Order
for ( int i = 0; i < eType; ++i ) {
if ( !s_aSingletons.at( i ).isConstructed ) {
throw ExceptionHandler( s_aSingletons.at( i ).strSingletonName +
" must be constructed before constructing " +
s_aSingletons.at( eType ).strSingletonName,
bSaveInLog );
}
}
s_aSingletons.at( eType ).isConstructed = true;
} else {
throw ExceptionHandler( s_aSingletons.at( eType ).strSingletonName +
" can only be constructed once.",
bSaveInLog );
}
} catch ( std::exception& ) {
// eType is out of range
std::ostringstream strStream;
strStream << __FUNCTION__ << " Invalid Singleton Type specified: " << eType;
throw ExceptionHandler( strStream, bSaveInLog );
}
}
Singleton::~Singleton() {
s_aSingletons.at( eType_ ).isConstructed = false;
}
void Singleton::logMemoryAllocation( bool isAllocated ) const {
if ( isAllocated ) {
Logger::log( "Created " + s_aSingletons.at( eType_ ).strSingletonName );
} else {
Logger::log( "Destroyed " + s_aSingletons.at( eType_ ).strSingletonName );
}
}
} // namespace demo
For the reset of the project code see the 2nd provided answer: If you are looking to up-vote or accept please use this as the primary answer to vote upon, and please do not vote on the 2nd answer as it is only reference to this answer!
Part 2: - Nested Function Stack Calls With Exceptions.
Note: - Please do not VOTE on this answer please refer to the first answer as this is just a continuation for reference of pertaining classes!
You can find Part 1 here. I had to split this into 2 separate answers for I was about 2,000 characters above the max character limit of 30,000. I do apologize for any inconvenience. However one can not apply this ExceptionHandler without the provided classes.
FileHandlers:
FileHandler.h
#ifndef FILE_HANDLER_H
#define FILE_HANDLER_H
namespace demo {
class FileHandler {
protected:
std::fstream fileStream_;
std::string strFilePath_;
std::string strFilenameWithPath_;
private:
bool bSaveExceptionInLog_;
public:
virtual ~FileHandler();
FileHandler( const FileHandler& c ) = delete;
FileHandler& operator=( const FileHandler& c ) = delete;
protected:
FileHandler( const std::string& strFilename, bool bSaveExceptionInLog );
void throwError( const std::string& strMessage ) const;
void throwError( const std::ostringstream& strStreamMessage ) const;
bool getString( std::string& str, bool appendPath );
};
} // namespace demo
#endif // !FILE_HANDLER_H
FileHandler.cpp
#include "stdafx.h"
#include "FileHandler.h"
namespace demo {
FileHandler::FileHandler( const std::string& strFilename, bool bSaveExceptionInLog ) :
bSaveExceptionInLog_( bSaveExceptionInLog ),
strFilenameWithPath_( strFilename ) {
// Extract path info if it exists
std::string::size_type lastIndex = strFilename.find_last_of( "/\\" );
if ( lastIndex != std::string::npos ) {
strFilePath_ = strFilename.substr( 0, lastIndex );
}
if ( strFilename.empty() ) {
throw ExceptionHandler( __FUNCTION__ + std::string( " missing filename", bSaveExceptionInLog_ ) );
}
}
FileHandler::~FileHandler() {
if ( fileStream_.is_open() ) {
fileStream_.close();
}
}
void FileHandler::throwError( const std::string& strMessage ) const {
throw ExceptionHandler( "File [" + strFilenameWithPath_ + "] " + strMessage, bSaveExceptionInLog_ );
}
void FileHandler::throwError( const std::ostringstream& strStreamMessage ) const {
throwError( strStreamMessage.str() );
}
bool FileHandler::getString( std::string& str, bool appendPath ) {
fileStream_.read( &str[0], str.size() );
if ( fileStream_.fail() ) {
return false;
}
// Trim Right
str.erase( str.find_first_of( char( 0 ) ) );
if ( appendPath && !strFilePath_.empty() ) {
// Add path if one exists
str = strFilePath_ + "/" + str;
}
return true;
}
} // namespace demo
TextFileReader.h
#ifndef TEXT_FILE_READER_H
#define TEXT_FILE_READER_H
#include "FileHandler.h"
namespace demo {
class TextFileReader : public FileHandler {
public:
explicit TextFileReader( const std::string& strFilename );
virtual ~TextFileReader() = default;
std::string readAll() const;
bool readLine( std::string& strLine );
TextFileReader( const TextFileReader& c ) = delete;
TextFileReader& operator=( const TextFileReader& c ) = delete;
};
} // namespace demo
#endif // !TEXT_FILE_READER_H
TextFileReader.cpp
#include "stdafx.h"
#include "TextFileReader.h"
namespace demo {
TextFileReader::TextFileReader( const std::string& strFilename ) :
FileHandler( strFilename, true ) {
fileStream_.open( strFilenameWithPath_.c_str(), std::ios_base::in );
if ( !fileStream_.is_open() ) {
throwError( __FUNCTION__ + std::string( " can not open file for reading" ) );
}
}
std::string TextFileReader::readAll() const {
std::ostringstream strStream;
strStream << fileStream_.rdbuf();
return strStream.str();
}
bool TextFileReader::readLine( std::string& strLine ) {
if ( fileStream_.eof() ) {
return false;
}
std::getline( fileStream_, strLine );
return true;
}
} // namespace demo
TextFileWriter.h
#ifndef TEXT_FILE_WRITER_H
#define TEXT_FILE_WRITER_H
#include "FileHandler.h"
namespace demo {
class TextFileWriter : public FileHandler {
public:
explicit TextFileWriter( const std::string& strFilename, bool bAppendToFile, bool bSaveExceptionInLog = true );
virtual ~TextFileWriter() = default;
void write( const std::string& str );
TextFileWriter( const TextFileWriter& c ) = delete;
TextFileWriter& operator=( const TextFileWriter& c ) = delete;
};
} // namespace demo
#endif // !TEXT_FILE_WRITER_H
TextFileWriter.cpp
#include "stdafx.h"
#include "TextFileWriter.h"
namespace demo {
TextFileWriter::TextFileWriter( const std::string& strFilename, bool bAppendToFile, bool bSaveExceptionInLog ) :
FileHandler( strFilename, bSaveExceptionInLog ) {
fileStream_.open( strFilenameWithPath_.c_str(),
std::ios_base::out | (bAppendToFile ? std::ios_base::app : std::ios_base::trunc) );
if ( !fileStream_.is_open() ) {
throwError( __FUNCTION__ + std::string( " can not open file for writing" ) );
}
}
void TextFileWriter::write( const std::string& str ) {
fileStream_ << str;
}
} // namespace demo
Processes & Threads
BlockProcess.h
#ifndef BLOCK_PROCESS_H
#define BLOCK_PROCESS_H
namespace demo {
class BlockProcess final {
private:
HANDLE hMutex_;
public:
explicit BlockProcess( const std::string& strName );
~BlockProcess();
bool isBlocked() const;
BlockProcess( const BlockProcess& c ) = delete;
BlockProcess& operator=( const BlockProcess& c ) = delete;
};
} // namespace demo
#endif // !BLOCK_PROCESS_H
BlockProccess.cpp
#include "stdafx.h"
#include "BlockProcess.h"
namespace demo {
BlockProcess::BlockProcess( const std::string& strName ) {
hMutex_ = CreateMutex( nullptr, FALSE, strName.c_str() );
}
BlockProcess::~BlockProcess() {
CloseHandle( hMutex_ );
}
bool BlockProcess::isBlocked() const {
return (hMutex_ == nullptr || GetLastError() == ERROR_ALREADY_EXISTS);
}
} // namespace demo
BlockThread.h
#ifndef BLOCK_THREAD_H
#define BLOCK_THREAD_H
namespace demo {
class BlockThread final {
private:
CRITICAL_SECTION* pCriticalSection_;
public:
explicit BlockThread( CRITICAL_SECTION& criticalSection );
~BlockThread();
BlockThread( const BlockThread& c ) = delete;
BlockThread& operator=( const BlockThread& c ) = delete;
};
} // namespace demo
#endif // !BLOCK_THREAD_H
BlockThread.cpp
#include "stdafx.h"
#include "BlockThread.h"
namespace demo {
BlockThread::BlockThread( CRITICAL_SECTION& criticalSection ) {
pCriticalSection_ = &criticalSection;
EnterCriticalSection( pCriticalSection_ );
}
BlockThread::~BlockThread() {
LeaveCriticalSection( pCriticalSection_ );
}
} // namespace demo
Utilities:
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
namespace demo {
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string toUpper( const std::string& str );
static std::string toLower( const std::string& str );
static std::string trim( const std::string& str, const std::string elementsToTrim = " \t\n\r" );
static unsigned convertToUnsigned( const std::string& str );
static int convertToInt( const std::string& str );
static float convertToFloat( const std::string& str );
static std::vector<std::string> splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty = true );
Utility( const Utility& c ) = delete;
Utility& operator=( const Utility& c ) = delete;
private:
Utility(); // Private - Not A Class Object
template<typename T>
static bool stringToValue( const std::string& str, T* pValue, unsigned uNumValues );
template<typename T>
static T getValue( const std::string& str, std::size_t& remainder );
};
#include "Utility.inl"
} // namespace demo
#endif // !UTILITY_H
Utility.inl
template<typename T>
static bool Utility::stringToValue( const std::string& str, T* pValue, unsigned uNumValues ) {
int numCommas = std::count( str.begin(), str.end(), ',' );
if ( numCommas != uNumValues - 1 ) {
return false;
}
std::size_t remainder;
pValue[0] = getValue<T>( str, remainder );
if ( uNumValues == 1 ) {
if ( str.size() != remainder ) {
return false;
}
} else {
std::size_t offset = remainder;
if ( str.at( offset ) != ',' ) {
return false;
}
unsigned uLastIdx = uNumValues - 1;
for ( unsigned u = 1; u < uNumValues; ++u ) {
pValue[u] = getValue<T>( str.substr( ++offset ), remainder );
offset += remainder;
if ( (u < uLastIdx && str.at( offset ) != ',') ||
(u == uLastIdx && offset != str.size()) ) {
return false;
}
}
}
return true;
}
Utility.cpp
#include "stdafx.h"
#include "Utility.h"
namespace demo {
void Utility::pressAnyKeyToQuit() {
std::cout << "\nPress any key to quit." << std::endl;
_getch();
}
std::string Utility::toUpper( const std::string& str ) {
std::string result = str;
std::transform( str.begin(), str.end(), result.begin(), ::toupper );
return result;
}
std::string Utility::toLower( const std::string& str ) {
std::string result = str;
std::transform( str.begin(), str.end(), result.begin(), ::tolower );
return result;
}
std::string Utility::trim( const std::string& str, const std::string elementsToTrim ) {
std::basic_string<char>::size_type firstIndex = str.find_first_not_of( elementsToTrim );
if ( firstIndex == std::string::npos ) {
return std::string(); // Nothing Left
}
std::basic_string<char>::size_type lastIndex = str.find_last_not_of( elementsToTrim );
return str.substr( firstIndex, lastIndex - firstIndex + 1 );
}
template<>
float Utility::getValue( const std::string& str, std::size_t& remainder ) {
return std::stof( str, &remainder );
}
template<>
int Utility::getValue( const std::string& str, std::size_t& remainder ) {
return std::stoi( str, &remainder );
}
template<>
unsigned Utility::getValue( const std::string& str, std::size_t& remainder ) {
return std::stoul( str, &remainder );
}
unsigned Utility::convertToUnsigned( const std::string& str ) {
unsigned u = 0;
if ( !stringToValue( str, &u, 1 ) ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to unsigned";
throw strStream.str();
}
return u;
}
int Utility::convertToInt( const std::string& str ) {
int i = 0;
if ( !stringToValue( str, &i, 1 ) ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to int";
throw strStream.str();
}
return i;
}
float Utility::convertToFloat( const std::string& str ) {
float f = 0;
if ( !stringToValue( str, &f, 1 ) ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << " Bad conversion of [" << str << "] to float";
throw strStream.str();
}
return f;
}
std::vector<std::string> Utility::splitString( const std::string& strStringToSplit, const std::string& strDelimiter, const bool keepEmpty ) {
std::vector<std::string> vResult;
if ( strDelimiter.empty() ) {
vResult.push_back( strStringToSplit );
return vResult;
}
std::string::const_iterator itSubStrStart = strStringToSplit.begin(), itSubStrEnd;
while ( true ) {
itSubStrEnd = search( itSubStrStart, strStringToSplit.end(), strDelimiter.begin(), strDelimiter.end() );
std::string strTemp( itSubStrStart, itSubStrEnd );
if ( keepEmpty || !strTemp.empty() ) {
vResult.push_back( strTemp );
}
if ( itSubStrEnd == strStringToSplit.end() ) {
break;
}
itSubStrStart = itSubStrEnd + strDelimiter.size();
}
return vResult;
}
} // namespace demo
Precompiled Headers:
stdafx.h
#ifndef STDAFX_H
#define STDAFX_H
// Included files that typically will not change
// during the development process of this application.
// System - Architect Includes
#include <Windows.h>
#include <process.h>
//#include <mmsystem.h>
// Character & Basic IO
#include <conio.h> // for _getch()
#include <tchar.h>
//---------------------------------------------//
// Standard Library Includes
// Atomics, Regular Expressions, Localizations
#include <atomic> // C++11
#include <clocale>
//#include <codecvt> // C++11 // Deprecated in C++17
#include <locale>
#include <regex>
// Numerics & Numeric Limits
#include <climits>
#include <cfloat>
#include <cstdint> // C++11
#include <cinttypes> // C++11
#include <limits>
#include <cmath>
#include <complex>
#include <valarray>
#include <random> // C++11
#include <numeric>
#include <ratio> // C++11
#include <cfenv> // C++11
// Strings, Streams & IO
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <fstream>
// Thread Support
#include <thread> // C++11
#include <mutex> // C++11
#include <shared_mutex> // C++14
#include <future> // C++11
#include <condition_variable> // C++11
// Containers
#include <array> // C++11
#include <stack>
#include <list>
#include <forward_list> // C++11
#include <map>
#include <unordered_map> // C++11
#include <queue>
#include <deque>
#include <set>
#include <unordered_set> // C++11
#include <vector>
// Algorithms, Iterators
#include <algorithm> // Note* C++ 17 also has <execution>
#include <iterator>
// Dynamic Memory
#include <new>
#include <memory>
#include <scoped_allocator> // C++11
// Utilities
#include <bitset>
#include <ctime> // Compatability with C style time formarts
#include <chrono> // C++ 11 - C++ Time Utilities
#include <functional>
#include <initializer_list> // C++11
#include <memory>
#include <thread>
#include <typeinfo>
#include <typeindex> // C++11
#include <type_traits> // C++11
#include <tuple> // C++11
#include <utility>
// C++ 17
#include <any>
#include <filesystem>
#include <optional>
#include <string_view>
#include <variant>
// C++ 20
// #include <compare>
// #include <charconv>
// #include <syncstream>
// 3rd Party Library Includes Here.
// User-Application Specific commonly used non changing headers.
#include "ExceptionHandler.h"
namespace demo {
enum ReturnCode {
RETURN_OK = 0,
RETURN_ERROR = 1,
}; // ReturnCode
extern const unsigned INVALID_UNSIGNED;
extern const unsigned INVALID_UNSIGNED_SHORT;
} // namespace demo
#endif // !STDAFX_H
stdafx.cpp
#include "stdafx.h"
namespace demo {
const unsigned INVALID_UNSIGNED = static_cast<const unsigned>(-1);
const unsigned INVALID_UNSIGNED_SHORT = static_cast<const unsigned short>(-1);
} // namespace demo

Template for WinAPI functions

Is it possible to somehow create a template for WinAPI functions? For example, there are two similar functions (LookupPrivilegeName and LookupPrivilegeDisplayName), but with different set of parameters. I call both functions like this: the first call retrieves required buffer size, the second call returns desired value. If this is not possible, are there any alternative ways to make the code more compact?
You likely want something like:
template<typename CharT>
bool LookupPriviledgeDisplayName(CharT const *, CharT const *, DWORD *, std::basic_string<CharT> & strDisplayName);
template<>
bool LookupPriviledgeDisplayName<char>(char const * pszSystem, char const * pszName, DWORD * pdwLangID, std::basic_string <char> & strDisplayName)
{
DWORD dwLength = 0;
if(!LookupPrivilegeDisplayNameA(pszSystem, pszName, nullptr, &dwLength, pdwLangID))
return false;
std::vector<char> buffer(dwLength + 1);
if(!LookupPrivilegeDisplayNameA(pszSystem, pszName, &buffer[0], &dwLength, pdwLangID))
return false;
strDisplayName.assign(&buffer[0], &buffer[0] + dwLength);
return true;
}
template<>
bool LookupPriviledgeDisplayName<wchar_t>(wchar_t const * pszSystem, wchar_t const * pszName, DWORD * pdwLangID, std::basic_string <wchar_t> & strDisplayName)
{
DWORD dwLength = 0;
if(!LookupPrivilegeDisplayNameW(pszSystem, pszName, nullptr, &dwLength, pdwLangID))
return false;
std::vector<wchar_t> buffer(dwLength + 1);
if(!LookupPrivilegeDisplayNameW(pszSystem, pszName, &buffer[0], &dwLength, pdwLangID))
return false;
strDisplayName.assign(&buffer[0], &buffer[0] + dwLength);
return true;
}
Something like this. The main idea is to separate code by functionality avoiding duplication.
#include <memory>
#include <string>
#include <iostream>
#include <system_error>
#include <cassert>
// Error handler.
void
On_Error(const ::DWORD error_code)
{
throw ::std::system_error{static_cast<int>(error_code), ::std::system_category()};
}
// Error check.
void
Validate_LookupPrivilegeNameSuccess(const ::BOOL result, const bool expect_insufficient_buffer)
{
if(FALSE == result)
{
auto const error_code{::GetLastError()};
if((ERROR_INSUFFICIENT_BUFFER == error_code) && (!expect_insufficient_buffer))
{
On_Error(error_code);
}
}
}
enum class
t_PrivilegeNameCategoryId
{
name
, display_name
};
// Helper class calling WinAPI methods, checking input and output.
template<t_PrivilegeNameCategoryId> class
t_LookupPrivilegeNameImpl;
template<> class
t_LookupPrivilegeNameImpl<t_PrivilegeNameCategoryId::name> final
{
public: static ::std::size_t
Lookup(const ::LPCWSTR psz_system_name, ::LUID & luid, const ::LPWSTR p_buffer, ::DWORD buffer_capacity_items_count)
{
assert((0 == buffer_capacity_items_count) || (nullptr != p_buffer));
Validate_LookupPrivilegeNameSuccess
(
::LookupPrivilegeNameW
(
psz_system_name
, ::std::addressof(luid)
, p_buffer
, ::std::addressof(buffer_capacity_items_count)
)
, nullptr == p_buffer
);
return(buffer_capacity_items_count);
}
};
template<> class
t_LookupPrivilegeNameImpl<t_PrivilegeNameCategoryId::display_name> final
{
public: static ::std::size_t
Lookup(const ::LPCWSTR psz_system_name, const ::LPCWSTR psz_display_name, const ::LPWSTR p_buffer, ::DWORD buffer_capacity_items_count)
{
assert(psz_display_name);
assert(L'\0' != psz_display_name[0]);
assert((0 == buffer_capacity_items_count) || (nullptr != p_buffer));
::DWORD language_id{};
Validate_LookupPrivilegeNameSuccess
(
::LookupPrivilegeDisplayNameW
(
psz_system_name
, psz_display_name
, p_buffer
, ::std::addressof(buffer_capacity_items_count)
, ::std::addressof(language_id)
)
, nullptr == p_buffer
);
return(buffer_capacity_items_count);
}
};
// Lookup function implementing get size -> resize buffer -> get data algorithm.
template<t_PrivilegeNameCategoryId name_category_id, typename... TArgs> void
Lookup_PrivilegeName(::std::wstring & name, TArgs &&... args)
{
try
{
name.resize(t_LookupPrivilegeNameImpl<name_category_id>::Lookup(::std::forward<TArgs>(args)..., ::LPWSTR{}, ::DWORD{}));
t_LookupPrivilegeNameImpl<name_category_id>::Lookup(::std::forward<TArgs>(args)..., name.data(), static_cast<::DWORD>(name.size()));
if(name.empty() || (L'\0' != name.back()))
{
On_Error(ERROR_UNIDENTIFIED_ERROR);
}
name.pop_back();
}
catch(...)
{
name.clear();
throw;
}
}
int main()
{
::LPCWSTR psz_system_name{};
::LUID privilege_luid{5}; // a wild guess
::std::wstring privilege_name{};
Lookup_PrivilegeName<t_PrivilegeNameCategoryId::name>(privilege_name, psz_system_name, privilege_luid);
::std::wstring privilege_display_name{};
Lookup_PrivilegeName<t_PrivilegeNameCategoryId::display_name>(privilege_display_name, psz_system_name, privilege_name.c_str());
::std::wcout << privilege_name << L"\n" << privilege_display_name << ::std::endl;
return(0);
}
My Russian friend explained to me the limitations of templates. Instead of them, he suggested using functions with context switching. In my situation it will be something like this:
BOOL LookupData(DWORD context, PLUID luid, wstring input, wstring & output) {
BOOL status = TRUE;
DWORD buflen = 0, lang = 0;
switch (context) {
case 0: status = LookupPrivilegeName(NULL, luid, NULL, &buflen); break;
case 1: status = LookupPrivilegeDisplayName(NULL, input.c_str(), NULL, &buflen, &lang); break;
default: return FALSE;
}
if (!status && ERROR_INSUFFICIENT_BUFFER != GetLastError()) return status;
auto buffer = make_unique<wchar_t[]>(buflen);
switch (context) {
case 0: status = LookupPrivilegeName(NULL, luid, buffer.get(), &buflen); break;
case 1: status = LookupPrivilegeDispayName(NULL, input.c_str(), buffer.get(), &buflen, &lang); break;
}
if (!status) {
buf.release();
return status;
}
output = buf.get();
buf.release();
return status;
}
Now I can write in cycle after getting TOKEN_PRIVILEGES structures:
std::wstring name, desription;
if (!LookupData(0, tp->Privipeges[i].Luid, L"", name)) break;
if (!LookupData(1, NULL, name, description)) break;
std::wcout << name << L" - " << std::endl;
Of course, it's dirty trick but it works.

C++ Implementing SFML InputStream

I'm trying to implement a custom InputStream but I'm having trouble doing so.
I seem to be opening the zip file just fine, and the library I'm using (https://bitbucket.org/wbenny/ziplib/wiki/Home) automatically gives me an istream* to the
data.
Yet I keep failing when I try to load the image file texture with the stream through:
sf::Texture::loadFromStream(sf::InputStream)
Any ideas as to what I'm doing incorrectly?
sf::InputStream
sf::Texture::loadFromStream
Here's my implementation:
Header)
#include <ZipFile.h>
namespace lvn
{
class NStream : public sf::InputStream
{
private:
ZipArchiveEntry::Ptr m_entry;
std::shared_ptr<std::istream> m_File = nullptr;
std::string m_filename;
//bool m_file_is_open = false;
public:
static bool ReadTxtFile( std::string filepath, tstring& textbuffer );
NStream( std::string pathName="" );
virtual ~NStream();
bool isOpen() const;
bool open( std::string pathName );
void close();
virtual sf::Int64 read( void* data, sf::Int64 size );
virtual sf::Int64 seek( sf::Int64 position );
virtual sf::Int64 tell();
virtual sf::Int64 getSize();
};
}
CPP)
#include <ZipFile.h>
#include "NStream.h"
namespace lvn
{
NStream::NStream( std::string pathName )
//: m_File( 0x00 )
{
using namespace std;
open( pathName );
}
NStream::~NStream( )
{
close( );
}
bool NStream::isOpen( ) const
{
//return (m_File != 0x0);
return ( m_File != nullptr );
}
//Ex. Images//albert.png
bool NStream::open( std::string pathName )
{
using namespace std;
close( );
auto archive_name = pathName.substr( 0, pathName.find( "/" ) ) + (".vndat"); //need to add the archive extension to the name
ZipArchive::Ptr archive = ZipFile::Open( archive_name );
m_entry = archive->GetEntry( pathName );
if ( m_entry == nullptr )
return false;
m_File = make_shared<istream>( nullptr );
m_File->rdbuf( m_entry->GetDecompressionStream()->rdbuf() );
m_filename = pathName;
return isOpen( );
}
void NStream::close( )
{
m_File.reset( );
}
sf::Int64 NStream::read( void* data, sf::Int64 size )
{
if ( !isOpen( ) )
return -1;
auto posPrev = tell();
m_File->read( static_cast<char *>( data ), size );
auto cur = tell();
return tell() - posPrev;
}
sf::Int64 NStream::seek( sf::Int64 position )
{
if ( !isOpen( ) )
return -1;
m_File->seekg( position );
return tell( );
}
sf::Int64 NStream::tell( )
{
if ( !isOpen( ) )
return -1;
// istream returns the offset in bytes or -1 on error just like SFML wants.
return m_File->tellg( );
}
sf::Int64 NStream::getSize( )
{
if ( !isOpen( ) )
return -1;
//get length of file (by seeking to end), then restore original offset
const auto originalIdx = tell( );
m_File->seekg( 0, m_File->end );
const sf::Int64 length = tell( );
seek( originalIdx );
// tell returns length of file or -1 on error just like SFML wants.
return length;
}
}
Example usage (should work but doesn't: loadFromStream fails):
auto pTextureStream = make_shared<NStream>();
pTextureStream->open( "Images/image.png" );
auto pTexture = make_shared<sf::Texture>();
pTexture->loadFromStream( *pTextureStream );
This is my implementation, I hope you find it useful
class StreamSFML : public sf::InputStream
{
std::shared_ptr<std::istream> m_source;
public:
explicit StreamSFML(std::shared_ptr<std::istream> stream) : m_source(stream) {}
sf::Int64 read(void* data, sf::Int64 size) override
{
m_source->read(static_cast<char*>(data), size);
return m_source->gcount();
}
sf::Int64 seek(sf::Int64 position) override
{
m_source->seekg(position, m_source->beg);
return m_source->gcount();
}
sf::Int64 tell() override
{
return m_source->tellg();
}
sf::Int64 getSize() override
{
auto curr = m_source->tellg();
m_source->seekg(0, m_source->end);
sf::Int64 pos = static_cast<sf::Int64>(m_source->tellg());
m_source->seekg(curr, m_source->beg);
return pos;
}
};

how can I design a RAII file descriptor without creating a new int

I want to create a RAII wrapper around a file descriptor. As the object might be passed around threads, it really is a shared resource: this is why I made a first implementation by using a shared_ptr with a custom destructor.
struct file_descriptor
{
file_descriptor( const std::string & pathname, int flags )
:m_fd( initialize( pathname, flags ) )
{
}
file_descriptor( const int opened_fd )
:m_fd( initialize( opened_fd ) )
{
}
operator int() const { return *m_fd; }
private:
std::shared_ptr<int> initialize( const int opened_fd )
{
std::shared_ptr<int> ptr_to_fd;
try
{
int * shared_fd = new int;
ptr_to_fd = std::shared_ptr<int>( shared_fd, file_descriptor_closer() );
*shared_fd = opened_fd;
}
catch( std::bad_alloc & )
{
close( opened_fd );
throw;
}
return ptr_to_fd;
}
std::shared_ptr<int> initialize( const std::string & pathname, int flags )
{
const int fd = open( pathname.c_str(), flags );
if (fd < 0)
throw std::system_error( std::error_code(errno, std::system_category() ), "cannot create file descriptor" );
return initialize( fd );
}
std::shared_ptr<int> m_fd;
};
The custom destructor, is pretty simple:
struct file_descriptor_closer
{
void operator()(int * const fd) noexcept { if (fd) close(*fd); delete fd; }
};
Now I find the design horrible, namely because of the "new int". I thought about making a custom allocator to point to an already-allocated block, but that seems overkill. Do you guys have suggestion to simplify this?
IMHO, you're mixing responsibilities. Let your RAII class deal with the opening and closing of the file descriptor. Let some other class deal with the lifetime question of your RAII class. As you have it now, the user of your file_descriptor class would need to know that it is using a shared_ptr internally. On first glance, if I were to share a file_descriptor between threads, I'd be making a shared_ptr<file_descriptor> of my own to counter the problem that I don't really know that internally it's already doing one.
use some gentle violence:
struct file_descriptor_closer
{
void operator()(void* fd) noexcept { if (fd) close(reinterpret_cast< int >(fd)); }
};
struct file_descriptor
{
file_descriptor( const std::string & pathname, int flags )
:m_fd( initialize( pathname, flags ) )
{
}
file_descriptor( const int opened_fd )
:m_fd( initialize( opened_fd ) )
{
}
operator int() const { return reinterpret_cast< int >(m_fd.get()); }
private:
std::shared_ptr<void> initialize( const int opened_fd )
{
try
{
return std::shared_ptr< void >( reinterpret_cast< void* >( opened_fd ), file_descriptor_closer() );
}
catch( std::bad_alloc & )
{
close( opened_fd );
throw;
}
}
std::shared_ptr<void> initialize( const std::string & pathname, int flags )
{
const int fd = open( pathname.c_str(), flags );
if (fd < 0)
throw std::system_error( std::error_code(errno, std::system_category() ), "cannot create file descriptor" );
return initialize( fd );
}
std::shared_ptr<void> m_fd;
};
Why not create your own container? What about something like: http://ideone.com/m3kmaJ or with static counter: http://ideone.com/Gs4Kb7
#include <iostream>
#include <sys/stat.h>
#include <fcntl.h>
#include <thread>
#include <memory>
#include <unistd.h>
#include <atomic>
class FD
{
private:
int fd;
static int count;
public:
FD(const char* FilePath, int flags) : fd(open(FilePath, flags)) {++FD::count;}
FD(const FD& other) : fd(other.fd) {++FD::count;}
FD(FD&& other) : fd(other.fd) { other.fd = -1; }
~FD()
{
FD::count -= 1;
if (FD::count == 0)
{
std::cout<<"Destroyed\n";
if (is_open())
close(fd);
}
}
bool is_open() {return fd != -1;}
FD* operator &() {return nullptr;}
operator int() {return fd;}
FD& operator = (FD other)
{
fd = other.fd;
FD::count += 1;
return *this;
}
FD& operator = (FD&& other)
{
fd = other.fd;
other.fd = -1;
return *this;
}
};
int FD::count = 0;
int main()
{
FD fd = FD("Unicode.cpp", O_RDONLY);
FD copy = fd;
FD cpy = FD(copy);
return 0;
}

Do not show console window in release but show in debug

I would like to create a program that will run in background as a final product. For debug purpose I want it to display a console.
I learned that there is a ShowWindow( hWnd, SW_HIDE ); function, but if I use it in a 'standard' main function the console window still pops up for a moment. I was trying to work it out like this (yes I know it's crappy):
#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <tchar.h>
#define DEBUG
//#undef DEBUG
#ifndef DEBUG
#pragma comment(linker, "/SUBSYSTEM:WINDOWS")
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd = GetConsoleWindow();
ShowWindow( hWnd, SW_HIDE );
while(1);
return 0;
}
#else
#pragma comment(linker, "/SUBSYSTEM:CONSOLE")
int main(int argc, int **argv)
{
HWND hWnd = GetConsoleWindow();
while(1);
return 0;
}
#endif
Here I managed to prevent the window form popping up, but I can't pass parameters to the program.
I believe there is a much better solution for this. Can you share?
PS
I don't want to use .NET.
This is an answer to the first part of the question, "Here I managed to prevent the window form popping up", i.e. how to set the Windows subsystem for an application in Visual C++.
I will answer the second part of the question, about command line arguments, separately.
// How to create a Windows GUI or console subsystem app with a standard `main`.
#ifndef _MSC_VER
# error Hey, this is Visual C++ specific source code!
#endif
// Better set this in the project settings, so that it's more easily configured.
#ifdef NDEBUG
# pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#else
# pragma comment( linker, "/subsystem:console" )
#endif
#undef UNICODE
#define UNICODE
#undef NOMINMAX
#define NOMINAX
#undef STRICT
#define STRICT
#include <windows.h>
int main()
{
MessageBox( 0, L"Hi!", L"This is the app!", MB_SETFOREGROUND );
}
The NDEBUG standard C++ macro is designed for suppressing the effect of standard assert, so it’s not required to be globally meaningful. However, in practice it is globally meaningful. And then it provides a bit of portability compared to using a Visual C++ macro such as DEBUG.
Anyway, in order to make it easier to configure the subsystem, unless you want to enforce that debug builds should be console and release builds should be GUI, then I recommend doing this in the project settings rather than via a #pragma (note also that e.g. the g++ compiler does not support linker pragmas, so using the project settings is more portable).
If you want you can check the subsystem programmatically instead of just by inspection (i.e. instead of noting whether the above program produces a console or not):
// How to create a Windows GUI or console subsystem app with a standard `main`.
#ifndef _MSC_VER
# error Hey, this is Visual C++ specific source code!
#endif
// Better set this in the project settings, so that it's more easily configured.
#ifdef NDEBUG
# pragma comment( linker, "/subsystem:windows /entry:mainCRTStartup" )
#else
# pragma comment( linker, "/subsystem:console" )
#endif
#undef UNICODE
#define UNICODE
#undef NOMINMAX
#define NOMINAX
#undef STRICT
#define STRICT
#include <windows.h>
#include <assert.h> // assert
#include <string> // std::wstring
#include <sstream> // std::wostringstream
using namespace std;
template< class Type >
wstring stringFrom( Type const& v )
{
wostringstream stream;
stream << v;
return stream.str();
}
class S
{
private:
wstring s_;
public:
template< class Type >
S& operator<<( Type const& v )
{
s_ += stringFrom( v );
return *this;
}
operator wstring const& () const { return s_; }
operator wchar_t const* () const { return s_.c_str(); }
};
IMAGE_NT_HEADERS const& imageHeaderRef()
{
HMODULE const hInstance =
GetModuleHandle( nullptr );
IMAGE_DOS_HEADER const* const pImageHeader =
reinterpret_cast< IMAGE_DOS_HEADER const* >( hInstance );
assert( pImageHeader->e_magic == IMAGE_DOS_SIGNATURE ); // "MZ"
IMAGE_NT_HEADERS const* const pNTHeaders = reinterpret_cast<IMAGE_NT_HEADERS const*>(
reinterpret_cast< char const* >( pImageHeader ) + pImageHeader->e_lfanew
);
assert( pNTHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC ); // "PE"
return *pNTHeaders;
}
int main()
{
IMAGE_NT_HEADERS const& imageHeader = imageHeaderRef();
WORD const subsystem = imageHeader.OptionalHeader.Subsystem;
MessageBox(
0,
S() << L"Subsystem " << subsystem << L" "
<< (0?0
: subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI? L"GUI"
: subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI? L"Console"
: L"Other"),
L"Subsystem info:",
MB_SETFOREGROUND );
}
You can still pass parameters to a regular, non-console Win32 program: they just show up in the single lpCmdLine string, all globbed together into one big command line. You can use CommandLineToArgvW to parse that into separate arguments, but do note that that function is only available in the Unicode flavor. For example:
int wmain(int argc, wchar_t **argv)
{
// Common main function (Unicode args)
}
#ifndef DEBUG
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
// Forward invocation to wmain
int argc;
LPWSTR *argv = CommandLineToArgvW(pCmdLine, &argc);
int status = wmain(argc, argv);
LocalFree(argv);
return status;
}
#endif
I'd also recommend using your project settings to set the executable's subsystem (console or Windows) depending on the configuration instead of using a #pragma to do it.
This is an answer to the second part of the question, “but I can't pass parameters to the program”, i.e. how to obtain the command line arguments in a Visual C++ Windows app.
The simplest but also most limited way is to use the arguments of a standard C++ main,
int main( int argc, char* argv[] )
{
// Whatever, e.g.
vector<string> const args( argv, argv + argc );
}
The C++ standard strongly suggests that those arguments should be encoded with some multi-byte character set such as UTF-8,
C++11 §3.6.1/2:
“If argc is nonzero these arguments shall be supplied in argv[0]
through argv[argc-1] as pointers to the initial characters of null-terminated multibyte strings (NTMBSs) (17.5.2.1.4.2) and argv[0] shall be the pointer to the initial character of a NTMBS that represents the name used to invoke the program or "".”
However, at the time of the first C++ standard, in 1998, neither the *nix world convention, nor the Windows convention, was to do this. Instead the convention was to pass the arguments with some locale-specific character encoding. The Linux world almost immediately started a migration towards UTF-8, while Windows did not, so that still as of 2012 in Windows the standard main arguments are not sufficient to pass e.g. arbitrary filenames…
Happily, in Windows the command line that’s passed to the process, and that is available via the GetCommandLine API function, is UTF-16 encoded, which means that any filename (and indeed any text) can be passed.
On the third hand, the API function that provides a standard parsing of the command line, CommandLineToArgvW, has at least one sillybug, and maybe more… And presumably the non-standard Visual C++ Unicode C++ startup function wmain has arguments provided by that function. So for best results, until that’s been fixed one should use some proper home-brewed command line parsing, e.g. as illustrated in the program below (I just picked an ad-hoc “personal tool” program I made last week, it’s similar to the Windows 2000 Resource Kit’s timethis):
// A program to measure the execution time of another program.
// Based vaguely on Jeffrey Richter's "timep" program in
// the 2nd edition of "Win32 System Programming".
//
// Author: Alf P. Steinbach, 2012. License: Boost license 1.0.
#undef UNICODE
#define UNICODE
#undef STRICT
#define STRICT
#undef NOMINMAX
#define NOMINMAX
#include <windows.h>
#include <shlwapi.h> // PathGetCharType
#include <assert.h> // assert
#include <functional> // std::function
#include <iomanip> // set::setfill, std::setw
#include <iostream> // std::wcout, std::endl
#include <sstream> // std::wostringstream
#include <stddef.h> // ptrdiff_t
#include <stdexcept> // std::runtime_error, std::exception
#include <stdint.h> // int64_t
#include <string> // std::string
#include <type_traits> // std::is_fundamental
#include <utility> // std::move
using namespace std;
#if !defined( CPP_STATIC_ASSERT )
# define CPP_STATIC_ASSERT( e ) static_assert( e, #e )
#endif
#if !defined( CPP_NORETURN )
# define CPP_NORETURN [[noreturn]]
#endif
// MSVC workaround: "#define CPP_NORETURN __declspec( noreturn )"
// clang workaround: "#define CPP_NORETURN __attribute__(( noreturn ))"
namespace cpp {
namespace detail {
template< class Destination, class Source >
class ImplicitCast
{
public:
static Destination value( Source const v )
{
return static_cast<Destination>( v );
}
};
template< class Source >
class ImplicitCast< bool, Source >
{
public:
static bool value( Source const v )
{
return !!v; // Shuts up Visual C++ sillywarning about performance.
}
};
};
template< class Destination, class Source >
Destination implicitCast( Source const v )
{
CPP_STATIC_ASSERT( is_fundamental< Destination >::value );
CPP_STATIC_ASSERT( is_fundamental< Source >::value );
return detail::ImplicitCast< Destination, Source >::value( v );
}
typedef ptrdiff_t Size;
inline bool hopefully( bool const c ) { return c; }
inline CPP_NORETURN bool throwX( string const& s )
{
throw runtime_error( s );
}
inline CPP_NORETURN bool throwX( string const& s, exception const& reasonX )
{
throwX( s + "\n!Because - " + reasonX.what() );
}
class ScopeGuard
{
private:
function<void()> cleanup_;
ScopeGuard( ScopeGuard const& ); // No such.
ScopeGuard& operator=( ScopeGuard const& ); // No such.
public:
~ScopeGuard() { cleanup_(); }
ScopeGuard( function<void()> const cleanup )
: cleanup_( cleanup )
{}
};
class SubstringRef
{
private:
wchar_t const* start_;
wchar_t const* end_;
public:
Size length() const { return end_ - start_; }
wchar_t const* start() const { return start_; }
wchar_t const* end() const { return end_; }
SubstringRef( wchar_t const* start, wchar_t const* end )
: start_( start )
, end_( end )
{}
};
inline void skipWhitespace( wchar_t const*& p )
{
while( *p != L'\0' && iswspace( *p ) ) { ++p; }
}
inline wchar_t const* theAfterWhitespacePart( wchar_t const* p )
{
skipWhitespace( p );
return p;
}
inline void invert( bool& b ) { b = !b; }
} // namespace cpp
namespace winapi {
using cpp::hopefully;
using cpp::invert;
using cpp::Size;
using cpp::skipWhitespace;
using cpp::SubstringRef;
using cpp::theAfterWhitespacePart;
using cpp::throwX;
namespace raw {
typedef DWORD DWord;
typedef FILETIME FileTime;
typedef HANDLE Handle;
typedef PROCESS_INFORMATION ProcessInformation;
typedef SYSTEMTIME SystemTime;
typedef WORD Word;
} // namespace raw
// The following logic is mainly a workaround for a bug in CommandLineToArgvW.
// See [http://preview.tinyurl.com/CommandLineToArgvWBug].
inline SubstringRef nextArgumentIn( wchar_t const* const commandLine )
{
wchar_t const* p = commandLine;
skipWhitespace( p );
wchar_t const* const start = p;
bool isInQuotedPart = false;
while( *p != L'\0' && (isInQuotedPart || !iswspace( *p ) ) )
{
if( *p == L'\"' ) { invert( isInQuotedPart ); }
++p;
}
return SubstringRef( start, p );
}
// This corresponds essentially to the argument of wWinMain(...).
inline wchar_t const* commandLineArgPart()
{
SubstringRef const programSpec = nextArgumentIn( GetCommandLine() );
return theAfterWhitespacePart( programSpec.end() );
}
class ProcessInfo
{
private:
raw::ProcessInformation info_;
ProcessInfo( ProcessInfo const& ); // No such.
ProcessInfo& operator=( ProcessInfo const& ); // No such.
public:
raw::ProcessInformation& raw() { return info_; }
raw::Handle handle() const { return info_.hProcess; }
~ProcessInfo()
{
::CloseHandle( info_.hThread );
::CloseHandle( info_.hProcess );
}
ProcessInfo(): info_() {}
ProcessInfo( ProcessInfo&& other )
: info_( move( other.info_ ) )
{
other.info_ = raw::ProcessInformation(); // Zero.
}
};
inline ProcessInfo createProcess( wchar_t const commandLine[] )
{
STARTUPINFO startupInfo = { sizeof( startupInfo ) };
ProcessInfo processInfo;
wstring mutableCommandLine( commandLine );
mutableCommandLine += L'\0';
GetStartupInfo( &startupInfo );
bool const creationSucceeded = !!CreateProcess (
nullptr, // LPCTSTR lpApplicationName,
&mutableCommandLine[0], // LPTSTR lpCommandLine,
nullptr, // LPSECURITY_ATTRIBUTES lpProcessAttributes,
nullptr, // LPSECURITY_ATTRIBUTES lpThreadAttributes,
true, // BOOL bInheritHandles,
NORMAL_PRIORITY_CLASS, // DWORD dwCreationFlags,
nullptr, // LPVOID lpEnvironment,
nullptr, // LPCTSTR lpCurrentDirectory,
&startupInfo, // LPSTARTUPINFO lpStartupInfo,
&processInfo.raw() // LPPROCESS_INFORMATION lpProcessInformation
);
hopefully( creationSucceeded )
|| throwX( "winapi::createProcess: CreateProcess failed" );
return processInfo;
}
inline raw::Handle dup(
raw::Handle const h,
raw::DWord const desiredAccess,
bool inheritable = false
)
{
raw::Handle result = 0;
bool const wasDuplicated = !!DuplicateHandle(
GetCurrentProcess(), h,
GetCurrentProcess(), &result,
desiredAccess,
inheritable,
0 // options
);
hopefully( wasDuplicated )
|| throwX( "winapi::dup: DuplicateHandle failed" );
assert( result != 0 );
return result;
}
inline int64_t mSecsFromRelative( raw::FileTime const t )
{
ULARGE_INTEGER asLargeInt;
asLargeInt.u.HighPart = t.dwHighDateTime;
asLargeInt.u.LowPart = t.dwLowDateTime;
return asLargeInt.QuadPart/10000;
}
SubstringRef filenamePart( SubstringRef const& path )
{
wchar_t const* p = path.end();
while( p != path.start() && PathGetCharType( *p ) != GCT_SEPARATOR )
{
--p;
}
if( PathGetCharType( *p ) == GCT_SEPARATOR ) { ++p; }
return SubstringRef( p, path.end() );
}
} // namespace winapi
winapi::ProcessInfo createProcess( wchar_t const commandLine[], char const errMsg[] )
{
try{ return winapi::createProcess( commandLine ); }
catch( exception const& x ) { cpp::throwX( errMsg, x ); }
}
winapi::raw::Handle run( wchar_t const commandLine[] )
{
namespace raw = winapi::raw;
using cpp::hopefully;
using cpp::throwX;
using winapi::dup;
using winapi::ProcessInfo;
static char const* const createErrMsg = "Failed to create process";
ProcessInfo const process = createProcess( commandLine, createErrMsg );
// Early handle duplication ensures that one has the required rights.
raw::Handle const accessibleHandle =
dup( process.handle(), PROCESS_QUERY_INFORMATION | SYNCHRONIZE );
raw::DWord const waitResult = WaitForSingleObject( process.handle(), INFINITE );
hopefully( waitResult == WAIT_OBJECT_0 )
|| throwX( "Failed waiting for process termination." );
return accessibleHandle;
}
class Interval
{
private:
int hours_;
int minutes_;
int seconds_;
int milliseconds_;
public:
int msecs() const { return milliseconds_; }
int seconds() const { return seconds_; }
int minutes() const { return minutes_; }
int hours() const { return hours_; }
Interval( int msecs, int seconds = 0, int minutes = 0, int hours = 0 )
: milliseconds_( msecs )
, seconds_( seconds )
, minutes_( minutes )
, hours_( hours )
{
assert( unsigned( hours ) < 24 );
assert( unsigned( minutes ) < 60 );
assert( unsigned( seconds ) < 60 );
assert( unsigned( msecs ) < 1000 );
}
static Interval fromMSecs( int msecs )
{
int const totalSeconds = msecs / 1000;
int const totalMinutes = totalSeconds / 60;
int const totalHours = totalMinutes / 24;
return Interval(
msecs % 1000, totalSeconds % 60, totalMinutes %60, totalHours
);
}
};
wostream& operator<<( wostream& stream, Interval const& t )
{
wostringstream formatter;
formatter << setfill( L'0' );
formatter
<< setw( 2 ) << t.hours() << ":"
<< setw( 2 ) << t.minutes() << ":"
<< setw( 2 ) << t.seconds() << "."
<< setw( 3 ) << t.msecs();
return (stream << formatter.str());
}
string narrowStringFrom( cpp::SubstringRef const& s )
{
return string( s.start(), s.end() ); // Non-ANSI characters => garbage.
}
void cppMain()
{
namespace raw = winapi::raw;
using cpp::hopefully;
using cpp::implicitCast;
using cpp::ScopeGuard;
using cpp::SubstringRef;
using cpp::throwX;
using winapi::commandLineArgPart;
using winapi::filenamePart;
using winapi::mSecsFromRelative;
using winapi::nextArgumentIn;
SubstringRef const programSpec = nextArgumentIn( GetCommandLine() );
SubstringRef const programName = filenamePart( programSpec );
wchar_t const* const otherCommandLine = commandLineArgPart();
hopefully( nextArgumentIn( otherCommandLine ).length() > 0 )
|| throwX( "Usage: " + narrowStringFrom( programName ) + " command" );
raw::DWord const startMSecs = GetTickCount();
raw::Handle const finishedProcess = run( otherCommandLine );
raw::DWord const endMSecs = GetTickCount();
raw::DWord const realElapsedMSecs = endMSecs - startMSecs;
ScopeGuard const closingHandle( [=]() { CloseHandle( finishedProcess ); } );
Interval const realElapsedTime = Interval::fromMSecs( realElapsedMSecs );
static char const* const commandLineLabel = "Command line: ";
static char const* const rElapsedTimeLabel = "External elapsed time: ";
static char const* const pElapsedTimeLabel = "In-process elapsed time: ";
static char const* const kernelTimeLabel = "In-process kernel time: ";
static char const* const userTimeLabel = "In-process user time: ";
wclog << endl;
wclog << commandLineLabel << "[" << otherCommandLine << "]" << endl;
wclog << rElapsedTimeLabel << realElapsedTime << endl;
raw::FileTime creationTime;
raw::FileTime exitTime;
raw::FileTime kernelTime;
raw::FileTime userTime;
bool const timesWereObtained = !!GetProcessTimes(
finishedProcess, &creationTime, &exitTime, &kernelTime, &userTime
);
hopefully( timesWereObtained )
|| throwX( "cppMain: GetProcessTimes failed" );
int const elapsedTimeMSecs= implicitCast<int>(
mSecsFromRelative( exitTime ) - mSecsFromRelative( creationTime )
);
int const kernelTimeMSecs = implicitCast<int>( mSecsFromRelative( kernelTime ) );
int const userTimeMSecs = implicitCast<int>( mSecsFromRelative( userTime ) );
wclog << pElapsedTimeLabel << Interval::fromMSecs( elapsedTimeMSecs ) << endl;
wclog << kernelTimeLabel << Interval::fromMSecs( kernelTimeMSecs ) << endl;
wclog << userTimeLabel << Interval::fromMSecs( userTimeMSecs ) << endl;
}
int main()
{
try
{
cppMain();
return EXIT_SUCCESS;
}
catch( exception const& x )
{
wcerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
Rather than changing your subsystem mode depending on the build type, consider using AllocConsole to explicitly create a console for your process.