Pol  Revision:cb584c9
polservice.cpp
Go to the documentation of this file.
1 
7 #include "../clib/esignal.h"
8 #include "../clib/threadhelp.h"
9 //#include "../clib/xmain.h"
10 #include "../clib/logfacility.h"
11 
12 #include "../plib/systemstate.h"
13 
14 #include "polresource.h"
15 
16 #include "../clib/Program/ProgramConfig.h"
17 #include "../clib/Header_Windows.h"
18 #include "pol.h"
19 // This needs to be after the windows includes, otherwise it'll complain about windows types.
20 #include "../clib/NTService.h"
21 #include "../clib/ntservmsg.h"
22 
23 #ifdef _MSC_VER
24 #pragma warning( disable : 4189 ) // local variable is initialized but not referenced. TODO: check
25  // if TrackPopupMenu() returns an error on line 146.
26 #endif
27 
28 namespace Pol
29 {
30 namespace Core
31 {
32 int RunWindowsService( int argc, char** argv );
33 }
34 
35 int xmain( int argc, char* argv[] )
36 {
37  return Core::RunWindowsService( argc, argv );
38 }
39 namespace Core
40 {
42 {
43 public:
44  PolService();
45  virtual void Run() POL_OVERRIDE;
46  virtual void OnStop() POL_OVERRIDE;
47 };
48 
49 PolService::PolService() : Clib::CNTService( "POL" )
50 {
51 }
52 
54 {
55  // a technicality: a service generally starts with an ignorant current directory.
56  try
57  {
58  // threadhelp::thread_sleep_ms( 20000 );
59  DWORD rc;
60  char buffer[1000] = "";
61  rc = GetCurrentDirectory( sizeof buffer, buffer );
62  LogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_DEBUG, buffer );
63  LogEvent( EVENTLOG_INFORMATION_TYPE, EVMSG_DEBUG, PROG_CONFIG::programDir().c_str() );
64  rc = SetCurrentDirectory( PROG_CONFIG::programDir().c_str() );
65 
66  xmain_outer( false /*testing*/ );
67  }
68  catch ( std::exception& ex )
69  {
70  this->LogEvent( EVENTLOG_ERROR_TYPE, EVMSG_DEBUG, ex.what() );
71  }
72 }
74 {
75  Clib::exit_signalled = true;
76 }
77 
78 
79 int RunWindowsService( int argc, char** argv )
80 {
81  // Create the service object
82  PolService MyService;
83 
84  // Parse for standard arguments (install, uninstall, version etc.)
85  if ( !MyService.ParseStandardArgs( argc, argv ) )
86  {
87  // no service-related parameters
88  return xmain_outer( false /*testing*/ );
89  }
90  else
91  {
92  return 0;
93  }
94 }
95 
96 
97 #define WM_ICON_NOTIFY WM_USER + 1
99 HWND hwnd;
100 NOTIFYICONDATA ndata;
101 
102 #define DLG_MODELESS 1
103 
104 #ifdef _M_X64
105 INT_PTR CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
106 #else
107 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
108 #endif
109 {
110  if ( uMsg == WM_TASKBARCREATED )
111  uMsg = WM_INITDIALOG;
112 
113  switch ( uMsg )
114  {
115  // case WM_TASKBARCREATED:
116  case WM_INITDIALOG:
117  ndata.hWnd = hwndDlg;
118 
119  Shell_NotifyIcon( NIM_ADD, &ndata );
120 
121  SetWindowPos( hwndDlg, nullptr, -10, -10, 0, 0, SWP_NOZORDER | SWP_NOMOVE );
122  hwnd = hwndDlg;
123  break;
124 
125  case WM_ICON_NOTIFY:
126 
127  if ( lParam == WM_RBUTTONDOWN )
128  {
129  // Beep(200,200); // Removed beep... ! (Debugging POLLaunch made me hate this :/)
130  HMENU m = LoadMenu( GetModuleHandle( nullptr ), MAKEINTRESOURCE( IDR_POPUP ) );
131  HMENU subm = GetSubMenu( m, 0 );
132  POINT p;
133  GetCursorPos( &p );
134 
135  SetForegroundWindow( hwndDlg );
136  BOOL rc = TrackPopupMenu( subm, TPM_LEFTALIGN, p.x, p.y, 0, hwndDlg, nullptr );
137  PostMessage( hwndDlg, WM_NULL, 0, 0 );
138  }
139  break;
140  case WM_COMMAND:
141  if ( LOWORD( wParam ) == ID_POPUP_STOP )
142  Clib::exit_signalled = true;
143  else if ( LOWORD( wParam ) == ID_POPUP_SHOWCONSOLE )
144  {
145  /*
146  PROCESS_INFORMATION pi;
147  STARTUPINFO si;
148 
149  ZeroMemory(&si,sizeof(STARTUPINFO));
150  si.cb = sizeof(STARTUPINFO);
151  si.dwFlags = STARTF_USESTDHANDLES;
152  si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
153  si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
154  si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
155  BOOL rc;
156  rc = CreateProcess( "constub.exe",
157  "constub.exe",
158  nullptr,
159  nullptr,
160  TRUE, // inherit handles
161  CREATE_NEW_CONSOLE,
162  nullptr,
163  nullptr,
164  &si,
165  &pi );
166  DWORD err = GetLastError();
167  Sleep( 5000 );
168  rc = WriteFile( si.hStdOutput, "abcdef", 6, nullptr, nullptr );
169  */
170  /*
171  HWND x = GetConsoleWindow();
172  HANDLE hInput = GetStdHandle( STD_INPUT_HANDLE );
173  HANDLE hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
174  HANDLE hError = GetStdHandle( STD_ERROR_HANDLE );
175 
176  //FreeConsole();
177  AllocConsole();
178  cout << "cout xyz" << endl;
179  cerr << "cerr xyz" << endl;
180  printf( "Hi there.\n" );
181  fflush( stdout );
182  */
183  }
184  else if ( LOWORD( wParam ) == ID_UPDATE_NOTIFYDATA )
185  {
186  Shell_NotifyIcon( NIM_MODIFY, &ndata );
187  }
188  else if ( LOWORD( wParam ) == ID_SHUTDOWN )
189  {
190  Shell_NotifyIcon( NIM_DELETE, &ndata );
191 #if DLG_MODELESS
192  DestroyWindow( hwndDlg );
193 #else
194  EndDialog( hwndDlg, wParam );
195 #endif
196  }
197  break;
198  case WM_DESTROY:
199  case WM_CLOSE:
200  case WM_QUIT:
201  {
202  Shell_NotifyIcon( NIM_DELETE, &ndata );
203 #if DLG_MODELESS
204  DestroyWindow( hwndDlg );
205 #else
206  EndDialog( hwndDlg, wParam );
207 #endif
208  break;
209  }
210  }
211  return FALSE;
212 }
213 
215 // DWORD WINAPI Thread( LPVOID lpParameter)
216 // void SystemTrayDialogThread( void )
217 {
218 // modeless:
219 #if DLG_MODELESS
220  hwnd = CreateDialog( nullptr, MAKEINTRESOURCE( IDD_DIALOG1 ), nullptr, DialogProc );
221  ShowWindow( hwnd, SW_HIDE );
222 
223  BOOL bRet;
224  MSG msg;
225 
226  while ( ( bRet = GetMessage( &msg, nullptr, 0, 0 ) ) != 0 )
227  {
228  if ( bRet == -1 )
229  {
230  // handle the error and possibly exit
231  break;
232  }
233  else if ( !IsWindow( hwnd ) || !IsDialogMessage( hwnd, &msg ) )
234  {
235  TranslateMessage( &msg );
236  DispatchMessage( &msg );
237  }
238  }
239 #else
240  // modal:
241  DialogBox( nullptr, MAKEINTRESOURCE( IDD_DIALOG1 ), nullptr, DialogProc );
242 #endif
243 }
244 
245 void SetSysTrayPopupText( const char* text )
246 {
247  strncpy( ndata.szTip, text, sizeof( ndata.szTip ) - 1 );
248  ndata.szTip[sizeof( ndata.szTip ) - 1] = '\0';
249 
250  if ( hwnd )
251  SendMessage( hwnd, WM_COMMAND, ID_UPDATE_NOTIFYDATA, 0 );
252 }
253 
255 {
256  switch ( dwCtrlType )
257  {
258  case CTRL_CLOSE_EVENT: // console window closing
259  Shell_NotifyIcon( NIM_DELETE, &ndata );
260 #if DLG_MODELESS
261  DestroyWindow( hwnd );
262 #else
263  EndDialog( hwndDlg, wParam );
264 #endif
265  break;
266  }
267  return FALSE;
268 }
270 {
271  WM_TASKBARCREATED = RegisterWindowMessage( "TaskbarCreated" );
272 
273  ndata.cbSize = sizeof( NOTIFYICONDATA );
274  // ndata.hWnd=hwndDlg;
275  ndata.uID = 2000;
276  ndata.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
277  ndata.uCallbackMessage = WM_ICON_NOTIFY;
278  ndata.hIcon = ::LoadIcon( GetModuleHandle( nullptr ), MAKEINTRESOURCE( IDI_POLTRAY ) );
279  strcpy( ndata.szTip, "POL Initializing" );
280 
281  _beginthread( SystemTrayDialogThread, 0, nullptr );
282  SetConsoleCtrlHandler( control_handler_SystemTray, TRUE );
283  // _beginthreadex( nullptr,
284  // 0,
285  // SystemTrayDialogThread,
286  // 0,
287  // nullptr );
288  // CreateThread(nullptr,0,Thread,nullptr,0,nullptr);
289  // threadhelp::start_thread( SystemTrayDialogThread, "SystemTrayDialog" );
290 }
291 
293 {
294  if ( hwnd )
295  {
296 #ifdef _M_X64
297  PDWORD_PTR res = nullptr;
298  LRESULT rc = SendMessageTimeout( hwnd, WM_COMMAND, ID_SHUTDOWN, 0, SMTO_NORMAL, 5000, res );
299 #else
300  DWORD res;
301  LRESULT rc = SendMessageTimeout( hwnd, WM_COMMAND, ID_SHUTDOWN, 0, SMTO_NORMAL, 5000, &res );
302 #endif
303 
304  if ( !rc )
305  {
306  DWORD err = GetLastError();
307  INFO_PRINT << "Unable to shutdown systray: " << err << "\n";
308  }
309  }
310 }
311 }
312 }
#define WM_ICON_NOTIFY
Definition: polservice.cpp:97
#define POL_OVERRIDE
BOOL ParseStandardArgs(int argc, char *argv[])
Definition: NTService.cpp:62
int RunWindowsService(int argc, char **argv)
Definition: polservice.cpp:79
virtual void OnStop() POL_OVERRIDE
Definition: polservice.cpp:73
int xmain(int argc, char *argv[])
Definition: polservice.cpp:35
void SystemTrayDialogThread(void *)
Definition: polservice.cpp:214
typedef DWORD(WINAPI *__SymGetOptions)(VOID)
unsigned char buffer[10000]
Definition: UoToolMain.cpp:109
#define ID_SHUTDOWN
Definition: polresource.h:7
NOTIFYICONDATA ndata
Definition: polservice.cpp:100
int xmain_outer(bool testing)
Definition: pol.cpp:1452
virtual void Run() POL_OVERRIDE
Definition: polservice.cpp:53
#define ID_UPDATE_NOTIFYDATA
Definition: polresource.h:6
#define IDR_POPUP
Definition: polresource.h:2
void InitializeSystemTrayHandling()
Definition: polservice.cpp:269
typedef BOOL(WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess
BOOL WINAPI control_handler_SystemTray(DWORD dwCtrlType)
Definition: polservice.cpp:254
unsigned WM_TASKBARCREATED
Definition: polservice.cpp:98
void LogEvent(WORD wType, DWORD dwID, const char *pszS1=NULL, const char *pszS2=NULL, const char *pszS3=NULL)
Definition: NTService.cpp:257
#define ID_POPUP_SHOWCONSOLE
Definition: polresource.h:5
void SetSysTrayPopupText(const char *text)
Definition: polservice.cpp:245
void ShutdownSystemTrayHandling()
Definition: polservice.cpp:292
#define IDI_POLTRAY
Definition: polresource.h:3
#define EVMSG_DEBUG
Definition: ntservmsg.h:107
#define INFO_PRINT
Definition: logfacility.h:223
#define ID_POPUP_STOP
Definition: polresource.h:4
Definition: berror.cpp:12
std::atomic< bool > exit_signalled
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
Definition: polservice.cpp:107
#define IDD_DIALOG1
Definition: polresource.h:1