|  |  | 
|  | /* | 
|  | * Copyright (C) Igor Sysoev | 
|  | */ | 
|  |  | 
|  |  | 
|  | #include <ngx_config.h> | 
|  | #include <ngx_core.h> | 
|  | #include <ngx_event.h> | 
|  | #include <nginx.h> | 
|  |  | 
|  |  | 
|  | static ngx_thread_value_t __stdcall ngx_worker_thread_cycle(void *data); | 
|  | static long __stdcall ngx_window_procedure(HWND window, u_int message, | 
|  | u_int wparam, long lparam); | 
|  |  | 
|  | #if 0 | 
|  | ngx_pid_t     ngx_new_binary; | 
|  |  | 
|  | sig_atomic_t  ngx_reap; | 
|  | sig_atomic_t  ngx_timer; | 
|  |  | 
|  | #endif | 
|  |  | 
|  | ngx_uint_t    ngx_process; | 
|  | ngx_pid_t     ngx_pid; | 
|  | ngx_uint_t    ngx_threaded; | 
|  | ngx_uint_t    ngx_inherited; | 
|  |  | 
|  |  | 
|  | sig_atomic_t  ngx_terminate; | 
|  | sig_atomic_t  ngx_quit; | 
|  | ngx_uint_t    ngx_exiting; | 
|  |  | 
|  | #if 0 | 
|  |  | 
|  | sig_atomic_t  ngx_noaccept; | 
|  | sig_atomic_t  ngx_reconfigure; | 
|  | sig_atomic_t  ngx_reopen; | 
|  | sig_atomic_t  ngx_change_binary; | 
|  |  | 
|  | #endif | 
|  |  | 
|  |  | 
|  | static HMENU  ngx_menu; | 
|  |  | 
|  |  | 
|  | void | 
|  | ngx_master_process_cycle(ngx_cycle_t *cycle) | 
|  | { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "master mode is not supported"); | 
|  |  | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | void | 
|  | ngx_single_process_cycle(ngx_cycle_t *cycle) | 
|  | { | 
|  | int               rc; | 
|  | ngx_int_t         i; | 
|  | ngx_err_t         err; | 
|  | ngx_tid_t         tid; | 
|  | MSG               message; | 
|  | HWND              window; | 
|  | HMENU             menu; | 
|  | HICON             icon,tray; | 
|  | WNDCLASS          wc; | 
|  | HINSTANCE         instance; | 
|  | ngx_core_conf_t  *ccf; | 
|  |  | 
|  | ngx_init_temp_number(); | 
|  |  | 
|  | for (i = 0; ngx_modules[i]; i++) { | 
|  | if (ngx_modules[i]->init_process) { | 
|  | if (ngx_modules[i]->init_process(cycle) == NGX_ERROR) { | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); | 
|  |  | 
|  | if (ngx_init_threads(ngx_threads_n, | 
|  | ccf->thread_stack_size, cycle) == NGX_ERROR) | 
|  | { | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  | err = ngx_thread_key_create(&ngx_core_tls_key); | 
|  | if (err != 0) { | 
|  | ngx_log_error(NGX_LOG_ALERT, cycle->log, err, | 
|  | ngx_thread_key_create_n " failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | instance = GetModuleHandle(NULL); | 
|  |  | 
|  | icon = LoadIcon(instance, "nginx"); | 
|  | if (icon == NULL) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "LoadIcon(\"nginx\") failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  | tray = LoadIcon(instance, "tray"); | 
|  | if (icon == NULL) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "LoadIcon(\"tray\") failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  | menu = LoadMenu(instance, "nginx"); | 
|  | if (menu == NULL) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "LoadMenu() failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  | ngx_menu = GetSubMenu(menu, 0); | 
|  | if (ngx_menu == NULL) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "GetSubMenu() failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | wc.style = CS_HREDRAW|CS_VREDRAW; | 
|  | wc.lpfnWndProc = ngx_window_procedure; | 
|  | wc.cbClsExtra = 0; | 
|  | wc.cbWndExtra = 0; | 
|  | wc.hInstance = instance; | 
|  | wc.hIcon = icon; | 
|  | wc.hCursor = NULL; | 
|  | wc.hbrBackground = NULL; | 
|  | wc.lpszMenuName =  NULL; | 
|  | wc.lpszClassName = "nginx"; | 
|  |  | 
|  | if (RegisterClass(&wc) == 0) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "RegisterClass() failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | window = CreateWindow("nginx", "nginx", WS_OVERLAPPEDWINDOW, | 
|  | CW_USEDEFAULT, CW_USEDEFAULT, | 
|  | CW_USEDEFAULT, CW_USEDEFAULT, | 
|  | NULL, NULL, instance, NULL); | 
|  |  | 
|  | if (window == NULL) { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "CreateWindow() failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | if (ngx_system_tray_icon(window, NIM_ADD, tray, (u_char *) " nginx") | 
|  | != NGX_OK) | 
|  | { | 
|  | ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 
|  | "Shell_NotifyIcon(NIM_ADD) failed"); | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | if (ngx_create_thread(&tid, ngx_worker_thread_cycle, NULL, cycle->log) != 0) | 
|  | { | 
|  | /* fatal */ | 
|  | exit(2); | 
|  | } | 
|  |  | 
|  |  | 
|  | for ( ;; ) { | 
|  | rc = GetMessage(&message, NULL, 0, 0); | 
|  |  | 
|  | if (rc == -1) { | 
|  | ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 
|  | "GetMessage() failed"); | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (rc == 0) { | 
|  | exit(0); | 
|  | } | 
|  |  | 
|  | TranslateMessage(&message); | 
|  | DispatchMessage(&message); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | static ngx_thread_value_t __stdcall | 
|  | ngx_worker_thread_cycle(void *data) | 
|  | { | 
|  | ngx_cycle_t  *cycle; | 
|  |  | 
|  | cycle = (ngx_cycle_t *) ngx_cycle; | 
|  |  | 
|  | while (!ngx_quit) { | 
|  | ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "worker cycle"); | 
|  |  | 
|  | ngx_process_events_and_timers(cycle); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  |  | 
|  | static long __stdcall | 
|  | ngx_window_procedure(HWND window, u_int message, u_int wparam, long lparam) | 
|  | { | 
|  | POINT  mouse; | 
|  |  | 
|  | switch (message) { | 
|  |  | 
|  | case NGX_WM_TRAY: | 
|  | if (lparam == WM_RBUTTONDOWN) { | 
|  | if (GetCursorPos(&mouse) == 0) { | 
|  | ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | 
|  | "GetCursorPos() failed"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (SetForegroundWindow(window) == 0) { | 
|  | ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | 
|  | "SetForegroundWindow() failed"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (TrackPopupMenu(ngx_menu, TPM_RIGHTBUTTON, | 
|  | mouse.x, mouse.y, 0, window, NULL) == 0) | 
|  | { | 
|  | ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | 
|  | "TrackPopupMenu() failed"); | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | return 0; | 
|  |  | 
|  | case WM_COMMAND: | 
|  | if (wparam == NGX_WM_ABOUT) { | 
|  | ngx_message_box("nginx", MB_OK, 0, | 
|  | NGINX_VER CRLF "(C) 2002-2005 Igor Sysoev"); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | if (wparam == NGX_WM_EXIT) { | 
|  | if (ngx_system_tray_icon(window, NIM_DELETE, NULL, NULL) | 
|  | != NGX_OK) | 
|  | { | 
|  | ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno, | 
|  | "Shell_NotifyIcon(NIM_DELETE) failed"); | 
|  | } | 
|  | } | 
|  |  | 
|  | PostQuitMessage(0); | 
|  |  | 
|  | return 0; | 
|  |  | 
|  | default: | 
|  | return DefWindowProc(window, message, wparam, lparam); | 
|  | } | 
|  | } |