1515 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1616*/
1717
18+ #include <windows.h>
1819#include <stdio.h>
1920#include <stdarg.h>
2021
2425
2526struct reg_global global_conf ;
2627
28+ static HMODULE netshell_dll = NULL ;
29+
30+ #define APPWM_TRAY (WM_APP+1)
31+ #define MNU_EXIT 101
32+
33+ static void die (const char * fmt , ...);
34+ static void init_ui ();
35+ static LRESULT CALLBACK tray_wproc (HWND hwnd , UINT msg , WPARAM wp , LPARAM lp );
36+ static void show_menu (HWND hwnd );
37+
2738int main (int argc , char * * argv ) {
28- setvbuf (stdout , NULL , _IONBF , 0 );
29- setvbuf (stderr , NULL , _IONBF , 0 );
39+ log_open ("ipxrouter.log" );
3040
3141 reg_open (KEY_QUERY_VALUE );
3242
@@ -39,37 +49,196 @@ int main(int argc, char **argv) {
3949
4050 WSADATA wsdata ;
4151 int err = WSAStartup (MAKEWORD (2 ,0 ), & wsdata );
42-
4352 if (err ) {
44- log_printf ("Failed to initialize winsock: %s" , w32_error (err ));
45- }else {
46- struct router_vars * router = router_init (TRUE);
47-
48- if (router ) {
49- //FreeConsole();
50- router_main (router );
51- router_destroy (router );
52- }
53-
54- WSACleanup ();
53+ die ("Failed to initialize winsock: %s" , w32_error (err ));
54+ }
55+
56+ struct router_vars * router = router_init (TRUE);
57+ if (!router ) {
58+ die ("Error while initializing router, check ipxrouter.log" );
59+ }
60+
61+ HANDLE worker = CreateThread (NULL , 0 , (LPTHREAD_START_ROUTINE )& router_main , router , 0 , NULL );
62+ if (!worker ) {
63+ die ("Failed to create router thread: %s" , w32_error (GetLastError ()));
64+ }
65+
66+ init_ui ();
67+
68+ MSG msg ;
69+
70+ while (GetMessage (& msg , NULL , 0 , 0 ) > 0 ) {
71+ TranslateMessage (& msg );
72+ DispatchMessage (& msg );
73+ }
74+
75+ EnterCriticalSection (& (router -> crit_sec ));
76+
77+ router -> running = FALSE;
78+ WSASetEvent (router -> wsa_event );
79+
80+ LeaveCriticalSection (& (router -> crit_sec ));
81+
82+ if (WaitForSingleObject (worker , 3000 ) == WAIT_TIMEOUT ) {
83+ log_printf ("Router thread didn't exit in 3 seconds, terminating" );
84+ TerminateThread (worker , 0 );
5585 }
5686
87+ CloseHandle (worker );
88+ router_destroy (router );
89+
90+ WSACleanup ();
91+
5792 reg_close ();
5893
59- system ( "pause" );
94+ log_close ( );
6095
6196 return 0 ;
6297}
6398
64- void log_printf (const char * fmt , ...) {
99+ static void die (const char * fmt , ...) {
65100 va_list argv ;
101+ char msg [512 ];
66102
67103 va_start (argv , fmt );
104+ vsnprintf (msg , sizeof (msg ), fmt , argv );
105+ va_end (argv );
106+
107+ MessageBox (NULL , msg , "Fatal error" , MB_OK | MB_TASKMODAL );
108+ exit (1 );
109+ }
110+
111+ static void init_ui () {
112+ WNDCLASS wclass ;
68113
69- //AllocConsole();
114+ wclass .style = 0 ;
115+ wclass .lpfnWndProc = & tray_wproc ;
116+ wclass .cbClsExtra = 0 ;
117+ wclass .cbWndExtra = 0 ;
118+ wclass .hInstance = GetModuleHandle (NULL );
119+ wclass .hIcon = NULL ;
120+ wclass .hCursor = LoadCursor (NULL , IDC_ARROW );
121+ wclass .hbrBackground = NULL ;
122+ wclass .lpszMenuName = NULL ;
123+ wclass .lpszClassName = "ipxrouter_tray" ;
70124
71- vfprintf (stderr , fmt , argv );
72- fputc ('\n' , stderr );
125+ if (!RegisterClass (& wclass )) {
126+ die ("RegisterClass: %s" , w32_error (GetLastError ()));
127+ }
73128
74- va_end (argv );
129+ HWND window = CreateWindow (
130+ "ipxrouter_tray" ,
131+ "IPX Router" ,
132+ 0 ,
133+ CW_USEDEFAULT , CW_USEDEFAULT ,
134+ CW_USEDEFAULT , CW_USEDEFAULT ,
135+ NULL ,
136+ NULL ,
137+ GetModuleHandle (NULL ),
138+ NULL
139+ );
140+
141+ if (!window ) {
142+ die ("CreateWindow: " , w32_error (GetLastError ()));
143+ }
144+
145+ if (!(netshell_dll = LoadLibrary ("netshell.dll" ))) {
146+ die ("Error loading netshell.dll: " , w32_error (GetLastError ()));
147+ }
148+
149+ HICON icon = LoadIcon (netshell_dll , MAKEINTRESOURCE (162 ));
150+ if (!icon ) {
151+ die ("Error loading icon: " , w32_error (GetLastError ()));
152+ }
153+
154+ NOTIFYICONDATA tray ;
155+
156+ tray .cbSize = sizeof (tray );
157+ tray .hWnd = window ;
158+ tray .uID = 1 ;
159+ tray .uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP ;
160+ tray .uCallbackMessage = APPWM_TRAY ;
161+ tray .hIcon = icon ;
162+ strcpy (tray .szTip , "IPXWrapper Router" );
163+
164+ if (!Shell_NotifyIcon (NIM_ADD , & tray )) {
165+ die ("Shell_NotifyIcon failed" );
166+ }
167+ }
168+
169+ static LRESULT CALLBACK tray_wproc (HWND hwnd , UINT msg , WPARAM wp , LPARAM lp ) {
170+ switch (msg ) {
171+ case WM_CLOSE : {
172+ DestroyWindow (hwnd );
173+ break ;
174+ }
175+
176+ case WM_DESTROY : {
177+ PostQuitMessage (0 );
178+ break ;
179+ }
180+
181+ case APPWM_TRAY : {
182+ if (lp == WM_LBUTTONUP || lp == WM_RBUTTONUP ) {
183+ show_menu (hwnd );
184+ }
185+
186+ break ;
187+ }
188+
189+ case WM_COMMAND : {
190+ if (wp == MNU_EXIT ) {
191+ if (MessageBox (NULL , "If the router is stopped any existing sockets will become invalid.\nAre you sure you want to exit?" , "IPXWrapper" , MB_YESNO ) == IDNO ) {
192+ return 0 ;
193+ }
194+
195+ NOTIFYICONDATA tray ;
196+ tray .cbSize = sizeof (tray );
197+ tray .hWnd = hwnd ;
198+ tray .uID = 1 ;
199+ tray .uFlags = 0 ;
200+
201+ Shell_NotifyIcon (NIM_DELETE , & tray );
202+ DestroyWindow (hwnd );
203+ }
204+
205+ break ;
206+ }
207+
208+ default : {
209+ return DefWindowProc (hwnd , msg , wp , lp );
210+ }
211+ }
212+
213+ return 0 ;
214+ }
215+
216+ static void show_menu (HWND hwnd ) {
217+ POINT cursor_pos ;
218+
219+ GetCursorPos (& cursor_pos );
220+
221+ SetForegroundWindow (hwnd );
222+
223+ HMENU menu = CreatePopupMenu ();
224+ if (!menu ) {
225+ die ("CreatePopupMenu: %s" , w32_error (GetLastError ()));
226+ }
227+
228+ InsertMenu (menu , -1 , MF_BYPOSITION | MF_STRING , MNU_EXIT , "Exit" );
229+
230+ SetMenuDefaultItem (menu , MNU_EXIT , FALSE);
231+
232+ SetFocus (hwnd );
233+
234+ TrackPopupMenu (
235+ menu ,
236+ TPM_LEFTALIGN | TPM_BOTTOMALIGN ,
237+ cursor_pos .x , cursor_pos .y ,
238+ 0 ,
239+ hwnd ,
240+ NULL
241+ );
242+
243+ DestroyMenu (menu );
75244}
0 commit comments