unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

gui.c (30340B)

      1 /************************************************************************
      2  *   IRC - Internet Relay Chat, windows/gui.c
      3  *   Copyright (C) 2000-2004 David Flynn (DrBin) & Dominick Meglio (codemastr)
      4  *   
      5  *   This program is free software; you can redistribute it and/or modify
      6  *   it under the terms of the GNU General Public License as published by
      7  *   the Free Software Foundation; either version 1, or (at your option)
      8  *   any later version.
      9  *
     10  *   This program is distributed in the hope that it will be useful,
     11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  *   GNU General Public License for more details.
     14  *
     15  *   You should have received a copy of the GNU General Public License
     16  *   along with this program; if not, write to the Free Software
     17  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     18  */
     19 
     20 #define WIN32_VERSION BASE_VERSION "-" PATCH1 PATCH2 PATCH3 PATCH4 PATCH5
     21 
     22 #include "unrealircd.h"
     23 #include <windowsx.h>
     24 #include <commctrl.h>
     25 #include <commdlg.h>
     26 #include <richedit.h>
     27 #include <Strsafe.h>
     28 #include "resource.h"
     29 #include "win.h"
     30 
     31 #define TOOLBAR_START 82
     32 #define TOOLBAR_STOP (TOOLBAR_START+20)
     33 
     34 __inline void ShowDialog(HWND *handle, HINSTANCE inst, char *template, HWND parent, 
     35 			 DLGPROC proc)
     36 {
     37 	if (!IsWindow(*handle)) 
     38 	{
     39 		*handle = CreateDialog(inst, template, parent, (DLGPROC)proc); 
     40 		ShowWindow(*handle, SW_SHOW);
     41 	}
     42 	else
     43 		SetForegroundWindow(*handle);
     44 }
     45 
     46 /* Comments:
     47  * 
     48  * DrBin did a great job with the original GUI, but he has been gone a long time.
     49  * In his absense, it was decided it would be best to continue windows development.
     50  * The new code is based on his so it will be pretty much similar in features, my
     51  * main goal is to make it more stable. A lot of what I know about GUI coding 
     52  * I learned from DrBin so thanks to him for teaching me :) -- codemastr
     53  */
     54 
     55 LRESULT CALLBACK MainDLG(HWND, UINT, WPARAM, LPARAM);
     56 LRESULT CALLBACK LicenseDLG(HWND, UINT, WPARAM, LPARAM);
     57 LRESULT CALLBACK InfoDLG(HWND, UINT, WPARAM, LPARAM);
     58 LRESULT CALLBACK CreditsDLG(HWND, UINT, WPARAM, LPARAM);
     59 LRESULT CALLBACK HelpDLG(HWND, UINT, WPARAM, LPARAM);
     60 LRESULT CALLBACK StatusDLG(HWND, UINT, WPARAM, LPARAM);
     61 LRESULT CALLBACK ConfigErrorDLG(HWND, UINT, WPARAM, LPARAM);
     62 LRESULT CALLBACK FromVarDLG(HWND, UINT, WPARAM, LPARAM, unsigned char *, unsigned char **);
     63 LRESULT CALLBACK FromFileReadDLG(HWND, UINT, WPARAM, LPARAM);
     64 LRESULT CALLBACK FromFileDLG(HWND, UINT, WPARAM, LPARAM);
     65 
     66 HBRUSH MainDlgBackground;
     67 
     68 extern void SocketLoop(void *dummy);
     69 HINSTANCE hInst;
     70 NOTIFYICONDATA SysTray;
     71 HTREEITEM AddItemToTree(HWND, LPSTR, int, short);
     72 void win_map(Client *, HWND, short);
     73 extern Link *Servers;
     74 unsigned char *errors = NULL;
     75 extern VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv);
     76 void CleanUp(void)
     77 {
     78 	Shell_NotifyIcon(NIM_DELETE ,&SysTray);
     79 }
     80 HWND hStatusWnd;
     81 HWND hwIRCDWnd=NULL;
     82 HWND hwTreeView;
     83 HWND hWndMod;
     84 UINT WM_TASKBARCREATED, WM_FINDMSGSTRING;
     85 FARPROC lpfnOldWndProc;
     86 HMENU hContext;
     87 char OSName[OSVER_SIZE];
     88 
     89 void TaskBarCreated() 
     90 {
     91 	HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(ICO_MAIN), IMAGE_ICON,16, 16, 0);
     92 	SysTray.cbSize = sizeof(NOTIFYICONDATA);
     93 	SysTray.hIcon = hIcon;
     94 	SysTray.hWnd = hwIRCDWnd;
     95 	SysTray.uCallbackMessage = WM_USER;
     96 	SysTray.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
     97 	SysTray.uID = 0;
     98 	strcpy(SysTray.szTip, WIN32_VERSION);
     99 	Shell_NotifyIcon(NIM_ADD ,&SysTray);
    100 }
    101 
    102 LRESULT LinkSubClassFunc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) 
    103 {
    104 	static HCURSOR hCursor;
    105 	if (!hCursor)
    106 		hCursor = LoadCursor(hInst, MAKEINTRESOURCE(CUR_HAND));
    107 	if (Message == WM_MOUSEMOVE || Message == WM_LBUTTONDOWN)
    108 		SetCursor(hCursor);
    109 
    110 	return CallWindowProc((WNDPROC)lpfnOldWndProc, hWnd, Message, wParam, lParam);
    111 }
    112 
    113 
    114 
    115 LRESULT RESubClassFunc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) 
    116 {
    117 	POINT p;
    118 	RECT r;
    119 	DWORD start, end;
    120 	unsigned char string[500];
    121 
    122 	if (Message == WM_GETDLGCODE)
    123 		return DLGC_WANTALLKEYS;
    124 
    125 	
    126 	if (Message == WM_CONTEXTMENU) 
    127 	{
    128 		p.x = GET_X_LPARAM(lParam);
    129 		p.y = GET_Y_LPARAM(lParam);
    130 		if (GET_X_LPARAM(lParam) == -1 && GET_Y_LPARAM(lParam) == -1) 
    131 		{
    132 			GetClientRect(hWnd, &r);
    133 			p.x = (int)((r.left + r.right)/2);
    134 			p.y = (int)((r.top + r.bottom)/2);
    135 			ClientToScreen(hWnd,&p);
    136 		}
    137 		if (!SendMessage(hWnd, EM_CANUNDO, 0, 0)) 
    138 			EnableMenuItem(hContext, IDM_UNDO, MF_BYCOMMAND|MF_GRAYED);
    139 		else
    140 			EnableMenuItem(hContext, IDM_UNDO, MF_BYCOMMAND|MF_ENABLED);
    141 		if (!SendMessage(hWnd, EM_CANPASTE, 0, 0)) 
    142 			EnableMenuItem(hContext, IDM_PASTE, MF_BYCOMMAND|MF_GRAYED);
    143 		else
    144 			EnableMenuItem(hContext, IDM_PASTE, MF_BYCOMMAND|MF_ENABLED);
    145 		if (GetWindowLong(hWnd, GWL_STYLE) & ES_READONLY) 
    146 		{
    147 			EnableMenuItem(hContext, IDM_CUT, MF_BYCOMMAND|MF_GRAYED);
    148 			EnableMenuItem(hContext, IDM_DELETE, MF_BYCOMMAND|MF_GRAYED);
    149 		}
    150 		else 
    151 		{
    152 			EnableMenuItem(hContext, IDM_CUT, MF_BYCOMMAND|MF_ENABLED);
    153 			EnableMenuItem(hContext, IDM_DELETE, MF_BYCOMMAND|MF_ENABLED);
    154 		}
    155 		SendMessage(hWnd, EM_GETSEL, (WPARAM)&start, (LPARAM)&end);
    156 		if (start == end) 
    157 			EnableMenuItem(hContext, IDM_COPY, MF_BYCOMMAND|MF_GRAYED);
    158 		else
    159 			EnableMenuItem(hContext, IDM_COPY, MF_BYCOMMAND|MF_ENABLED);
    160 		TrackPopupMenu(hContext,TPM_LEFTALIGN|TPM_RIGHTBUTTON,p.x,p.y,0,GetParent(hWnd),NULL);
    161 		return 0;
    162 	}
    163 
    164 	return CallWindowProc((WNDPROC)lpfnOldWndProc, hWnd, Message, wParam, lParam);
    165 }
    166 
    167 int DoCloseUnreal(HWND hWnd)
    168 {
    169 	unreal_log(ULOG_INFO, "main", "UNREALIRCD_STOP", NULL,
    170 	           "Terminating server (process termination requested or GUI window closed)");
    171 	loop.terminating = 1;
    172 	unload_all_modules();
    173 	DestroyWindow(hWnd);
    174 	TerminateProcess(GetCurrentProcess(), 0);
    175 	exit(0); /* in case previous fails (possible?) */
    176 }
    177 
    178 int AskCloseUnreal(HWND hWnd)
    179 {
    180 	if (MessageBox(hWnd, "Close UnrealIRCd?", "Are you sure?", MB_YESNO|MB_ICONQUESTION) == IDNO)
    181 		 return 0;
    182 	DoCloseUnreal(hWnd);
    183 	exit(0);
    184 }
    185 
    186 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    187 {
    188 	MSG msg;
    189 	unsigned char *s;
    190 	HWND hWnd;
    191 	HICON hIcon;
    192 	SC_HANDLE hService, hSCManager;
    193 	SERVICE_TABLE_ENTRY DispatchTable[] = 
    194 	{
    195 		{ "UnrealIRCd", ServiceMain },
    196 		{ 0, 0 }
    197 	};
    198 	DWORD need;
    199 	
    200 	/* Go one level up, since we are currently in the bin\ subdir
    201 	 * and we want to be in (f.e.) "C:\Program Files\UnrealIRCd 6"
    202 	 */
    203 	chdir("..");
    204 
    205 	GetOSName(OSName);
    206 
    207 	/* Check if we are running as a service... */
    208 	hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    209 	if ((hService = OpenService(hSCManager, "UnrealIRCd", SC_MANAGER_CONNECT)))
    210 	{
    211 		int save_err = 0;
    212 		StartServiceCtrlDispatcher(DispatchTable);
    213 		if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
    214 		{
    215 			SERVICE_STATUS status;
    216 			/* Restart handling, it's ugly but it's as
    217 			 * pretty as it is gonna get :)
    218 			 */
    219 			if (__argc == 2 && !strcmp(__argv[1], "restartsvc"))
    220 			{
    221 				QueryServiceStatus(hService, &status);
    222 				if (status.dwCurrentState != SERVICE_STOPPED)
    223 				{
    224 					ControlService(hService,
    225 						SERVICE_CONTROL_STOP, &status);
    226 					while (status.dwCurrentState == SERVICE_STOP_PENDING)
    227 					{
    228 						QueryServiceStatus(hService, &status);
    229 						if (status.dwCurrentState != SERVICE_STOPPED)
    230 							Sleep(1000);
    231 					}
    232 				}
    233 			}
    234 			if (!StartService(hService, 0, NULL))
    235 				save_err = GetLastError();
    236 		}
    237 
    238 		CloseServiceHandle(hService);
    239 		CloseServiceHandle(hSCManager);
    240 		if (save_err != ERROR_SERVICE_DISABLED)
    241 			exit(0);
    242 	} else {
    243 		CloseServiceHandle(hSCManager);
    244 	}
    245 	InitCommonControls();
    246 	WM_TASKBARCREATED = RegisterWindowMessage("TaskbarCreated");
    247 	WM_FINDMSGSTRING = RegisterWindowMessage(FINDMSGSTRING);
    248 	atexit(CleanUp);
    249 	if (!LoadLibrary("riched20.dll"))
    250 		LoadLibrary("riched32.dll");
    251 	InitDebug();
    252 	init_winsock();
    253 	hInst = hInstance; 
    254 
    255 	MainDlgBackground = CreateSolidBrush(RGB(75, 134, 238)); /* Background of main dialog */
    256 
    257 	hWnd = CreateDialog(hInstance, "UnrealIRCd", 0, (DLGPROC)MainDLG); 
    258 	hwIRCDWnd = hWnd;
    259 	
    260 	TaskBarCreated();
    261 
    262 	if (InitUnrealIRCd(__argc, __argv) != 1)
    263 	{
    264 		MessageBox(NULL, "UnrealIRCd has failed to initialize in InitUnrealIRCd()", "UnrealIRCD Initalization Error" ,MB_OK);
    265 		return FALSE;
    266 	}
    267 	ShowWindow(hWnd, SW_SHOW);
    268 	_beginthread(SocketLoop, 0, NULL);
    269 	while (GetMessage(&msg, NULL, 0, 0))
    270 	{
    271 		if (!IsWindow(hStatusWnd) || !IsDialogMessage(hStatusWnd, &msg)) 
    272 		{
    273 			TranslateMessage(&msg);
    274 			DispatchMessage(&msg);
    275 		}
    276 	}
    277 	return FALSE;
    278 
    279 }
    280 
    281 LRESULT CALLBACK MainDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    282 {
    283 	static HCURSOR hCursor;
    284 	static HMENU hRehash, hAbout, hConfig, hTray, hLogs;
    285 
    286 	unsigned char *argv[3];
    287 	Client *pClient;
    288 	unsigned char *msg;
    289 	POINT p;
    290 
    291 	if (message == WM_TASKBARCREATED)
    292 	{
    293 		TaskBarCreated();
    294 		return TRUE;
    295 	}
    296 	
    297 	switch (message)
    298 	{
    299 		case WM_INITDIALOG: 
    300 		{
    301 			ShowWindow(hDlg, SW_HIDE);
    302 			hCursor = LoadCursor(hInst, MAKEINTRESOURCE(CUR_HAND));
    303 			hContext = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(MENU_CONTEXT)),0);
    304 			/* Rehash popup menu */
    305 			hRehash = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(MENU_REHASH)),0);
    306 			/* About popup menu */
    307 			hAbout = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(MENU_ABOUT)),0);
    308 			/* Systray popup menu set the items to point to the other menus*/
    309 			hTray = GetSubMenu(LoadMenu(hInst, MAKEINTRESOURCE(MENU_SYSTRAY)),0);
    310 			ModifyMenu(hTray, IDM_REHASH, MF_BYCOMMAND|MF_POPUP|MF_STRING, HandleToUlong(hRehash), "&Rehash");
    311 			ModifyMenu(hTray, IDM_ABOUT, MF_BYCOMMAND|MF_POPUP|MF_STRING, HandleToUlong(hAbout), "&About");
    312 			
    313 			SetWindowText(hDlg, WIN32_VERSION);
    314 			SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_SMALL, 
    315 				(LPARAM)(HICON)LoadImage(hInst, MAKEINTRESOURCE(ICO_MAIN), IMAGE_ICON,16, 16, 0));
    316 			SendMessage(hDlg, WM_SETICON, (WPARAM)ICON_BIG, 
    317 				(LPARAM)(HICON)LoadImage(hInst, MAKEINTRESOURCE(ICO_MAIN), IMAGE_ICON,32, 32, 0));
    318 			return TRUE;
    319 		}
    320 		case WM_CTLCOLORDLG:
    321 			return (LONG)HandleToLong(MainDlgBackground);
    322 		case WM_SIZE: 
    323 		{
    324 			if (wParam & SIZE_MINIMIZED)
    325 				ShowWindow(hDlg,SW_HIDE);
    326 			return 0;
    327 		}
    328 		case WM_CLOSE: 
    329 			return DoCloseUnreal(hDlg);
    330 		case WM_USER: 
    331 		{
    332 			switch(LOWORD(lParam)) 
    333 			{
    334 				case WM_LBUTTONDBLCLK:
    335 					ShowWindow(hDlg, SW_SHOW);
    336 					ShowWindow(hDlg,SW_RESTORE);
    337 					SetForegroundWindow(hDlg);
    338 				case WM_RBUTTONDOWN:
    339 					SetForegroundWindow(hDlg);
    340 					break;
    341 				case WM_RBUTTONUP: 
    342 				{
    343 					unsigned long i = 60000;
    344 					MENUITEMINFO mii;
    345 					GetCursorPos(&p);
    346 					DestroyMenu(hConfig);
    347 					hConfig = CreatePopupMenu();
    348 					DestroyMenu(hLogs);
    349 					hLogs = CreatePopupMenu();
    350 					AppendMenu(hConfig, MF_STRING, IDM_CONF, CPATH);
    351 #if 0
    352 					if (conf_log) 
    353 					{
    354 						ConfigItem_log *logs;
    355 						AppendMenu(hConfig, MF_POPUP|MF_STRING, HandleToUlong(hLogs), "Logs");
    356 						for (logs = conf_log; logs; logs = logs->next)
    357 						{
    358 							AppendMenu(hLogs, MF_STRING, i++, logs->file);
    359 						}
    360 					}
    361 					AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    362 #endif
    363 					if (conf_files)
    364 					{
    365 						AppendMenu(hConfig, MF_STRING, IDM_MOTD, conf_files->motd_file);
    366 						AppendMenu(hConfig, MF_STRING, IDM_SMOTD, conf_files->smotd_file);
    367 						AppendMenu(hConfig, MF_STRING, IDM_OPERMOTD, conf_files->opermotd_file);
    368 						AppendMenu(hConfig, MF_STRING, IDM_BOTMOTD, conf_files->botmotd_file);
    369 						AppendMenu(hConfig, MF_STRING, IDM_RULES, conf_files->rules_file);
    370 					}
    371 						
    372 					if (conf_tld) 
    373 					{
    374 						ConfigItem_tld *tlds;
    375 						AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    376 						for (tlds = conf_tld; tlds; tlds = tlds->next)
    377 						{
    378 							if (!tlds->flag.motdptr)
    379 								AppendMenu(hConfig, MF_STRING, i++, tlds->motd_file);
    380 							if (!tlds->flag.ruleclient)
    381 								AppendMenu(hConfig, MF_STRING, i++, tlds->rules_file);
    382 							if (tlds->smotd_file)
    383 								AppendMenu(hConfig, MF_STRING, i++, tlds->smotd_file);
    384 						}
    385 					}
    386 					AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    387 					AppendMenu(hConfig, MF_STRING, IDM_NEW, "New File");
    388 					mii.cbSize = sizeof(MENUITEMINFO);
    389 					mii.fMask = MIIM_SUBMENU;
    390 					mii.hSubMenu = hConfig;
    391 					SetMenuItemInfo(hTray, IDM_CONFIG, MF_BYCOMMAND, &mii);
    392 					TrackPopupMenu(hTray, TPM_LEFTALIGN|TPM_LEFTBUTTON,p.x,p.y,0,hDlg,NULL);
    393 					/* Kludge for a win bug */
    394 					SendMessage(hDlg, WM_NULL, 0, 0);
    395 					break;
    396 				}
    397 			}
    398 			return 0;
    399 		}
    400 		case WM_DESTROY:
    401 			return 0;
    402 		case WM_MOUSEMOVE: 
    403 		{
    404 			POINT p;
    405 			p.x = LOWORD(lParam);
    406 			p.y = HIWORD(lParam);
    407 			if ((p.x >= 93) && (p.x <= 150) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    408 				SetCursor(hCursor);
    409 			else if ((p.x >= 160) && (p.x <= 208) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    410 				SetCursor(hCursor);
    411 			else if ((p.x >= 219) && (p.x <= 267) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    412 				SetCursor(hCursor);
    413 			else if ((p.x >= 279) && (p.x <= 325) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    414 				SetCursor(hCursor);
    415 			else if ((p.x >= 336) && (p.x <= 411) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    416 				SetCursor(hCursor);
    417 			return 0;
    418 		}
    419 		case WM_LBUTTONDOWN: 
    420 		{
    421 			POINT p;
    422 			p.x = LOWORD(lParam);
    423 			p.y = HIWORD(lParam);
    424 			if ((p.x >= 93) && (p.x <= 150) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP))
    425 			{
    426 				ClientToScreen(hDlg,&p);
    427 				TrackPopupMenu(hRehash,TPM_LEFTALIGN|TPM_LEFTBUTTON,p.x,p.y,0,hDlg,NULL);
    428 				return 0;
    429 			}
    430 			else if ((p.x >= 160) && (p.x <= 208) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP))
    431 			{
    432 				ShowDialog(&hStatusWnd, hInst, "Status", hDlg, StatusDLG);
    433 				return 0;
    434 			}
    435 			else if ((p.x >= 219) && (p.x <= 267) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP))
    436 			{
    437 				unsigned long i = 60000;
    438 				ClientToScreen(hDlg,&p);
    439 				DestroyMenu(hConfig);
    440 				hConfig = CreatePopupMenu();
    441 				DestroyMenu(hLogs);
    442 				hLogs = CreatePopupMenu();
    443 
    444 				AppendMenu(hConfig, MF_STRING, IDM_CONF, CPATH);
    445 #if 0
    446 				if (conf_log) 
    447 				{
    448 					ConfigItem_log *logs;
    449 					AppendMenu(hConfig, MF_POPUP|MF_STRING, HandleToUlong(hLogs), "Logs");
    450 					for (logs = conf_log; logs; logs = logs->next)
    451 					{
    452 						AppendMenu(hLogs, MF_STRING, i++, logs->file);
    453 					}
    454 				}
    455 				AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    456 #endif
    457 				if (conf_files)
    458 				{
    459 					AppendMenu(hConfig, MF_STRING, IDM_MOTD, conf_files->motd_file);
    460 					AppendMenu(hConfig, MF_STRING, IDM_SMOTD, conf_files->smotd_file);
    461 					AppendMenu(hConfig, MF_STRING, IDM_OPERMOTD, conf_files->opermotd_file);
    462 					AppendMenu(hConfig, MF_STRING, IDM_BOTMOTD, conf_files->botmotd_file);
    463 					AppendMenu(hConfig, MF_STRING, IDM_RULES, conf_files->rules_file);
    464 				}
    465 				
    466 				if (conf_tld) 
    467 				{
    468 					ConfigItem_tld *tlds;
    469 					AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    470 					for (tlds = conf_tld; tlds; tlds = tlds->next)
    471 					{
    472 						if (!tlds->flag.motdptr)
    473 							AppendMenu(hConfig, MF_STRING, i++, tlds->motd_file);
    474 						if (!tlds->flag.ruleclient)
    475 							AppendMenu(hConfig, MF_STRING, i++, tlds->rules_file);
    476 						if (tlds->smotd_file)
    477 							AppendMenu(hConfig, MF_STRING, i++, tlds->smotd_file);
    478 					}
    479 				}
    480 				AppendMenu(hConfig, MF_SEPARATOR, 0, NULL);
    481 				AppendMenu(hConfig, MF_STRING, IDM_NEW, "New File");
    482 				TrackPopupMenu(hConfig,TPM_LEFTALIGN|TPM_LEFTBUTTON,p.x,p.y,0,hDlg,NULL);
    483 
    484 				return 0;
    485 			}
    486 			else if ((p.x >= 279) && (p.x <= 325) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    487 			{
    488 				ClientToScreen(hDlg,&p);
    489 				TrackPopupMenu(hAbout,TPM_LEFTALIGN|TPM_LEFTBUTTON,p.x,p.y,0,hDlg,NULL);
    490 				return 0;
    491 			}
    492 			else if ((p.x >= 336) && (p.x <= 411) && (p.y >= TOOLBAR_START) && (p.y <= TOOLBAR_STOP)) 
    493 				return AskCloseUnreal(hDlg);
    494 		}
    495 		case WM_SYSCOMMAND:
    496 		{
    497 			if (wParam == SC_CLOSE)
    498 			{
    499 				AskCloseUnreal(hDlg);
    500 				return 1;
    501 			}
    502 			break;
    503 		}
    504 		case WM_COMMAND: 
    505 		{
    506 			if (LOWORD(wParam) >= 60000 && HIWORD(wParam) == 0 && !lParam) 
    507 			{
    508 				unsigned char path[MAX_PATH];
    509 				if (GetMenuString(hLogs, LOWORD(wParam), path, MAX_PATH, MF_BYCOMMAND))
    510 					DialogBoxParam(hInst, "FromVar", hDlg, (DLGPROC)FromFileReadDLG, (LPARAM)path);
    511 				
    512 				else 
    513 				{
    514 					GetMenuString(hConfig,LOWORD(wParam), path, MAX_PATH, MF_BYCOMMAND);
    515 					if (!url_is_valid(path))
    516 						DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG, (LPARAM)path);
    517 				}
    518 				return FALSE;
    519 			}
    520 
    521 			if (!loop.booted)
    522 			{
    523 				MessageBox(NULL, "UnrealIRCd not booted due to configuration errors. "
    524 				                 "Check other window for error details. Then close that window, "
    525 				                 "fix the errors and start UnrealIRCd again.",
    526 				                 "UnrealIRCd not started",
    527 				                 MB_OK);
    528 				return FALSE;
    529 			}
    530 			switch(LOWORD(wParam)) 
    531 			{
    532 				case IDM_STATUS:
    533 					ShowDialog(&hStatusWnd, hInst, "Status", hDlg,StatusDLG);
    534 					break;
    535 				case IDM_SHUTDOWN:
    536 					return AskCloseUnreal(hDlg);
    537 				case IDM_RHALL:
    538 					MessageBox(NULL, "Rehashing all files", "Rehashing", MB_OK);
    539 					dorehash = 1;
    540 					break;
    541 				case IDM_LICENSE: 
    542 					DialogBox(hInst, "FromVar", hDlg, (DLGPROC)LicenseDLG);
    543 					break;
    544 				case IDM_INFO:
    545 					DialogBox(hInst, "FromVar", hDlg, (DLGPROC)InfoDLG);
    546 					break;
    547 				case IDM_CREDITS:
    548 					DialogBox(hInst, "FromVar", hDlg, (DLGPROC)CreditsDLG);
    549 					break;
    550 				case IDM_HELP:
    551 					DialogBox(hInst, "Help", hDlg, (DLGPROC)HelpDLG);
    552 					break;
    553 				case IDM_CONF:
    554 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG, 
    555 						(LPARAM)CPATH);
    556 					break;
    557 				case IDM_MOTD:
    558 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG, 
    559 						(LPARAM)conf_files->motd_file);
    560 					break;
    561 				case IDM_SMOTD:
    562 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG, 
    563 						(LPARAM)conf_files->smotd_file);
    564 					break;
    565 				case IDM_OPERMOTD:
    566 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG,
    567 						(LPARAM)conf_files->opermotd_file);
    568 					break;
    569 				case IDM_BOTMOTD:
    570 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG,
    571 						(LPARAM)conf_files->botmotd_file);
    572 					break;
    573 				case IDM_RULES:
    574 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG,
    575 						(LPARAM)conf_files->rules_file);
    576 					break;
    577 				case IDM_NEW:
    578 					DialogBoxParam(hInst, "FromFile", hDlg, (DLGPROC)FromFileDLG, (LPARAM)NULL);
    579 					break;
    580 			}
    581 		}
    582 	}
    583 	return FALSE;
    584 }
    585 
    586 LRESULT CALLBACK LicenseDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    587 {
    588 	return FromVarDLG(hDlg, message, wParam, lParam, "UnrealIRCd License", gnulicense);
    589 }
    590 
    591 LRESULT CALLBACK InfoDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    592 {
    593 	return FromVarDLG(hDlg, message, wParam, lParam, "UnrealIRCd Team", unrealinfo);
    594 }
    595 
    596 LRESULT CALLBACK CreditsDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    597 {
    598 	return FromVarDLG(hDlg, message, wParam, lParam, "UnrealIRCd Credits", unrealcredits);
    599 }
    600 
    601 LRESULT CALLBACK FromVarDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam,
    602                             unsigned char *title, unsigned char **s) 
    603 {
    604 	HWND hWnd;
    605 	switch (message) 
    606 	{
    607 		case WM_INITDIALOG: 
    608 		{
    609 #if 0
    610 			unsigned char	String[16384];
    611 			int size;
    612 			unsigned char *RTFString;
    613 			StreamIO *stream = safe_alloc(sizeof(StreamIO));
    614 			EDITSTREAM edit;
    615 			SetWindowText(hDlg, title);
    616 			memset(String, 0, sizeof(String));
    617 			lpfnOldWndProc = (FARPROC)SetWindowLongPtr(GetDlgItem(hDlg, IDC_TEXT), GWLP_WNDPROC, (LONG_PTR)RESubClassFunc);
    618 			while (*s) 
    619 			{
    620 				strcat(String, *s++);
    621 				if (*s)
    622 					strcat(String, "\r\n");
    623 			}
    624 			size = CountRTFSize(String)+1;
    625 			RTFString = safe_alloc(size);
    626 			IRCToRTF(String,RTFString);
    627 			RTFBuf = RTFString;
    628 			size--;
    629 			stream->size = &size;
    630 			stream->buffer = &RTFBuf;
    631 			edit.dwCookie = HandleToUlong(stream);
    632 			edit.pfnCallback = SplitIt;
    633 			SendMessage(GetDlgItem(hDlg, IDC_TEXT), EM_STREAMIN, (WPARAM)SF_RTF|SFF_PLAINRTF, (LPARAM)&edit);
    634 			safe_free(RTFString);
    635 			safe_free(stream);
    636 			return TRUE;
    637 #else
    638 			return FALSE;
    639 #endif
    640 		}
    641 
    642 		case WM_COMMAND: 
    643 		{
    644 			hWnd = GetDlgItem(hDlg, IDC_TEXT);
    645 			if (LOWORD(wParam) == IDOK)
    646 				return EndDialog(hDlg, TRUE);
    647 			if (LOWORD(wParam) == IDM_COPY) 
    648 			{
    649 				SendMessage(hWnd, WM_COPY, 0, 0);
    650 				return 0;
    651 			}
    652 			if (LOWORD(wParam) == IDM_SELECTALL) 
    653 			{
    654 				SendMessage(hWnd, EM_SETSEL, 0, -1);
    655 				return 0;
    656 			}
    657 			if (LOWORD(wParam) == IDM_PASTE) 
    658 			{
    659 				SendMessage(hWnd, WM_PASTE, 0, 0);
    660 				return 0;
    661 			}
    662 			if (LOWORD(wParam) == IDM_CUT) 
    663 			{
    664 				SendMessage(hWnd, WM_CUT, 0, 0);
    665 				return 0;
    666 			}
    667 			if (LOWORD(wParam) == IDM_UNDO) 
    668 			{
    669 				SendMessage(hWnd, EM_UNDO, 0, 0);
    670 				return 0;
    671 			}
    672 			if (LOWORD(wParam) == IDM_DELETE) 
    673 			{
    674 				SendMessage(hWnd, WM_CLEAR, 0, 0);
    675 				return 0;
    676 			}
    677 			break;
    678 		}
    679 		case WM_CLOSE:
    680 			EndDialog(hDlg, TRUE);
    681 			break;
    682 		case WM_DESTROY:
    683 			break;
    684 	}
    685 	return (FALSE);
    686 }
    687 
    688 LRESULT CALLBACK FromFileReadDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    689 {
    690 	HWND hWnd;
    691 	switch (message) 
    692 	{
    693 		case WM_INITDIALOG: 
    694 		{
    695 			int fd,len;
    696 			unsigned char *buffer = '\0', *string = '\0';
    697 			EDITSTREAM edit;
    698 			StreamIO *stream = safe_alloc(sizeof(StreamIO));
    699 			unsigned char szText[256];
    700 			struct stat sb;
    701 			HWND hWnd = GetDlgItem(hDlg, IDC_TEXT), hTip;
    702 			StringCbPrintf(szText, sizeof(szText), "UnrealIRCd Viewer - %s", (unsigned char *)lParam);
    703 			SetWindowText(hDlg, szText);
    704 			lpfnOldWndProc = (FARPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)RESubClassFunc);
    705 			if ((fd = open((unsigned char *)lParam, _O_RDONLY|_O_BINARY)) != -1) 
    706 			{
    707 				fstat(fd,&sb);
    708 				/* Only allocate the amount we need */
    709 				buffer = safe_alloc(sb.st_size+1);
    710 				buffer[0] = 0;
    711 				len = read(fd, buffer, sb.st_size); 
    712 				buffer[len] = 0;
    713 				len = CountRTFSize(buffer)+1;
    714 				string = safe_alloc(len);
    715 				IRCToRTF(buffer,string);
    716 				RTFBuf = string;
    717 				len--;
    718 				stream->size = &len;
    719 				stream->buffer = &RTFBuf;
    720 				edit.dwCookie = (DWORD_PTR)stream;
    721 				edit.pfnCallback = SplitIt;
    722 				SendMessage(hWnd, EM_EXLIMITTEXT, 0, (LPARAM)0x7FFFFFFF);
    723 				SendMessage(hWnd, EM_STREAMIN, (WPARAM)SF_RTF|SFF_PLAINRTF, (LPARAM)&edit);
    724 				close(fd);
    725 				RTFBuf = NULL;
    726 				safe_free(buffer);
    727 				safe_free(string);
    728 				safe_free(stream);
    729 			}
    730 			return TRUE;
    731 		}
    732 		case WM_COMMAND: 
    733 		{
    734 			hWnd = GetDlgItem(hDlg, IDC_TEXT);
    735 			if (LOWORD(wParam) == IDOK)
    736 				return EndDialog(hDlg, TRUE);
    737 			if (LOWORD(wParam) == IDM_COPY) 
    738 			{
    739 				SendMessage(hWnd, WM_COPY, 0, 0);
    740 				return 0;
    741 			}
    742 			if (LOWORD(wParam) == IDM_SELECTALL) 
    743 			{
    744 				SendMessage(hWnd, EM_SETSEL, 0, -1);
    745 				return 0;
    746 			}
    747 			if (LOWORD(wParam) == IDM_PASTE) 
    748 			{
    749 				SendMessage(hWnd, WM_PASTE, 0, 0);
    750 				return 0;
    751 			}
    752 			if (LOWORD(wParam) == IDM_CUT) 
    753 			{
    754 				SendMessage(hWnd, WM_CUT, 0, 0);
    755 				return 0;
    756 			}
    757 			if (LOWORD(wParam) == IDM_UNDO) 
    758 			{
    759 				SendMessage(hWnd, EM_UNDO, 0, 0);
    760 				return 0;
    761 			}
    762 			if (LOWORD(wParam) == IDM_DELETE) 
    763 			{
    764 				SendMessage(hWnd, WM_CLEAR, 0, 0);
    765 				return 0;
    766 			}
    767 			break;
    768 		}
    769 		case WM_CLOSE:
    770 			EndDialog(hDlg, TRUE);
    771 			break;
    772 		case WM_DESTROY:
    773 			break;
    774 	}
    775 	return FALSE;
    776 }
    777 
    778 LRESULT CALLBACK HelpDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    779 {
    780 	static HFONT hFont;
    781 	static HCURSOR hCursor;
    782 	switch (message) 
    783 	{
    784 		case WM_INITDIALOG:
    785 			hCursor = LoadCursor(hInst, MAKEINTRESOURCE(CUR_HAND));
    786 			hFont = CreateFont(8,0,0,0,0,0,1,0,ANSI_CHARSET,0,0,PROOF_QUALITY,0,"MS Sans Serif");
    787 			SendMessage(GetDlgItem(hDlg, IDC_EMAIL), WM_SETFONT, (WPARAM)hFont,TRUE);
    788 			SendMessage(GetDlgItem(hDlg, IDC_URL), WM_SETFONT, (WPARAM)hFont,TRUE);
    789 			lpfnOldWndProc = (FARPROC)SetWindowLongPtr(GetDlgItem(hDlg, IDC_EMAIL), GWLP_WNDPROC, (LONG_PTR)LinkSubClassFunc);
    790 			SetWindowLongPtr(GetDlgItem(hDlg, IDC_URL), GWLP_WNDPROC, (LONG_PTR)LinkSubClassFunc);
    791 			return TRUE;
    792 
    793 		case WM_DRAWITEM: 
    794 		{
    795 			LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;
    796 			unsigned char text[500];
    797 			COLORREF oldtext;
    798 			RECT focus;
    799 			GetWindowText(lpdis->hwndItem, text, 500);
    800 			if (wParam == IDC_URL || IDC_EMAIL) 
    801 			{
    802 				FillRect(lpdis->hDC, &lpdis->rcItem, GetSysColorBrush(COLOR_3DFACE));
    803 				oldtext = SetTextColor(lpdis->hDC, RGB(0,0,255));
    804 				DrawText(lpdis->hDC, text, strlen(text), &lpdis->rcItem, DT_CENTER|DT_VCENTER);
    805 				SetTextColor(lpdis->hDC, oldtext);
    806 				if (lpdis->itemState & ODS_FOCUS) 
    807 				{
    808 					CopyRect(&focus, &lpdis->rcItem);
    809 					focus.left += 2;
    810 					focus.right -= 2;
    811 					focus.top += 1;
    812 					focus.bottom -= 1;
    813 					DrawFocusRect(lpdis->hDC, &focus);
    814 				}
    815 				return TRUE;
    816 			}
    817 		}	
    818 		case WM_COMMAND:
    819 			if (LOWORD(wParam) == IDOK)
    820 				EndDialog(hDlg, TRUE);
    821 			if (HIWORD(wParam) == BN_DBLCLK) 
    822 			{
    823 				if (LOWORD(wParam) == IDC_URL) 
    824 					ShellExecute(NULL, "open", "https://www.unrealircd.org", NULL, NULL, 
    825 						SW_MAXIMIZE);
    826 				else if (LOWORD(wParam) == IDC_EMAIL)
    827 					ShellExecute(NULL, "open", "mailto:unreal-users@lists.sourceforge.net", NULL, NULL, 
    828 						SW_MAXIMIZE);
    829 				EndDialog(hDlg, TRUE);
    830 				return 0;
    831 			}
    832 			break;
    833 		case WM_CLOSE:
    834 			EndDialog(hDlg, TRUE);
    835 			break;
    836 		case WM_DESTROY:
    837 			DeleteObject(hFont);
    838 			break;
    839 
    840 	}
    841 	return FALSE;
    842 }
    843 
    844 
    845 
    846 
    847 
    848 
    849 
    850 
    851 LRESULT CALLBACK StatusDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
    852 {
    853 	switch (message) 
    854 	{
    855 		case WM_INITDIALOG: 
    856 		{
    857 			hwTreeView = GetDlgItem(hDlg, IDC_TREE);
    858 			win_map(&me, hwTreeView, 0);
    859 			SetDlgItemInt(hDlg, IDC_CLIENTS, irccounts.clients, FALSE);
    860 			SetDlgItemInt(hDlg, IDC_SERVERS, irccounts.servers, FALSE);
    861 			SetDlgItemInt(hDlg, IDC_INVISO, irccounts.invisible, FALSE);
    862 			SetDlgItemInt(hDlg, IDC_UNKNOWN, irccounts.unknown, FALSE);
    863 			SetDlgItemInt(hDlg, IDC_OPERS, irccounts.operators, FALSE);
    864 			SetDlgItemInt(hDlg, IDC_CHANNELS, irccounts.channels, FALSE);
    865 			if (irccounts.clients > irccounts.global_max)
    866 				irccounts.global_max = irccounts.clients;
    867 			if (irccounts.me_clients > irccounts.me_max)
    868 					irccounts.me_max = irccounts.me_clients;
    869 			SetDlgItemInt(hDlg, IDC_MAXCLIENTS, irccounts.global_max, FALSE);
    870 			SetDlgItemInt(hDlg, IDC_LCLIENTS, irccounts.me_clients, FALSE);
    871 			SetDlgItemInt(hDlg, IDC_LSERVERS, irccounts.me_servers, FALSE);
    872 			SetDlgItemInt(hDlg, IDC_LMAXCLIENTS, irccounts.me_max, FALSE);
    873 			SetTimer(hDlg, 1, 5000, NULL);
    874 			return TRUE;
    875 		}
    876 		case WM_CLOSE:
    877 			DestroyWindow(hDlg);
    878 			return TRUE;
    879 		case WM_TIMER:
    880 			TreeView_DeleteAllItems(hwTreeView);
    881 			win_map(&me, hwTreeView, 1);
    882 			SetDlgItemInt(hDlg, IDC_CLIENTS, irccounts.clients, FALSE);
    883 			SetDlgItemInt(hDlg, IDC_SERVERS, irccounts.servers, FALSE);
    884 			SetDlgItemInt(hDlg, IDC_INVISO, irccounts.invisible, FALSE);
    885 			SetDlgItemInt(hDlg, IDC_INVISO, irccounts.invisible, FALSE);
    886 			SetDlgItemInt(hDlg, IDC_UNKNOWN, irccounts.unknown, FALSE);
    887 			SetDlgItemInt(hDlg, IDC_OPERS, irccounts.operators, FALSE);
    888 			SetDlgItemInt(hDlg, IDC_CHANNELS, irccounts.channels, FALSE);
    889 			if (irccounts.clients > irccounts.global_max)
    890 				irccounts.global_max = irccounts.clients;
    891 			if (irccounts.me_clients > irccounts.me_max)
    892 					irccounts.me_max = irccounts.me_clients;
    893 			SetDlgItemInt(hDlg, IDC_MAXCLIENTS, irccounts.global_max, FALSE);
    894 			SetDlgItemInt(hDlg, IDC_LCLIENTS, irccounts.me_clients, FALSE);
    895 			SetDlgItemInt(hDlg, IDC_LSERVERS, irccounts.me_servers, FALSE);
    896 			SetDlgItemInt(hDlg, IDC_LMAXCLIENTS, irccounts.me_max, FALSE);
    897 			SetTimer(hDlg, 1, 5000, NULL);
    898 			return TRUE;
    899 		case WM_COMMAND:
    900 			if (LOWORD(wParam) == IDOK) 
    901 			{
    902 				DestroyWindow(hDlg);
    903 				return TRUE;
    904 			}
    905 			break;
    906 
    907 	}
    908 	return FALSE;
    909 }
    910 
    911 /* This was made by DrBin but I cleaned it up a bunch to make it work better */
    912 
    913 HTREEITEM AddItemToTree(HWND hWnd, LPSTR lpszItem, int nLevel, short remap)
    914 {
    915 	TVITEM tvi; 
    916 	TVINSERTSTRUCT tvins; 
    917 	static HTREEITEM hPrev = (HTREEITEM)TVI_FIRST; 
    918 	static HTREEITEM hPrevLev[10] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
    919 	HTREEITEM hti; 
    920 
    921 	if (remap) 
    922 	{
    923 		hPrev = (HTREEITEM)TVI_FIRST;
    924 		memset(hPrevLev, 0, sizeof(HTREEITEM)*10);
    925 	}
    926 		
    927 	tvi.mask = TVIF_TEXT|TVIF_PARAM; 
    928 	tvi.pszText = lpszItem; 
    929 	tvi.cchTextMax = lstrlen(lpszItem); 
    930 	tvi.lParam = (LPARAM)nLevel; 
    931 	tvins.item = tvi; 
    932 	tvins.hInsertAfter = hPrev; 
    933 	if (nLevel == 1) 
    934 		tvins.hParent = TVI_ROOT; 
    935 	else 
    936 		tvins.hParent = hPrevLev[nLevel-1];
    937 	hPrev = (HTREEITEM)SendMessage(hWnd, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT) &tvins); 
    938 	hPrevLev[nLevel] = hPrev;
    939 	TreeView_EnsureVisible(hWnd,hPrev);
    940 	if (nLevel > 1) 
    941 	{ 
    942 		hti = TreeView_GetParent(hWnd, hPrev); 
    943 		tvi.mask = TVIF_IMAGE|TVIF_SELECTEDIMAGE; 
    944 		tvi.hItem = hti; 
    945 		TreeView_SetItem(hWnd, &tvi); 
    946 	} 
    947 	return hPrev; 
    948 }
    949 
    950 /*
    951  * Now used to create list of servers for server list tree view -- David Flynn
    952  * Recoded by codemastr to be faster.
    953  * I removed the Potvin credit because it no longer uses any original code and I don't
    954  * even think Potvin actually made the original code
    955  */
    956 void win_map(Client *server, HWND hwTreeView, short remap)
    957 {
    958 /*
    959 	Client *acptr;
    960 	Link *lp;
    961 
    962 	AddItemToTree(hwTreeView,server->name,server->hopcount+1, remap);
    963 
    964 	for (lp = Servers; lp; lp = lp->next)
    965         {
    966                 acptr = lp->value.client;
    967                 if (acptr->uplink != server)
    968                         continue;
    969                 win_map(acptr, hwTreeView, 0);
    970         }
    971 FIXME
    972 */
    973 }
    974 
    975 /* ugly stuff, but hey it works -- codemastr */
    976 void win_log(FORMAT_STRING(const char *format), ...)
    977 {
    978 	va_list ap;
    979 	unsigned char buf[2048];
    980 	FILE *fd;
    981 
    982 	va_start(ap, format);
    983 
    984 	ircvsnprintf(buf, sizeof(buf), format, ap);
    985 	stripcrlf(buf);
    986 
    987 	if (!IsService) 
    988 	{
    989 		strcat(buf, "\r\n");
    990 		if (errors) 
    991 		{
    992 			char *tbuf = safe_alloc(strlen(errors) + strlen(buf) + 1);
    993 			strcpy(tbuf, errors);
    994 			strcat(tbuf, buf);
    995 			safe_free(errors);
    996 			errors = tbuf;
    997 		}
    998 		else 
    999 		{
   1000 			safe_strdup(errors, buf);
   1001 		}
   1002 	}
   1003 	else 
   1004 	{
   1005 		FILE *fd = fopen("logs\\service.log", "a");
   1006 		if (fd)
   1007 		{
   1008 			char timebuf[256];
   1009 			snprintf(timebuf, sizeof(timebuf), "[%s]", myctime(time(NULL)));
   1010 			fprintf(fd, "%s - %s\n", timebuf, buf);
   1011 			fclose(fd);
   1012 		}
   1013 #ifdef _DEBUG
   1014 		else
   1015 		{
   1016 			OutputDebugString(buf);
   1017 		}
   1018 #endif
   1019 	}
   1020 	va_end(ap);
   1021 }
   1022 
   1023 void win_error() 
   1024 {
   1025 	if (errors && !IsService)
   1026 		DialogBox(hInst, "ConfigError", hwIRCDWnd, (DLGPROC)ConfigErrorDLG);
   1027 }
   1028 
   1029 LRESULT CALLBACK ConfigErrorDLG(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 
   1030 {
   1031 	switch (message) 
   1032 	{
   1033 		case WM_INITDIALOG:
   1034 			MessageBeep(MB_ICONEXCLAMATION);
   1035 			SetDlgItemText(hDlg, IDC_CONFIGERROR, errors);
   1036 			safe_free(errors);
   1037 			errors = NULL;
   1038 			return (TRUE);
   1039 		case WM_COMMAND:
   1040 			if (LOWORD(wParam) == IDOK)
   1041 				EndDialog(hDlg, TRUE);
   1042 			break;
   1043 		case WM_CLOSE:
   1044 			EndDialog(hDlg, TRUE);
   1045 			break;
   1046 		case WM_DESTROY:
   1047 			break;
   1048 
   1049 		}
   1050 	return (FALSE);
   1051 }