2d8f50c24564e7d9b00b2a4f6d0fd7daef501fdb
[public/netxms.git] / src / console / win32 / comm.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Windows Console
4 ** Copyright (C) 2004 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** $module: comm.cpp
21 ** Background communication functions
22 **
23 **/
24
25 #include "stdafx.h"
26 #include "nxcon.h"
27
28
29 //
30 // Constants
31 //
32
33 #define UI_THREAD_WAIT_TIME 300
34
35
36 //
37 // Set status text in wait window
38 //
39
40 inline void SetInfoText(HWND hWnd, char *pszText)
41 {
42 SendMessage(hWnd, WM_SET_INFO_TEXT, 0, (LPARAM)pszText);
43 }
44
45
46 //
47 // Check if MIB file is exist and up-to-date
48 //
49
50 static DWORD CheckMIBFile(char *pszName, BYTE *pHash)
51 {
52 char szFileName[MAX_PATH];
53 BYTE currHash[MD5_DIGEST_SIZE];
54 BOOL bNeedUpdate = TRUE;
55 DWORD dwResult = RCC_SUCCESS;
56
57 // Build full file name
58 strcpy(szFileName, g_szWorkDir);
59 strcat(szFileName, WORKDIR_MIBCACHE);
60 strcat(szFileName, "\\");
61 strcat(szFileName, pszName);
62
63 // Check file hash
64 if (CalculateFileMD5Hash(szFileName, currHash))
65 bNeedUpdate = memcmp(currHash, pHash, MD5_DIGEST_SIZE);
66
67 // Download file from server if needed
68 if (bNeedUpdate)
69 {
70 strcpy(szFileName, g_szWorkDir);
71 strcat(szFileName, WORKDIR_MIBCACHE);
72 dwResult = NXCDownloadMIBFile(pszName, szFileName);
73 }
74 return dwResult;
75 }
76
77
78 //
79 // Login thread
80 //
81
82 static DWORD WINAPI LoginThread(void *pArg)
83 {
84 HWND hWnd = *((HWND *)pArg); // Handle to status window
85 DWORD dwResult;
86
87 dwResult = NXCConnect(g_szServer, g_szLogin, g_szPassword);
88
89 // If successful, load container objects' categories
90 if (dwResult == RCC_SUCCESS)
91 {
92 SetInfoText(hWnd, "Loading container categories...");
93 dwResult = NXCLoadCCList(&g_pCCList);
94 }
95
96 // Synchronize objects
97 if (dwResult == RCC_SUCCESS)
98 {
99 SetInfoText(hWnd, "Synchronizing objects...");
100 dwResult = NXCSyncObjects();
101 }
102
103 if (dwResult == RCC_SUCCESS)
104 {
105 SetInfoText(hWnd, "Loading user database...");
106 dwResult = NXCLoadUserDB();
107 }
108
109 if (dwResult == RCC_SUCCESS)
110 {
111 SetInfoText(hWnd, "Loading action configuration...");
112 dwResult = NXCLoadActions(&g_dwNumActions, &g_pActionList);
113 if (dwResult == RCC_ACCESS_DENIED)
114 dwResult = RCC_SUCCESS; // User may not have rights to see actions, it's ok here
115 }
116
117 if (dwResult == RCC_SUCCESS)
118 {
119 NXC_MIB_LIST *pMibList;
120 DWORD i;
121
122 SetInfoText(hWnd, "Loading and initializing MIB files...");
123 dwResult = NXCGetMIBList(&pMibList);
124 if (dwResult == RCC_SUCCESS)
125 {
126 for(i = 0; i < pMibList->dwNumFiles; i++)
127 if ((dwResult = CheckMIBFile(pMibList->ppszName[i], pMibList->ppHash[i])) != RCC_SUCCESS)
128 break;
129 NXCDestroyMIBList(pMibList);
130 if (dwResult == RCC_SUCCESS)
131 CreateMIBTree();
132 }
133 }
134
135 if (dwResult == RCC_SUCCESS)
136 {
137 SetInfoText(hWnd, "Loading event information...");
138 dwResult = NXCLoadEventDB();
139 }
140
141 // Synchronize images
142 if (dwResult == RCC_SUCCESS)
143 {
144 char szCacheDir[MAX_PATH];
145
146 SetInfoText(hWnd, "Synchronizing images...");
147 strcpy(szCacheDir, g_szWorkDir);
148 strcat(szCacheDir, WORKDIR_IMAGECACHE);
149 dwResult = NXCSyncImages(&g_pSrvImageList, szCacheDir, IMAGE_FORMAT_ICO);
150 if (dwResult == RCC_SUCCESS)
151 CreateObjectImageList();
152 }
153
154 // Load default image list
155 if (dwResult == RCC_SUCCESS)
156 {
157 DWORD i, *pdwClassId, *pdwImageId;
158
159 SetInfoText(hWnd, "Loading default image list...");
160 dwResult = NXCLoadDefaultImageList(&g_dwDefImgListSize, &pdwClassId, &pdwImageId);
161 if (dwResult == RCC_SUCCESS)
162 {
163 g_pDefImgList = (DEF_IMG *)realloc(g_pDefImgList, sizeof(DEF_IMG) * g_dwDefImgListSize);
164 for(i = 0; i < g_dwDefImgListSize; i++)
165 {
166 g_pDefImgList[i].dwObjectClass = pdwClassId[i];
167 g_pDefImgList[i].dwImageId = pdwImageId[i];
168 g_pDefImgList[i].iImageIndex = ImageIdToIndex(pdwImageId[i]);
169 }
170 safe_free(pdwClassId);
171 safe_free(pdwImageId);
172 }
173 }
174
175 // Disconnect if some of post-login operations was failed
176 if (dwResult != RCC_SUCCESS)
177 NXCDisconnect();
178
179 PostMessage(hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
180 return dwResult;
181 }
182
183
184 //
185 // Perform login
186 //
187
188 DWORD DoLogin(void)
189 {
190 HANDLE hThread;
191 HWND hWnd = NULL;
192 DWORD dwThreadId, dwResult;
193
194 hThread = CreateThread(NULL, 0, LoginThread, &hWnd, CREATE_SUSPENDED, &dwThreadId);
195 if (hThread != NULL)
196 {
197 CRequestProcessingDlg wndWaitDlg;
198
199 wndWaitDlg.m_phWnd = &hWnd;
200 wndWaitDlg.m_hThread = hThread;
201 wndWaitDlg.m_strInfoText = "Connecting to server...";
202 dwResult = (DWORD)wndWaitDlg.DoModal();
203 CloseHandle(hThread);
204 }
205 else
206 {
207 dwResult = RCC_SYSTEM_FAILURE;
208 }
209
210 return dwResult;
211 }
212
213
214 //
215 // Request processing thread
216 //
217
218 static DWORD WINAPI RequestThread(void *pArg)
219 {
220 RqData *pData = (RqData *)pArg;
221 DWORD dwResult;
222
223 switch(pData->dwNumParams)
224 {
225 case 0:
226 dwResult = pData->pFunc();
227 break;
228 case 1:
229 dwResult = pData->pFunc(pData->pArg1);
230 break;
231 case 2:
232 dwResult = pData->pFunc(pData->pArg1, pData->pArg2);
233 break;
234 case 3:
235 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3);
236 break;
237 case 4:
238 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3, pData->pArg4);
239 break;
240 case 5:
241 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3,
242 pData->pArg4, pData->pArg5);
243 break;
244 case 6:
245 dwResult = pData->pFunc(pData->pArg1, pData->pArg2, pData->pArg3,
246 pData->pArg4, pData->pArg5, pData->pArg6);
247 break;
248 }
249 if (pData->hWnd != NULL)
250 PostMessage(pData->hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
251 return dwResult;
252 }
253
254
255 //
256 // Perform request (common code)
257 //
258
259 static DWORD ExecuteRequest(RqData *pData, char *pszInfoText)
260 {
261 HANDLE hThread;
262 DWORD dwThreadId, dwResult;
263
264 hThread = CreateThread(NULL, 0, RequestThread, pData, 0, &dwThreadId);
265 if (hThread != NULL)
266 {
267 CRequestProcessingDlg wndWaitDlg;
268
269 // Wait for request completion
270 if (WaitForSingleObject(hThread, UI_THREAD_WAIT_TIME) == WAIT_TIMEOUT)
271 {
272 // Thread still not finished, open status window
273 SuspendThread(hThread);
274 wndWaitDlg.m_phWnd = &pData->hWnd;
275 wndWaitDlg.m_hThread = hThread;
276 wndWaitDlg.m_strInfoText = pszInfoText;
277 dwResult = (DWORD)wndWaitDlg.DoModal();
278 }
279 else
280 {
281 // Thread is finished, get it's exit code
282 if (!GetExitCodeThread(hThread, &dwResult))
283 dwResult = RCC_SYSTEM_FAILURE;
284 }
285 CloseHandle(hThread);
286 }
287 else
288 {
289 dwResult = RCC_SYSTEM_FAILURE;
290 }
291
292 return dwResult;
293 }
294
295
296 //
297 // Perform generic request without parameters
298 //
299
300 DWORD DoRequest(DWORD (* pFunc)(void), char *pszInfoText)
301 {
302 RqData rqData;
303
304 rqData.hWnd = NULL;
305 rqData.dwNumParams = 0;
306 rqData.pFunc = (DWORD (*)(...))pFunc;
307 return ExecuteRequest(&rqData, pszInfoText);
308 }
309
310
311 //
312 // Perform request with 1 parameter
313 //
314
315 DWORD DoRequestArg1(void *pFunc, void *pArg1, char *pszInfoText)
316 {
317 RqData rqData;
318
319 rqData.hWnd = NULL;
320 rqData.dwNumParams = 1;
321 rqData.pArg1 = pArg1;
322 rqData.pFunc = (DWORD (*)(...))pFunc;
323 return ExecuteRequest(&rqData, pszInfoText);
324 }
325
326
327 //
328 // Perform request with 2 parameters
329 //
330
331 DWORD DoRequestArg2(void *pFunc, void *pArg1, void *pArg2, char *pszInfoText)
332 {
333 RqData rqData;
334
335 rqData.hWnd = NULL;
336 rqData.dwNumParams = 2;
337 rqData.pArg1 = pArg1;
338 rqData.pArg2 = pArg2;
339 rqData.pFunc = (DWORD (*)(...))pFunc;
340 return ExecuteRequest(&rqData, pszInfoText);
341 }
342
343
344 //
345 // Perform request with 3 parameter
346 //
347
348 DWORD DoRequestArg3(void *pFunc, void *pArg1, void *pArg2, void *pArg3, char *pszInfoText)
349 {
350 RqData rqData;
351
352 rqData.hWnd = NULL;
353 rqData.dwNumParams = 3;
354 rqData.pArg1 = pArg1;
355 rqData.pArg2 = pArg2;
356 rqData.pArg3 = pArg3;
357 rqData.pFunc = (DWORD (*)(...))pFunc;
358 return ExecuteRequest(&rqData, pszInfoText);
359 }
360
361
362 //
363 // Perform request with 4 parameter
364 //
365
366 DWORD DoRequestArg4(void *pFunc, void *pArg1, void *pArg2, void *pArg3,
367 void *pArg4, char *pszInfoText)
368 {
369 RqData rqData;
370
371 rqData.hWnd = NULL;
372 rqData.dwNumParams = 4;
373 rqData.pArg1 = pArg1;
374 rqData.pArg2 = pArg2;
375 rqData.pArg3 = pArg3;
376 rqData.pArg4 = pArg4;
377 rqData.pFunc = (DWORD (*)(...))pFunc;
378 return ExecuteRequest(&rqData, pszInfoText);
379 }
380
381
382 //
383 // Perform request with 5 parameter
384 //
385
386 DWORD DoRequestArg5(void *pFunc, void *pArg1, void *pArg2, void *pArg3, void *pArg4,
387 void *pArg5, char *pszInfoText)
388 {
389 RqData rqData;
390
391 rqData.hWnd = NULL;
392 rqData.dwNumParams = 5;
393 rqData.pArg1 = pArg1;
394 rqData.pArg2 = pArg2;
395 rqData.pArg3 = pArg3;
396 rqData.pArg4 = pArg4;
397 rqData.pArg5 = pArg5;
398 rqData.pFunc = (DWORD (*)(...))pFunc;
399 return ExecuteRequest(&rqData, pszInfoText);
400 }
401
402
403 //
404 // Perform request with 6 parameter
405 //
406
407 DWORD DoRequestArg6(void *pFunc, void *pArg1, void *pArg2, void *pArg3, void *pArg4,
408 void *pArg5, void *pArg6, char *pszInfoText)
409 {
410 RqData rqData;
411
412 rqData.hWnd = NULL;
413 rqData.dwNumParams = 6;
414 rqData.pArg1 = pArg1;
415 rqData.pArg2 = pArg2;
416 rqData.pArg3 = pArg3;
417 rqData.pArg4 = pArg4;
418 rqData.pArg5 = pArg5;
419 rqData.pArg6 = pArg6;
420 rqData.pFunc = (DWORD (*)(...))pFunc;
421 return ExecuteRequest(&rqData, pszInfoText);
422 }
423
424
425 //
426 // Callback function for node poller
427 //
428
429 static void PollerCallback(TCHAR *pszMsg, void *pArg)
430 {
431 if (((RqData *)pArg)->hWnd != NULL)
432 PostMessage(((RqData *)pArg)->hWnd, WM_POLLER_MESSAGE, 0, (LPARAM)_tcsdup(pszMsg));
433 }
434
435
436 //
437 // Poller thread
438 //
439
440 DWORD WINAPI PollerThread(void *pArg)
441 {
442 RqData *pData = (RqData *)pArg;
443 DWORD dwResult;
444
445 theApp.DebugPrintf("Starting poll...");
446 dwResult = NXCPollNode((DWORD)pData->pArg1, (int)pData->pArg2, PollerCallback, pArg);
447 theApp.DebugPrintf("poll complete: %d", dwResult);
448 if (pData->hWnd != NULL)
449 PostMessage(pData->hWnd, WM_REQUEST_COMPLETED, 0, dwResult);
450 return dwResult;
451 }