mirror of
https://github.com/polserver/polserver
synced 2026-08-13 08:23:08 -04:00
* Add exit_code to uo::Shutdown() Co-authored-by: Eric Swanson <eric.the.unicorn@gmail.com>
310 lines
7.5 KiB
C++
310 lines
7.5 KiB
C++
/** @file
|
|
*
|
|
* @par History
|
|
*/
|
|
|
|
|
|
#include "../clib/esignal.h"
|
|
#include "../clib/threadhelp.h"
|
|
//#include "../clib/xmain.h"
|
|
#include "../clib/logfacility.h"
|
|
|
|
#include "../plib/systemstate.h"
|
|
|
|
#include "polresource.h"
|
|
|
|
#include "../clib/Header_Windows.h"
|
|
#include "../clib/Program/ProgramConfig.h"
|
|
#include "pol.h"
|
|
// This needs to be after the windows includes, otherwise it'll complain about windows types.
|
|
#include "../clib/NTService.h"
|
|
#include "../clib/ntservmsg.h"
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma warning( disable : 4189 ) // local variable is initialized but not referenced. TODO: check
|
|
// if TrackPopupMenu() returns an error on line 146.
|
|
#endif
|
|
|
|
namespace Pol
|
|
{
|
|
namespace Core
|
|
{
|
|
int RunWindowsService( int argc, char** argv );
|
|
}
|
|
|
|
int xmain( int argc, char* argv[] )
|
|
{
|
|
return Core::RunWindowsService( argc, argv );
|
|
}
|
|
namespace Core
|
|
{
|
|
class PolService : public Clib::CNTService
|
|
{
|
|
public:
|
|
PolService();
|
|
virtual void Run() override;
|
|
virtual void OnStop() override;
|
|
};
|
|
|
|
PolService::PolService() : Clib::CNTService( "POL" ) {}
|
|
|
|
void PolService::Run()
|
|
{
|
|
// a technicality: a service generally starts with an ignorant current directory.
|
|
try
|
|
{
|
|
// threadhelp::thread_sleep_ms( 20000 );
|
|
DWORD rc;
|
|
char buffer[1000] = "";
|
|
rc = GetCurrentDirectory( sizeof buffer, buffer );
|
|
LogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_DEBUG, buffer );
|
|
LogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_DEBUG, PROG_CONFIG::programDir().c_str() );
|
|
rc = SetCurrentDirectory( PROG_CONFIG::programDir().c_str() );
|
|
|
|
xmain_outer( false /*testing*/ );
|
|
}
|
|
catch ( std::exception& ex )
|
|
{
|
|
this->LogEvent( EVENTLOG_ERROR_TYPE, EVMSG_DEBUG, ex.what() );
|
|
}
|
|
}
|
|
void PolService::OnStop()
|
|
{
|
|
Clib::signal_exit();
|
|
}
|
|
|
|
|
|
int RunWindowsService( int argc, char** argv )
|
|
{
|
|
// Create the service object
|
|
PolService MyService;
|
|
|
|
// Parse for standard arguments (install, uninstall, version etc.)
|
|
if ( !MyService.ParseStandardArgs( argc, argv ) )
|
|
{
|
|
// no service-related parameters
|
|
return xmain_outer( false /*testing*/ );
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
#define WM_ICON_NOTIFY WM_USER + 1
|
|
unsigned WM_TASKBARCREATED;
|
|
HWND hwnd;
|
|
NOTIFYICONDATA ndata;
|
|
|
|
#define DLG_MODELESS 1
|
|
|
|
#ifdef _M_X64
|
|
INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
#else
|
|
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
#endif
|
|
{
|
|
if ( uMsg == WM_TASKBARCREATED )
|
|
uMsg = WM_INITDIALOG;
|
|
|
|
switch ( uMsg )
|
|
{
|
|
// case WM_TASKBARCREATED:
|
|
case WM_INITDIALOG:
|
|
ndata.hWnd = hwndDlg;
|
|
|
|
Shell_NotifyIcon( NIM_ADD, &ndata );
|
|
|
|
SetWindowPos( hwndDlg, nullptr, -10, -10, 0, 0, SWP_NOZORDER | SWP_NOMOVE );
|
|
hwnd = hwndDlg;
|
|
break;
|
|
|
|
case WM_ICON_NOTIFY:
|
|
|
|
if ( lParam == WM_RBUTTONDOWN )
|
|
{
|
|
// Beep(200,200); // Removed beep... ! (Debugging POLLaunch made me hate this :/)
|
|
HMENU m = LoadMenu( GetModuleHandle( nullptr ), MAKEINTRESOURCE( IDR_POPUP ) );
|
|
HMENU subm = GetSubMenu( m, 0 );
|
|
POINT p;
|
|
GetCursorPos( &p );
|
|
|
|
SetForegroundWindow( hwndDlg );
|
|
BOOL rc = TrackPopupMenu( subm, TPM_LEFTALIGN, p.x, p.y, 0, hwndDlg, nullptr );
|
|
PostMessage( hwndDlg, WM_NULL, 0, 0 );
|
|
}
|
|
break;
|
|
case WM_COMMAND:
|
|
if ( LOWORD( wParam ) == ID_POPUP_STOP )
|
|
Clib::signal_exit();
|
|
else if ( LOWORD( wParam ) == ID_POPUP_SHOWCONSOLE )
|
|
{
|
|
/*
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
|
|
ZeroMemory(&si,sizeof(STARTUPINFO));
|
|
si.cb = sizeof(STARTUPINFO);
|
|
si.dwFlags = STARTF_USESTDHANDLES;
|
|
si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
|
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
|
BOOL rc;
|
|
rc = CreateProcess( "constub.exe",
|
|
"constub.exe",
|
|
nullptr,
|
|
nullptr,
|
|
TRUE, // inherit handles
|
|
CREATE_NEW_CONSOLE,
|
|
nullptr,
|
|
nullptr,
|
|
&si,
|
|
&pi );
|
|
DWORD err = GetLastError();
|
|
Sleep( 5000 );
|
|
rc = WriteFile( si.hStdOutput, "abcdef", 6, nullptr, nullptr );
|
|
*/
|
|
/*
|
|
HWND x = GetConsoleWindow();
|
|
HANDLE hInput = GetStdHandle( STD_INPUT_HANDLE );
|
|
HANDLE hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
|
|
HANDLE hError = GetStdHandle( STD_ERROR_HANDLE );
|
|
|
|
//FreeConsole();
|
|
AllocConsole();
|
|
cout << "cout xyz" << endl;
|
|
cerr << "cerr xyz" << endl;
|
|
printf( "Hi there.\n" );
|
|
fflush( stdout );
|
|
*/
|
|
}
|
|
else if ( LOWORD( wParam ) == ID_UPDATE_NOTIFYDATA )
|
|
{
|
|
Shell_NotifyIcon( NIM_MODIFY, &ndata );
|
|
}
|
|
else if ( LOWORD( wParam ) == ID_SHUTDOWN )
|
|
{
|
|
Shell_NotifyIcon( NIM_DELETE, &ndata );
|
|
#if DLG_MODELESS
|
|
DestroyWindow( hwndDlg );
|
|
#else
|
|
EndDialog( hwndDlg, wParam );
|
|
#endif
|
|
}
|
|
break;
|
|
case WM_DESTROY:
|
|
case WM_CLOSE:
|
|
case WM_QUIT:
|
|
{
|
|
Shell_NotifyIcon( NIM_DELETE, &ndata );
|
|
#if DLG_MODELESS
|
|
DestroyWindow( hwndDlg );
|
|
#else
|
|
EndDialog( hwndDlg, wParam );
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void SystemTrayDialogThread( void* )
|
|
// DWORD WINAPI Thread( LPVOID lpParameter)
|
|
// void SystemTrayDialogThread( void )
|
|
{
|
|
// modeless:
|
|
#if DLG_MODELESS
|
|
hwnd = CreateDialog( nullptr, MAKEINTRESOURCE( IDD_DIALOG1 ), nullptr, DialogProc );
|
|
ShowWindow( hwnd, SW_HIDE );
|
|
|
|
BOOL bRet;
|
|
MSG msg;
|
|
|
|
while ( ( bRet = GetMessage( &msg, nullptr, 0, 0 ) ) != 0 )
|
|
{
|
|
if ( bRet == -1 )
|
|
{
|
|
// handle the error and possibly exit
|
|
break;
|
|
}
|
|
else if ( !IsWindow( hwnd ) || !IsDialogMessage( hwnd, &msg ) )
|
|
{
|
|
TranslateMessage( &msg );
|
|
DispatchMessage( &msg );
|
|
}
|
|
}
|
|
#else
|
|
// modal:
|
|
DialogBox( nullptr, MAKEINTRESOURCE( IDD_DIALOG1 ), nullptr, DialogProc );
|
|
#endif
|
|
}
|
|
|
|
void SetSysTrayPopupText( const char* text )
|
|
{
|
|
strncpy( ndata.szTip, text, sizeof( ndata.szTip ) - 1 );
|
|
ndata.szTip[sizeof( ndata.szTip ) - 1] = '\0';
|
|
|
|
if ( hwnd )
|
|
SendMessage( hwnd, WM_COMMAND, ID_UPDATE_NOTIFYDATA, 0 );
|
|
}
|
|
|
|
BOOL WINAPI control_handler_SystemTray( DWORD dwCtrlType )
|
|
{
|
|
switch ( dwCtrlType )
|
|
{
|
|
case CTRL_CLOSE_EVENT: // console window closing
|
|
Shell_NotifyIcon( NIM_DELETE, &ndata );
|
|
#if DLG_MODELESS
|
|
DestroyWindow( hwnd );
|
|
#else
|
|
EndDialog( hwndDlg, wParam );
|
|
#endif
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
void InitializeSystemTrayHandling()
|
|
{
|
|
WM_TASKBARCREATED = RegisterWindowMessage( "TaskbarCreated" );
|
|
|
|
ndata.cbSize = sizeof( NOTIFYICONDATA );
|
|
// ndata.hWnd=hwndDlg;
|
|
ndata.uID = 2000;
|
|
ndata.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
|
|
ndata.uCallbackMessage = WM_ICON_NOTIFY;
|
|
ndata.hIcon = ::LoadIcon( GetModuleHandle( nullptr ), MAKEINTRESOURCE( IDI_POLTRAY ) );
|
|
strcpy( ndata.szTip, "POL Initializing" );
|
|
|
|
_beginthread( SystemTrayDialogThread, 0, nullptr );
|
|
SetConsoleCtrlHandler( control_handler_SystemTray, TRUE );
|
|
// _beginthreadex( nullptr,
|
|
// 0,
|
|
// SystemTrayDialogThread,
|
|
// 0,
|
|
// nullptr );
|
|
// CreateThread(nullptr,0,Thread,nullptr,0,nullptr);
|
|
// threadhelp::start_thread( SystemTrayDialogThread, "SystemTrayDialog" );
|
|
}
|
|
|
|
void ShutdownSystemTrayHandling()
|
|
{
|
|
if ( hwnd )
|
|
{
|
|
#ifdef _M_X64
|
|
PDWORD_PTR res = nullptr;
|
|
LRESULT rc = SendMessageTimeout( hwnd, WM_COMMAND, ID_SHUTDOWN, 0, SMTO_NORMAL, 5000, res );
|
|
#else
|
|
DWORD res;
|
|
LRESULT rc = SendMessageTimeout( hwnd, WM_COMMAND, ID_SHUTDOWN, 0, SMTO_NORMAL, 5000, &res );
|
|
#endif
|
|
|
|
if ( !rc )
|
|
{
|
|
DWORD err = GetLastError();
|
|
INFO_PRINT << "Unable to shutdown systray: " << err << "\n";
|
|
}
|
|
}
|
|
}
|
|
} // namespace Core
|
|
} // namespace Pol
|