Implemented object caching on client side
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
21e4b6f0
VK
1/*
2** NetXMS - Network Management System
3** Copyright (C) 2003, 2004 Victor Kirhenshtein
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 2 of the License, or
8** (at your option) 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** $module: session.cpp
20**
21**/
22
a551fe4d 23#include "nxcore.h"
21e4b6f0 24
693119d6
VK
25#ifndef _WIN32
26#include <dirent.h>
06e7be2f
VK
27#endif
28
21e4b6f0 29
693119d6
VK
30//
31// Constants
32//
33
34#define TRAP_CREATE 1
35#define TRAP_UPDATE 2
36#define TRAP_DELETE 3
37
257defd7
VK
38#define RAW_MSG_SIZE 262144
39
693119d6 40
ccdbbb52
VK
41//
42// Externals
43//
44
45void UnregisterSession(DWORD dwIndex);
46
47
d966d18a
VK
48//
49// Node poller start data
50//
51
52typedef struct
53{
54 ClientSession *pSession;
55 Node *pNode;
56 int iPollType;
57 DWORD dwRqId;
58} POLLER_START_DATA;
59
60
2d5c8ac8
VK
61//
62// Fill CSCP message with user data
63//
64
65static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
66{
67 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
68 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
69 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
70 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
71 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
72 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
73}
74
75
76//
77// Fill CSCP message with user group data
78//
79
80static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
81{
82 DWORD i, dwId;
83
84 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
85 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
86 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
87 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
88 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
89 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
90 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
91 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
92}
93
94
ccdbbb52
VK
95//
96// Client communication read thread starter
97//
98
99THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
100{
101 ((ClientSession *)pArg)->ReadThread();
102
103 // When ClientSession::ReadThread exits, all other session
104 // threads are already stopped, so we can safely destroy
105 // session object
106 UnregisterSession(((ClientSession *)pArg)->GetIndex());
107 delete (ClientSession *)pArg;
108 return THREAD_OK;
109}
110
111
112//
113// Client communication write thread starter
114//
115
116THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
117{
118 ((ClientSession *)pArg)->WriteThread();
119 return THREAD_OK;
120}
121
122
123//
124// Received message processing thread starter
125//
126
127THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
128{
129 ((ClientSession *)pArg)->ProcessingThread();
130 return THREAD_OK;
131}
132
133
134//
135// Information update processing thread starter
136//
137
138THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
139{
140 ((ClientSession *)pArg)->UpdateThread();
141 return THREAD_OK;
142}
143
144
d966d18a
VK
145//
146// Forced node poll thread starter
147//
148
149THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
150{
151 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
152 ((POLLER_START_DATA *)pArg)->pNode,
153 ((POLLER_START_DATA *)pArg)->iPollType,
154 ((POLLER_START_DATA *)pArg)->dwRqId);
5109017e 155 ((POLLER_START_DATA *)pArg)->pSession->DecRefCount();
d966d18a
VK
156 free(pArg);
157 return THREAD_OK;
158}
159
160
21e4b6f0
VK
161//
162// Client session class constructor
163//
164
b54b2b11 165ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
21e4b6f0
VK
166{
167 m_pSendQueue = new Queue;
168 m_pMessageQueue = new Queue;
62f5857f 169 m_pUpdateQueue = new Queue;
21e4b6f0
VK
170 m_hSocket = hSocket;
171 m_dwIndex = INVALID_INDEX;
cb7ec554 172 m_iState = SESSION_STATE_INIT;
21e4b6f0 173 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
ccdbbb52
VK
174 m_hWriteThread = INVALID_THREAD_HANDLE;
175 m_hProcessingThread = INVALID_THREAD_HANDLE;
176 m_hUpdateThread = INVALID_THREAD_HANDLE;
03482383
VK
177 m_mutexSendEvents = MutexCreate();
178 m_mutexSendObjects = MutexCreate();
179 m_mutexSendAlarms = MutexCreate();
c9363772 180 m_mutexSendActions = MutexCreate();
d966d18a 181 m_mutexPollerInit = MutexCreate();
b54b2b11
VK
182 m_dwFlags = 0;
183 m_dwHostAddr = dwHostAddr;
184 strcpy(m_szUserName, "<not logged in>");
984542f8 185 m_dwUserId = INVALID_INDEX;
338493a0
VK
186 m_dwOpenDCIListSize = 0;
187 m_pOpenDCIList = NULL;
8f7e2482 188 m_ppEPPRuleList = NULL;
257defd7
VK
189 m_hCurrFile = -1;
190 m_dwFileRqId = 0;
5109017e 191 m_dwRefCount = 0;
21e4b6f0
VK
192}
193
194
195//
196// Destructor
197//
198
199ClientSession::~ClientSession()
200{
201 shutdown(m_hSocket, 2);
202 closesocket(m_hSocket);
203 delete m_pSendQueue;
204 delete m_pMessageQueue;
62f5857f 205 delete m_pUpdateQueue;
338493a0 206 safe_free(m_pMsgBuffer);
03482383
VK
207 MutexDestroy(m_mutexSendEvents);
208 MutexDestroy(m_mutexSendObjects);
209 MutexDestroy(m_mutexSendAlarms);
c9363772 210 MutexDestroy(m_mutexSendActions);
d966d18a 211 MutexDestroy(m_mutexPollerInit);
338493a0 212 safe_free(m_pOpenDCIList);
8f7e2482
VK
213 if (m_ppEPPRuleList != NULL)
214 {
215 DWORD i;
216
217 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
218 for(i = 0; i < m_dwRecordsUploaded; i++)
219 delete m_ppEPPRuleList[i];
220 free(m_ppEPPRuleList);
221 }
21e4b6f0
VK
222}
223
224
ccdbbb52
VK
225//
226// Start all threads
227//
228
229void ClientSession::Run(void)
230{
231 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
232 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
233 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
234 ThreadCreate(ReadThreadStarter, 0, this);
235}
236
237
21e4b6f0
VK
238//
239// Print debug information
240//
241
242void ClientSession::DebugPrintf(char *szFormat, ...)
243{
244 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
245 {
246 va_list args;
247
248 printf("*CSCP(%d)* ", m_dwIndex);
249 va_start(args, szFormat);
250 vprintf(szFormat, args);
251 va_end(args);
252 }
253}
254
255
21e4b6f0
VK
256//
257// ReadThread()
258//
259
260void ClientSession::ReadThread(void)
261{
262 CSCP_MESSAGE *pRawMsg;
263 CSCPMessage *pMsg;
257defd7 264 TCHAR szBuffer[256];
21e4b6f0 265 int iErr;
338493a0
VK
266 DWORD i;
267 NetObj *pObject;
257defd7 268 WORD wFlags;
21e4b6f0
VK
269
270 // Initialize raw message receiving function
a933a2bf 271 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
21e4b6f0 272
257defd7 273 pRawMsg = (CSCP_MESSAGE *)malloc(RAW_MSG_SIZE);
21e4b6f0
VK
274 while(1)
275 {
257defd7 276 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, RAW_MSG_SIZE)) <= 0)
21e4b6f0
VK
277 break;
278
a933a2bf
VK
279 // Check if message is too large
280 if (iErr == 1)
257defd7
VK
281 {
282 DebugPrintf("Received message %s is too large (%d bytes)\n",
283 CSCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
284 ntohl(pRawMsg->dwSize));
a933a2bf 285 continue;
257defd7 286 }
a933a2bf 287
21e4b6f0 288 // Check that actual received packet size is equal to encoded in packet
6159a875 289 if ((int)ntohl(pRawMsg->dwSize) != iErr)
21e4b6f0 290 {
6159a875 291 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
21e4b6f0
VK
292 continue; // Bad packet, wait for next
293 }
294
257defd7
VK
295 // Special handling for raw messages
296 wFlags = ntohs(pRawMsg->wFlags);
297 if (wFlags & MF_BINARY)
298 {
299 // Convert message header to host format
300 pRawMsg->dwId = ntohl(pRawMsg->dwId);
301 pRawMsg->wCode = ntohs(pRawMsg->wCode);
302 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
303 DebugPrintf("Received raw message %s\n", CSCPMessageCodeName(pRawMsg->wCode, szBuffer));
304
305 if ((pRawMsg->wCode == CMD_FILE_DATA) ||
306 (pRawMsg->wCode == CMD_ABORT_FILE_TRANSFER))
307 {
308 if ((m_hCurrFile != -1) && (m_dwFileRqId == pRawMsg->dwId))
309 {
310 if (pRawMsg->wCode == CMD_FILE_DATA)
311 {
312 if (write(m_hCurrFile, pRawMsg->df, pRawMsg->dwNumVars) == (int)pRawMsg->dwNumVars)
313 {
314 if (wFlags & MF_EOF)
315 {
316 CSCPMessage msg;
317
318 close(m_hCurrFile);
319 m_hCurrFile = -1;
320
321 msg.SetCode(CMD_REQUEST_COMPLETED);
322 msg.SetId(pRawMsg->dwId);
323 msg.SetVariable(VID_RCC, RCC_SUCCESS);
324 SendMessage(&msg);
325
326 OnFileUpload(TRUE);
327 }
328 }
329 else
330 {
331 // I/O error
332 CSCPMessage msg;
333
334 close(m_hCurrFile);
335 m_hCurrFile = -1;
336
337 msg.SetCode(CMD_REQUEST_COMPLETED);
338 msg.SetId(pRawMsg->dwId);
339 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
340 SendMessage(&msg);
341
342 OnFileUpload(FALSE);
343 }
344 }
345 else
346 {
347 // Abort current file transfer because of client's problem
348 close(m_hCurrFile);
349 m_hCurrFile = -1;
350
351 OnFileUpload(FALSE);
352 }
353 }
354 else
355 {
356 DebugPrintf("Out of state message (ID: %d)\n", pRawMsg->dwId);
357 }
358 }
359 }
360 else
361 {
362 // Create message object from raw message
363 pMsg = new CSCPMessage(pRawMsg);
364 m_pMessageQueue->Put(pMsg);
365 }
21e4b6f0
VK
366 }
367 if (iErr < 0)
368 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
369 free(pRawMsg);
370
371 // Notify other threads to exit
d09b1909 372 m_pSendQueue->Clear();
ecb7e1ee 373 m_pSendQueue->Put(INVALID_POINTER_VALUE);
d09b1909 374 m_pMessageQueue->Clear();
ecb7e1ee 375 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
d09b1909 376 m_pUpdateQueue->Clear();
8f7e2482 377 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
ecb7e1ee
VK
378
379 // Wait for other threads to finish
ccdbbb52
VK
380 ThreadJoin(m_hWriteThread);
381 ThreadJoin(m_hProcessingThread);
382 ThreadJoin(m_hUpdateThread);
54abbe0e 383
257defd7
VK
384 // Abort current file upload operation, if any
385 if (m_hCurrFile != -1)
386 {
387 close(m_hCurrFile);
388 m_hCurrFile = -1;
389 OnFileUpload(FALSE);
390 }
391
54abbe0e
VK
392 // Remove all locks created by this session
393 RemoveAllSessionLocks(m_dwIndex);
338493a0
VK
394 for(i = 0; i < m_dwOpenDCIListSize; i++)
395 {
396 pObject = FindObjectById(m_pOpenDCIList[i]);
397 if (pObject != NULL)
3ca9b0a5
VK
398 if ((pObject->Type() == OBJECT_NODE) ||
399 (pObject->Type() == OBJECT_TEMPLATE))
400 ((Template *)pObject)->UnlockDCIList(m_dwIndex);
338493a0 401 }
8f7e2482 402
5109017e
VK
403 // Waiting while reference count becomes 0
404 if (m_dwRefCount > 0)
405 {
406 DebugPrintf("Waiting for pending requests...\n");
407 do
408 {
409 ThreadSleep(1);
410 } while(m_dwRefCount > 0);
411 }
412
8f7e2482 413 DebugPrintf("Session closed\n");
21e4b6f0
VK
414}
415
416
417//
418// WriteThread()
419//
420
421void ClientSession::WriteThread(void)
422{
423 CSCP_MESSAGE *pMsg;
7ac0c0a8 424 char szBuffer[128];
21e4b6f0
VK
425
426 while(1)
427 {
428 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
ecb7e1ee 429 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
430 break;
431
6159a875 432 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
1216cc73 433 if (SendEx(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
21e4b6f0 434 {
9d72bde1 435 safe_free(pMsg);
80de4676 436 closesocket(m_hSocket);
21e4b6f0
VK
437 break;
438 }
9d72bde1 439 safe_free(pMsg);
21e4b6f0 440 }
8f7e2482
VK
441}
442
443
444//
445// Update processing thread
446//
447
448void ClientSession::UpdateThread(void)
449{
450 UPDATE_INFO *pUpdate;
451 CSCPMessage msg;
452
8f7e2482
VK
453 while(1)
454 {
455 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
456 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
457 break;
458
459 switch(pUpdate->dwCategory)
460 {
461 case INFO_CAT_EVENT:
03482383 462 MutexLock(m_mutexSendEvents, INFINITE);
8f7e2482 463 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
03482383 464 MutexUnlock(m_mutexSendEvents);
8f7e2482
VK
465 free(pUpdate->pData);
466 break;
467 case INFO_CAT_OBJECT_CHANGE:
03482383 468 MutexLock(m_mutexSendObjects, INFINITE);
8f7e2482 469 msg.SetCode(CMD_OBJECT_UPDATE);
03482383 470 msg.SetId(0);
8f7e2482
VK
471 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
472 SendMessage(&msg);
03482383 473 MutexUnlock(m_mutexSendObjects);
8f7e2482
VK
474 msg.DeleteAllVariables();
475 ((NetObj *)pUpdate->pData)->DecRefCount();
476 break;
03482383
VK
477 case INFO_CAT_ALARM:
478 MutexLock(m_mutexSendAlarms, INFINITE);
479 msg.SetCode(CMD_ALARM_UPDATE);
480 msg.SetId(0);
c9363772 481 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
b900a78b 482 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
49dde062 483 SendMessage(&msg);
03482383
VK
484 MutexUnlock(m_mutexSendAlarms);
485 msg.DeleteAllVariables();
c9363772
VK
486 free(pUpdate->pData);
487 break;
488 case INFO_CAT_ACTION:
489 MutexLock(m_mutexSendActions, INFINITE);
490 msg.SetCode(CMD_ACTION_DB_UPDATE);
491 msg.SetId(0);
492 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
493 msg.SetVariable(VID_ACTION_ID, ((NXC_ACTION *)pUpdate->pData)->dwId);
e91cb822
VK
494 if (pUpdate->dwCode != NX_NOTIFY_ACTION_DELETED)
495 FillActionInfoMessage(&msg, (NXC_ACTION *)pUpdate->pData);
c9363772
VK
496 SendMessage(&msg);
497 MutexUnlock(m_mutexSendActions);
498 msg.DeleteAllVariables();
499 free(pUpdate->pData);
03482383 500 break;
8f7e2482
VK
501 default:
502 break;
503 }
504
505 free(pUpdate);
506 }
21e4b6f0
VK
507}
508
509
510//
511// Message processing thread
512//
513
514void ClientSession::ProcessingThread(void)
515{
3421c063 516 CSCPMessage *pMsg;
74a5aa17 517 char szBuffer[128];
cb7ec554 518 DWORD i;
21e4b6f0
VK
519
520 while(1)
521 {
522 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
ecb7e1ee 523 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
524 break;
525
74a5aa17 526 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
cb7ec554 527 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
693119d6 528 (pMsg->GetCode() != CMD_LOGIN) && (pMsg->GetCode() != CMD_GET_SERVER_INFO))
21e4b6f0
VK
529 {
530 delete pMsg;
531 continue;
532 }
533
cb7ec554
VK
534 m_wCurrentCmd = pMsg->GetCode();
535 m_iState = SESSION_STATE_PROCESSING;
536 switch(m_wCurrentCmd)
21e4b6f0
VK
537 {
538 case CMD_LOGIN:
e100f091 539 Login(pMsg);
21e4b6f0 540 break;
693119d6
VK
541 case CMD_GET_SERVER_INFO:
542 SendServerInfo(pMsg->GetId());
543 break;
21e4b6f0 544 case CMD_GET_OBJECTS:
bfa29136 545 SendAllObjects(pMsg);
21e4b6f0
VK
546 break;
547 case CMD_GET_EVENTS:
74a5aa17 548 SendAllEvents(pMsg->GetId());
21e4b6f0
VK
549 break;
550 case CMD_GET_CONFIG_VARLIST:
551 SendAllConfigVars();
552 break;
37c4d6aa 553 case CMD_LOAD_EVENT_DB:
b54b2b11
VK
554 SendEventDB(pMsg->GetId());
555 break;
37c4d6aa
VK
556 case CMD_LOCK_EVENT_DB:
557 LockEventDB(pMsg->GetId());
558 break;
559 case CMD_UNLOCK_EVENT_DB:
560 UnlockEventDB(pMsg->GetId());
b54b2b11 561 break;
605d2931
VK
562 case CMD_SET_EVENT_INFO:
563 SetEventInfo(pMsg);
564 break;
37c4d6aa
VK
565 case CMD_DELETE_EVENT_TEMPLATE:
566 DeleteEventTemplate(pMsg);
567 break;
c19b2871
VK
568 case CMD_GENERATE_EVENT_CODE:
569 GenerateEventCode(pMsg->GetId());
37c4d6aa 570 break;
24156e90
VK
571 case CMD_MODIFY_OBJECT:
572 ModifyObject(pMsg);
573 break;
c1c39152
VK
574 case CMD_SET_OBJECT_MGMT_STATUS:
575 ChangeObjectMgmtStatus(pMsg);
576 break;
23a32988
VK
577 case CMD_LOAD_USER_DB:
578 SendUserDB(pMsg->GetId());
579 break;
ff550544
VK
580 case CMD_CREATE_USER:
581 CreateUser(pMsg);
582 break;
583 case CMD_UPDATE_USER:
584 UpdateUser(pMsg);
585 break;
586 case CMD_DELETE_USER:
587 DeleteUser(pMsg);
588 break;
589 case CMD_LOCK_USER_DB:
590 LockUserDB(pMsg->GetId(), TRUE);
591 break;
592 case CMD_UNLOCK_USER_DB:
593 LockUserDB(pMsg->GetId(), FALSE);
594 break;
017e1e13
VK
595 case CMD_SET_PASSWORD:
596 SetPassword(pMsg);
597 break;
7257eb7d
VK
598 case CMD_GET_NODE_DCI_LIST:
599 OpenNodeDCIList(pMsg);
600 break;
601 case CMD_UNLOCK_NODE_DCI_LIST:
602 CloseNodeDCIList(pMsg);
603 break;
9ed4eaff
VK
604 case CMD_CREATE_NEW_DCI:
605 case CMD_MODIFY_NODE_DCI:
606 case CMD_DELETE_NODE_DCI:
607 ModifyNodeDCI(pMsg);
608 break;
5b9a1c7b
VK
609 case CMD_SET_DCI_STATUS:
610 ChangeDCIStatus(pMsg);
611 break;
933aee5c
VK
612 case CMD_COPY_DCI:
613 CopyDCI(pMsg);
614 break;
b5b72be8
VK
615 case CMD_APPLY_TEMPLATE:
616 ApplyTemplate(pMsg);
617 break;
ebebc8ea
VK
618 case CMD_GET_DCI_DATA:
619 GetCollectedData(pMsg);
620 break;
06e7be2f
VK
621 case CMD_OPEN_EPP:
622 OpenEPP(pMsg->GetId());
623 break;
624 case CMD_CLOSE_EPP:
625 CloseEPP(pMsg->GetId());
626 break;
627 case CMD_SAVE_EPP:
628 SaveEPP(pMsg);
629 break;
8f7e2482
VK
630 case CMD_EPP_RECORD:
631 ProcessEPPRecord(pMsg);
06e7be2f
VK
632 break;
633 case CMD_GET_MIB_LIST:
634 SendMIBList(pMsg->GetId());
635 break;
636 case CMD_GET_MIB:
637 SendMIB(pMsg);
638 break;
ef44d5ea
VK
639 case CMD_CREATE_OBJECT:
640 CreateObject(pMsg);
641 break;
e6b958c4
VK
642 case CMD_BIND_OBJECT:
643 ChangeObjectBinding(pMsg, TRUE);
644 break;
645 case CMD_UNBIND_OBJECT:
646 ChangeObjectBinding(pMsg, FALSE);
647 break;
f70fc197 648 case CMD_GET_IMAGE_LIST:
aa3743b2 649 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
f70fc197
VK
650 break;
651 case CMD_LOAD_IMAGE_FILE:
aa3743b2
VK
652 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
653 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
8bff53f6
VK
654 break;
655 case CMD_GET_DEFAULT_IMAGE_LIST:
656 SendDefaultImageList(this, pMsg->GetId());
f70fc197 657 break;
03482383
VK
658 case CMD_GET_ALL_ALARMS:
659 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
660 break;
661 case CMD_GET_ALARM:
662 break;
663 case CMD_ACK_ALARM:
ee20e615
VK
664 AcknowlegeAlarm(pMsg);
665 break;
666 case CMD_DELETE_ALARM:
ae3a55d9 667 DeleteAlarm(pMsg);
03482383 668 break;
c9363772
VK
669 case CMD_LOCK_ACTION_DB:
670 LockActionDB(pMsg->GetId(), TRUE);
671 break;
672 case CMD_UNLOCK_ACTION_DB:
673 LockActionDB(pMsg->GetId(), FALSE);
674 break;
675 case CMD_CREATE_ACTION:
676 CreateAction(pMsg);
677 break;
678 case CMD_MODIFY_ACTION:
679 UpdateAction(pMsg);
680 break;
681 case CMD_DELETE_ACTION:
682 DeleteAction(pMsg);
683 break;
e91cb822
VK
684 case CMD_LOAD_ACTIONS:
685 SendAllActions(pMsg->GetId());
686 break;
6849d9be
VK
687 case CMD_GET_CONTAINER_CAT_LIST:
688 SendContainerCategories(pMsg->GetId());
689 break;
88039e6c
VK
690 case CMD_DELETE_OBJECT:
691 DeleteObject(pMsg);
692 break;
0b89f5fb
VK
693 case CMD_POLL_NODE:
694 ForcedNodePoll(pMsg);
695 break;
b562fca8
VK
696 case CMD_TRAP:
697 OnTrap(pMsg);
698 break;
ed1140dc
VK
699 case CMD_WAKEUP_NODE:
700 OnWakeUpNode(pMsg);
701 break;
b4895bbe
VK
702 case CMD_LOCK_TRAP_CFG:
703 LockTrapCfg(pMsg->GetId(), TRUE);
704 break;
705 case CMD_UNLOCK_TRAP_CFG:
706 LockTrapCfg(pMsg->GetId(), FALSE);
707 break;
708 case CMD_CREATE_TRAP:
693119d6 709 EditTrap(TRAP_CREATE, pMsg);
b4895bbe
VK
710 break;
711 case CMD_MODIFY_TRAP:
693119d6 712 EditTrap(TRAP_UPDATE, pMsg);
b4895bbe
VK
713 break;
714 case CMD_DELETE_TRAP:
693119d6 715 EditTrap(TRAP_DELETE, pMsg);
b4895bbe 716 break;
840eb902 717 case CMD_LOAD_TRAP_CFG:
b4895bbe
VK
718 SendAllTraps(pMsg->GetId());
719 break;
80de4676
VK
720 case CMD_QUERY_PARAMETER:
721 QueryParameter(pMsg);
722 break;
5be45ff2
VK
723 case CMD_LOCK_PACKAGE_DB:
724 LockPackageDB(pMsg->GetId(), TRUE);
725 break;
726 case CMD_UNLOCK_PACKAGE_DB:
727 LockPackageDB(pMsg->GetId(), FALSE);
728 break;
1c8b8363
VK
729 case CMD_GET_PACKAGE_LIST:
730 SendAllPackages(pMsg->GetId());
731 break;
257defd7
VK
732 case CMD_INSTALL_PACKAGE:
733 InstallPackage(pMsg);
734 break;
f6aa542e
VK
735 case CMD_REMOVE_PACKAGE:
736 RemovePackage(pMsg);
737 break;
89235715
VK
738 case CMD_GET_PARAMETER_LIST:
739 SendParametersList(pMsg);
740 break;
3b158c80
VK
741 case CMD_DEPLOY_PACKAGE:
742 DeployPackage(pMsg);
743 break;
20aaa307
VK
744 case CMD_GET_LAST_VALUES:
745 SendLastValues(pMsg);
746 break;
21e4b6f0 747 default:
ded831ac
VK
748 // Pass message to loaded modules
749 for(i = 0; i < g_dwNumModules; i++)
cb7ec554 750 if (g_pModuleList[i].pfCommandHandler(m_wCurrentCmd, pMsg, this))
ded831ac
VK
751 break; // Message was processed by the module
752 if (i == g_dwNumModules)
37c4d6aa
VK
753 {
754 CSCPMessage responce;
755
756 responce.SetId(pMsg->GetId());
757 responce.SetCode(CMD_REQUEST_COMPLETED);
758 responce.SetVariable(VID_RCC, RCC_NOT_IMPLEMENTED);
759 SendMessage(&responce);
760 }
21e4b6f0
VK
761 break;
762 }
763 delete pMsg;
cb7ec554 764 m_iState = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
21e4b6f0
VK
765 }
766}
767
768
257defd7
VK
769//
770// Process received file
771//
772
773void ClientSession::OnFileUpload(BOOL bSuccess)
774{
775 // Do processing specific to command initiated file upload
776 switch(m_dwUploadCommand)
777 {
778 case CMD_INSTALL_PACKAGE:
779 if (!bSuccess)
780 {
781 TCHAR szQuery[256];
782
783 _sntprintf(szQuery, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%ld"), m_dwUploadData);
784 DBQuery(g_hCoreDB, szQuery);
785 }
786 break;
787 default:
788 break;
789 }
790
791 // Remove received file in case of failure
792 if (!bSuccess)
793 _tunlink(m_szCurrFileName);
794}
795
796
693119d6
VK
797//
798// Send server information to client
799//
800
801void ClientSession::SendServerInfo(DWORD dwRqId)
802{
803 CSCPMessage msg;
804
805 // Prepare responce message
806 msg.SetCode(CMD_REQUEST_COMPLETED);
807 msg.SetId(dwRqId);
808
809 // Fill message with server info
810 msg.SetVariable(VID_RCC, RCC_SUCCESS);
811 msg.SetVariable(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
812 msg.SetVariable(VID_SUPPORTED_ENCRYPTION, (DWORD)0);
813
814 // Send responce
815 SendMessage(&msg);
816}
817
818
e100f091
VK
819//
820// Authenticate client
821//
822
823void ClientSession::Login(CSCPMessage *pRequest)
824{
825 CSCPMessage msg;
6528a4d7 826 BYTE szPassword[SHA1_DIGEST_SIZE];
e100f091
VK
827 char szLogin[MAX_USER_NAME], szBuffer[32];
828
829 // Prepare responce message
830 msg.SetCode(CMD_LOGIN_RESP);
831 msg.SetId(pRequest->GetId());
832
cb7ec554 833 if (!(m_dwFlags & CSF_AUTHENTICATED))
e100f091
VK
834 {
835
836 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
6528a4d7 837 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
e100f091
VK
838
839 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
840 {
cb7ec554 841 m_dwFlags |= CSF_AUTHENTICATED;
e100f091
VK
842 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
843 msg.SetVariable(VID_RCC, RCC_SUCCESS);
844 DebugPrintf("User %s authenticated\n", m_szUserName);
845 }
846 else
847 {
848 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
849 }
850 }
851 else
852 {
853 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
854 }
855
856 // Send responce
857 SendMessage(&msg);
858}
859
860
b54b2b11
VK
861//
862// Send event configuration to client
863//
864
865void ClientSession::SendEventDB(DWORD dwRqId)
866{
867 DB_ASYNC_RESULT hResult;
868 CSCPMessage msg;
869 char szBuffer[1024];
870
871 // Prepare responce message
3a5042fd 872 msg.SetCode(CMD_REQUEST_COMPLETED);
b54b2b11
VK
873 msg.SetId(dwRqId);
874
b8bad201
VK
875 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
876 {
877 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
878 SendMessage(&msg);
879 }
b54b2b11
VK
880 else
881 {
b54b2b11
VK
882 msg.SetVariable(VID_RCC, RCC_SUCCESS);
883 SendMessage(&msg);
884 msg.DeleteAllVariables();
885
886 // Prepare data message
887 msg.SetCode(CMD_EVENT_DB_RECORD);
888 msg.SetId(dwRqId);
889
c19b2871 890 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_code,event_name,severity,flags,message,description FROM event_cfg");
ebebc8ea 891 if (hResult != NULL)
b54b2b11 892 {
ebebc8ea
VK
893 while(DBFetch(hResult))
894 {
c19b2871 895 msg.SetVariable(VID_EVENT_CODE, DBGetFieldAsyncULong(hResult, 0));
ebebc8ea
VK
896 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
897 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
898 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
8f7e2482
VK
899
900 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
901 DecodeSQLString(szBuffer);
902 msg.SetVariable(VID_MESSAGE, szBuffer);
903
904 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
905 DecodeSQLString(szBuffer);
906 msg.SetVariable(VID_DESCRIPTION, szBuffer);
907
ebebc8ea
VK
908 SendMessage(&msg);
909 msg.DeleteAllVariables();
910 }
911 DBFreeAsyncResult(hResult);
b54b2b11 912 }
3a5042fd
VK
913
914 // Send end-of-list indicator
c19b2871 915 msg.SetVariable(VID_EVENT_CODE, (DWORD)0);
3a5042fd 916 SendMessage(&msg);
b54b2b11
VK
917 }
918}
919
920
37c4d6aa
VK
921//
922// Lock event configuration database
923//
924
925void ClientSession::LockEventDB(DWORD dwRqId)
926{
927 CSCPMessage msg;
928 char szBuffer[1024];
929
930 // Prepare responce message
931 msg.SetCode(CMD_REQUEST_COMPLETED);
932 msg.SetId(dwRqId);
933
934 if (!CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
935 {
936 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
937 }
938 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
939 {
940 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
941 msg.SetVariable(VID_LOCKED_BY, szBuffer);
942 }
943 else
944 {
945 m_dwFlags |= CSF_EVENT_DB_LOCKED;
946 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
947
948 msg.SetVariable(VID_RCC, RCC_SUCCESS);
949 }
950 SendMessage(&msg);
951}
952
953
3421c063
VK
954//
955// Close event configuration database
956//
957
37c4d6aa 958void ClientSession::UnlockEventDB(DWORD dwRqId)
3421c063
VK
959{
960 CSCPMessage msg;
961
962 msg.SetCode(CMD_REQUEST_COMPLETED);
963 msg.SetId(dwRqId);
964
965 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
966 {
967 // Check if event configuration DB has been modified
968 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
969 {
970 ReloadEvents();
971
972 // Notify clients on event database change
973 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
974 }
975 UnlockComponent(CID_EVENT_DB);
976 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
977 msg.SetVariable(VID_RCC, RCC_SUCCESS);
978 }
979 else
980 {
981 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
982 }
983 SendMessage(&msg);
984}
985
986
37c4d6aa
VK
987//
988// Update event template
989//
990
991void ClientSession::SetEventInfo(CSCPMessage *pRequest)
992{
993 CSCPMessage msg;
994
995 // Prepare reply message
996 msg.SetCode(CMD_REQUEST_COMPLETED);
997 msg.SetId(pRequest->GetId());
998
999 // Check if we have event configuration database opened
1000 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1001 {
1002 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1003 }
1004 else
1005 {
1006 // Check access rights
1007 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1008 {
1009 char szQuery[4096], szName[MAX_EVENT_NAME];
c19b2871 1010 DWORD dwEventCode;
37c4d6aa
VK
1011 BOOL bEventExist = FALSE;
1012 DB_RESULT hResult;
1013
c19b2871
VK
1014 // Check if event with specific code exists
1015 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
1016 sprintf(szQuery, "SELECT event_code FROM event_cfg WHERE event_code=%ld", dwEventCode);
37c4d6aa
VK
1017 hResult = DBSelect(g_hCoreDB, szQuery);
1018 if (hResult != NULL)
1019 {
1020 if (DBGetNumRows(hResult) > 0)
1021 bEventExist = TRUE;
1022 DBFreeResult(hResult);
1023 }
1024
1025 // Check that we are not trying to create event below 100000
c19b2871 1026 if (bEventExist || (dwEventCode >= FIRST_USER_EVENT_ID))
37c4d6aa
VK
1027 {
1028 // Prepare and execute SQL query
1029 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
1030 if (IsValidObjectName(szName))
1031 {
1032 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
1033
1034 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
1035 pszEscMsg = EncodeSQLString(szMessage);
1036
1037 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
1038 pszEscDescr = EncodeSQLString(pszDescription);
1039 safe_free(pszDescription);
1040
1041 if (bEventExist)
1042 {
c19b2871 1043 sprintf(szQuery, "UPDATE event_cfg SET event_name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_code=%ld",
37c4d6aa 1044 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
c19b2871 1045 pszEscMsg, pszEscDescr, dwEventCode);
37c4d6aa
VK
1046 }
1047 else
1048 {
c19b2871 1049 sprintf(szQuery, "INSERT INTO event_cfg (event_code,event_name,severity,flags,"
37c4d6aa 1050 "message,description) VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
c19b2871 1051 dwEventCode, szName, pRequest->GetVariableLong(VID_SEVERITY),
37c4d6aa
VK
1052 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
1053 }
1054
1055 free(pszEscMsg);
1056 free(pszEscDescr);
1057
1058 if (DBQuery(g_hCoreDB, szQuery))
1059 {
1060 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1061 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
1062 }
1063 else
1064 {
1065 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1066 }
1067 }
1068 else
1069 {
1070 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1071 }
1072 }
1073 else
1074 {
1075 msg.SetVariable(VID_RCC, RCC_INVALID_EVENT_CODE);
1076 }
1077 }
1078 else
1079 {
1080 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1081 }
1082 }
1083
1084 // Send responce
1085 SendMessage(&msg);
1086}
1087
1088
1089//
1090// Delete event template
1091//
1092
1093void ClientSession::DeleteEventTemplate(CSCPMessage *pRequest)
1094{
1095 CSCPMessage msg;
c19b2871 1096 DWORD dwEventCode;
37c4d6aa
VK
1097
1098 // Prepare reply message
1099 msg.SetCode(CMD_REQUEST_COMPLETED);
1100 msg.SetId(pRequest->GetId());
1101
1102 // Check if we have event configuration database opened
1103 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1104 {
1105 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1106 }
1107 else
1108 {
c19b2871 1109 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
37c4d6aa
VK
1110
1111 // Check access rights
c19b2871 1112 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
37c4d6aa
VK
1113 {
1114 TCHAR szQuery[256];
1115
c19b2871 1116 _stprintf(szQuery, _T("DELETE FROM event_cfg WHERE event_code=%ld"), dwEventCode);
37c4d6aa
VK
1117 if (DBQuery(g_hCoreDB, szQuery))
1118 {
1119 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1120 m_dwFlags |= CSF_EVENT_DB_LOCKED;
1121 }
1122 else
1123 {
1124 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1125 }
1126 }
1127 else
1128 {
1129 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1130 }
1131 }
1132
1133 // Send responce
1134 SendMessage(&msg);
1135}
1136
1137
1138//
1139// Generate ID for new event template
1140//
1141
c19b2871 1142void ClientSession::GenerateEventCode(DWORD dwRqId)
37c4d6aa
VK
1143{
1144 CSCPMessage msg;
1145
1146 // Prepare reply message
1147 msg.SetCode(CMD_REQUEST_COMPLETED);
1148 msg.SetId(dwRqId);
1149
1150 // Check if we have event configuration database opened
1151 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1152 {
1153 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1154 }
1155 else
1156 {
1157 // Check access rights
1158 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1159 {
c19b2871 1160 msg.SetVariable(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
37c4d6aa
VK
1161 }
1162 else
1163 {
1164 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1165 }
1166 }
1167
1168 // Send responce
1169 SendMessage(&msg);
1170}
1171
1172
21e4b6f0
VK
1173//
1174// Send all objects to client
1175//
1176
bfa29136 1177void ClientSession::SendAllObjects(CSCPMessage *pRequest)
21e4b6f0 1178{
bfa29136 1179 DWORD i, dwTimeStamp;
21e4b6f0
VK
1180 CSCPMessage msg;
1181
e100f091
VK
1182 // Send confirmation message
1183 msg.SetCode(CMD_REQUEST_COMPLETED);
bfa29136 1184 msg.SetId(pRequest->GetId());
e100f091
VK
1185 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1186 SendMessage(&msg);
1187 msg.DeleteAllVariables();
1188
bfa29136
VK
1189 // Get client's last known time stamp
1190 dwTimeStamp = pRequest->GetVariableLong(VID_TIMESTAMP);
1191
03482383 1192 MutexLock(m_mutexSendObjects, INFINITE);
53512272 1193
21e4b6f0
VK
1194 // Prepare message
1195 msg.SetCode(CMD_OBJECT);
1196
1197 // Send objects, one per message
4e839863 1198 RWLockReadLock(g_rwlockIdIndex, INFINITE);
21e4b6f0 1199 for(i = 0; i < g_dwIdIndexSize; i++)
bfa29136
VK
1200 if ((g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
1201 (g_pIndexById[i].pObject->TimeStamp() > dwTimeStamp))
24156e90
VK
1202 {
1203 g_pIndexById[i].pObject->CreateMessage(&msg);
1204 SendMessage(&msg);
1205 msg.DeleteAllVariables();
1206 }
4e839863 1207 RWLockUnlock(g_rwlockIdIndex);
21e4b6f0
VK
1208
1209 // Send end of list notification
1210 msg.SetCode(CMD_OBJECT_LIST_END);
1211 SendMessage(&msg);
53512272 1212
03482383 1213 MutexUnlock(m_mutexSendObjects);
21e4b6f0
VK
1214}
1215
1216
1217//
1218// Send all events to client
1219//
1220
74a5aa17 1221void ClientSession::SendAllEvents(DWORD dwRqId)
21e4b6f0 1222{
21e4b6f0 1223 CSCPMessage msg;
20177e8e 1224 DB_ASYNC_RESULT hResult;
9c36ef66 1225 NXC_EVENT event;
babb8280
VK
1226#ifndef UNICODE
1227 char szBuffer[MAX_EVENT_MSG_LENGTH];
1228#endif
21e4b6f0 1229
74a5aa17
VK
1230 // Send confirmation message
1231 msg.SetCode(CMD_REQUEST_COMPLETED);
1232 msg.SetId(dwRqId);
1233 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1234 SendMessage(&msg);
1235 msg.DeleteAllVariables();
1236
03482383 1237 MutexLock(m_mutexSendEvents, INFINITE);
62f5857f 1238
21e4b6f0 1239 // Retrieve events from database
0c6014e4 1240 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,event_code,event_timestamp,event_source,"
31115ff9
VK
1241 "event_severity,event_message FROM event_log "
1242 "ORDER BY event_timestamp");
21e4b6f0
VK
1243 if (hResult != NULL)
1244 {
1245 // Send events, one per message
20177e8e 1246 while(DBFetch(hResult))
21e4b6f0 1247 {
0c6014e4
VK
1248 event.qwEventId = htonq(DBGetFieldAsyncUInt64(hResult, 0));
1249 event.dwEventCode = htonl(DBGetFieldAsyncULong(hResult, 1));
1250 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 2));
1251 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 3));
1252 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 4));
babb8280 1253#ifdef UNICODE
0c6014e4 1254 DBGetFieldAsync(hResult, 5, event.szMessage, MAX_EVENT_MSG_LENGTH);
8f7e2482 1255 DecodeSQLString(event.szMessage);
babb8280
VK
1256#else
1257 DBGetFieldAsync(hResult, 5, szBuffer, MAX_EVENT_MSG_LENGTH);
1258 DecodeSQLString(szBuffer);
1259 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szBuffer, -1,
1260 (WCHAR *)event.szMessage, MAX_EVENT_MSG_LENGTH);
3ca9b0a5 1261 ((WCHAR *)event.szMessage)[MAX_EVENT_MSG_LENGTH - 1] = 0;
babb8280
VK
1262#endif
1263 SwapWideString((WCHAR *)event.szMessage);
74a5aa17 1264 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
9c36ef66 1265 }
20177e8e 1266 DBFreeAsyncResult(hResult);
21e4b6f0
VK
1267 }
1268
1269 // Send end of list notification
1270 msg.SetCode(CMD_EVENT_LIST_END);
1271 SendMessage(&msg);
62f5857f 1272
03482383 1273 MutexUnlock(m_mutexSendEvents);
21e4b6f0
VK
1274}
1275
1276
1277//
1278// Send all configuration variables to client
1279//
1280
1281void ClientSession::SendAllConfigVars(void)
1282{
1283 DWORD i, dwNumRecords;
1284 CSCPMessage msg;
1285 DB_RESULT hResult;
1286
1287 // Check user rights
11363a86 1288 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG) == 0))
21e4b6f0
VK
1289 {
1290 // Access denied
1291 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1292 msg.SetVariable(VID_ERROR, (DWORD)1);
21e4b6f0
VK
1293 SendMessage(&msg);
1294 }
1295 else
1296 {
1297 // Prepare message
1298 msg.SetCode(CMD_CONFIG_VARIABLE);
1299
1300 // Retrieve configuration variables from database
44375123 1301 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value FROM config WHERE is_visible=1");
21e4b6f0
VK
1302 if (hResult != NULL)
1303 {
1304 // Send events, one per message
1305 dwNumRecords = DBGetNumRows(hResult);
1306 for(i = 0; i < dwNumRecords; i++)
1307 {
a5f8dbb8
VK
1308 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
1309 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
21e4b6f0
VK
1310 SendMessage(&msg);
1311 msg.DeleteAllVariables();
1312 }
20177e8e 1313 DBFreeResult(hResult);
21e4b6f0
VK
1314 }
1315
1316 // Send end of list notification
1317 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1318 msg.SetVariable(VID_ERROR, (DWORD)0);
21e4b6f0
VK
1319 SendMessage(&msg);
1320 }
1321}
20177e8e
VK
1322
1323
1324//
1325// Close session forcibly
1326//
1327
1328void ClientSession::Kill(void)
1329{
1330 // We shutdown socket connection, which will cause
1331 // read thread to stop, and other threads will follow
1332 shutdown(m_hSocket, 2);
1333}
62f5857f
VK
1334
1335
1336//
1337// Handler for new events
1338//
1339
1340void ClientSession::OnNewEvent(Event *pEvent)
1341{
1342 UPDATE_INFO *pUpdate;
1343
cb7ec554 1344 if (IsAuthenticated())
984542f8
VK
1345 {
1346 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1347 pUpdate->dwCategory = INFO_CAT_EVENT;
1348 pUpdate->pData = malloc(sizeof(NXC_EVENT));
1349 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
1350 m_pUpdateQueue->Put(pUpdate);
1351 }
62f5857f
VK
1352}
1353
1354
1355//
1356// Handler for object changes
1357//
1358
53512272 1359void ClientSession::OnObjectChange(NetObj *pObject)
62f5857f 1360{
53512272
VK
1361 UPDATE_INFO *pUpdate;
1362
cb7ec554 1363 if (IsAuthenticated())
984542f8
VK
1364 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1365 {
1366 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1367 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
1368 pUpdate->pData = pObject;
984542f8 1369 pObject->IncRefCount();
333ece94 1370 m_pUpdateQueue->Put(pUpdate);
984542f8 1371 }
62f5857f
VK
1372}
1373
1374
83f0529c
VK
1375//
1376// Send notification message to server
1377//
1378
4de204a3 1379void ClientSession::Notify(DWORD dwCode, DWORD dwData)
83f0529c
VK
1380{
1381 CSCPMessage msg;
1382
1383 msg.SetCode(CMD_NOTIFY);
1384 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
4de204a3 1385 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
83f0529c
VK
1386 SendMessage(&msg);
1387}
605d2931
VK
1388
1389
24156e90
VK
1390//
1391// Modify object
1392//
1393
1394void ClientSession::ModifyObject(CSCPMessage *pRequest)
1395{
ff550544 1396 DWORD dwObjectId, dwResult = RCC_SUCCESS;
24156e90
VK
1397 NetObj *pObject;
1398 CSCPMessage msg;
1399
1400 // Prepare reply message
1401 msg.SetCode(CMD_REQUEST_COMPLETED);
1402 msg.SetId(pRequest->GetId());
1403
1404 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1405 pObject = FindObjectById(dwObjectId);
1406 if (pObject != NULL)
1407 {
1408 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1409 {
ff550544
VK
1410 // If user attempts to change object's ACL, check
1411 // if he has OBJECT_ACCESS_CONTROL permission
1412 if (pRequest->IsVariableExist(VID_ACL_SIZE))
1413 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
1414 dwResult = RCC_ACCESS_DENIED;
1415
1416 // If allowed, change object and set completion code
1417 if (dwResult != RCC_ACCESS_DENIED)
1418 dwResult = pObject->ModifyFromMessage(pRequest);
24156e90
VK
1419 msg.SetVariable(VID_RCC, dwResult);
1420 }
1421 else
1422 {
1423 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1424 }
1425 }
1426 else
1427 {
1428 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1429 }
1430
1431 // Send responce
1432 SendMessage(&msg);
1433}
23a32988
VK
1434
1435
1436//
1437// Send users database to client
1438//
1439
1440void ClientSession::SendUserDB(DWORD dwRqId)
1441{
1442 CSCPMessage msg;
2d5c8ac8 1443 DWORD i;
23a32988
VK
1444
1445 // Prepare responce message
1446 msg.SetCode(CMD_REQUEST_COMPLETED);
1447 msg.SetId(dwRqId);
1448 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1449 SendMessage(&msg);
1450
1451 // Send users
1452 msg.SetCode(CMD_USER_DATA);
1453 for(i = 0; i < g_dwNumUsers; i++)
1454 {
2d5c8ac8 1455 FillUserInfoMessage(&msg, &g_pUserList[i]);
23a32988
VK
1456 SendMessage(&msg);
1457 msg.DeleteAllVariables();
1458 }
1459
1460 // Send groups
1461 msg.SetCode(CMD_GROUP_DATA);
1462 for(i = 0; i < g_dwNumGroups; i++)
1463 {
2d5c8ac8 1464 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
23a32988
VK
1465 SendMessage(&msg);
1466 msg.DeleteAllVariables();
1467 }
1468
1469 // Send end-of-database notification
1470 msg.SetCode(CMD_USER_DB_EOF);
1471 SendMessage(&msg);
1472}
ff550544
VK
1473
1474
1475//
1476// Create new user
1477//
1478
1479void ClientSession::CreateUser(CSCPMessage *pRequest)
1480{
1481 CSCPMessage msg;
1482
1483 // Prepare responce message
1484 msg.SetCode(CMD_REQUEST_COMPLETED);
1485 msg.SetId(pRequest->GetId());
1486
1487 // Check user rights
1488 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1489 {
1490 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1491 }
1492 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1493 {
1494 // User database have to be locked before any
1495 // changes to user database can be made
1496 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1497 }
1498 else
1499 {
984542f8 1500 DWORD dwResult, dwUserId;
ff550544
VK
1501 BOOL bIsGroup;
1502 char szUserName[MAX_USER_NAME];
1503
1504 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
8f7e2482
VK
1505 if (IsValidObjectName(szUserName))
1506 {
1507 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
1508 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
1509 msg.SetVariable(VID_RCC, dwResult);
1510 if (dwResult == RCC_SUCCESS)
1511 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
1512 }
1513 else
1514 {
1515 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1516 }
ff550544
VK
1517 }
1518
1519 // Send responce
1520 SendMessage(&msg);
1521}
1522
1523
1524//
1525// Update existing user's data
1526//
1527
1528void ClientSession::UpdateUser(CSCPMessage *pRequest)
1529{
612d43dc
VK
1530 CSCPMessage msg;
1531
1532 // Prepare responce message
1533 msg.SetCode(CMD_REQUEST_COMPLETED);
1534 msg.SetId(pRequest->GetId());
1535
1536 // Check user rights
1537 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1538 {
1539 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1540 }
1541 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1542 {
1543 // User database have to be locked before any
1544 // changes to user database can be made
1545 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1546 }
1547 else
1548 {
86f31e8f 1549 DWORD dwUserId, dwResult;
612d43dc
VK
1550
1551 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1552 if (dwUserId & GROUP_FLAG)
1553 {
1554 NMS_USER_GROUP group;
2d5c8ac8 1555 DWORD i, dwId;
86f31e8f
VK
1556
1557 group.dwId = dwUserId;
2d5c8ac8
VK
1558 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
1559 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
1560 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1561 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1562 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
1563 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
1564 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
1565 group.pMembers[i] = pRequest->GetVariableLong(dwId);
86f31e8f 1566 dwResult = ModifyGroup(&group);
2d5c8ac8 1567 safe_free(group.pMembers);
612d43dc
VK
1568 }
1569 else
1570 {
1571 NMS_USER user;
1572
1573 user.dwId = dwUserId;
1574 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
1575 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
1576 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
1577 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
86f31e8f
VK
1578 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1579 dwResult = ModifyUser(&user);
612d43dc 1580 }
86f31e8f 1581 msg.SetVariable(VID_RCC, dwResult);
612d43dc
VK
1582 }
1583
1584 // Send responce
1585 SendMessage(&msg);
ff550544
VK
1586}
1587
1588
1589//
1590// Delete user
1591//
1592
1593void ClientSession::DeleteUser(CSCPMessage *pRequest)
1594{
1595 CSCPMessage msg;
1596 DWORD dwUserId;
1597
1598 // Prepare responce message
1599 msg.SetCode(CMD_REQUEST_COMPLETED);
1600 msg.SetId(pRequest->GetId());
1601
612d43dc
VK
1602 // Check user rights
1603 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
ff550544 1604 {
612d43dc
VK
1605 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1606 }
1607 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1608 {
1609 // User database have to be locked before any
1610 // changes to user database can be made
1611 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1612 }
1613 else
1614 {
1615 // Get Id of user to be deleted
1616 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1617
1618 if (dwUserId != 0)
ff550544 1619 {
c9363772 1620 DWORD dwResult;
612d43dc 1621
c9363772
VK
1622 dwResult = DeleteUserFromDB(dwUserId);
1623 msg.SetVariable(VID_RCC, dwResult);
ff550544
VK
1624 }
1625 else
1626 {
612d43dc
VK
1627 // Nobody can delete system administrator account
1628 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
ff550544
VK
1629 }
1630 }
ff550544
VK
1631
1632 // Send responce
1633 SendMessage(&msg);
1634}
1635
1636
1637//
1638// Lock/unlock user database
1639//
1640
1641void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1642{
1643 CSCPMessage msg;
1644 char szBuffer[256];
1645
1646 // Prepare responce message
1647 msg.SetCode(CMD_REQUEST_COMPLETED);
1648 msg.SetId(dwRqId);
1649
1650 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1651 {
1652 if (bLock)
1653 {
1654 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1655 {
1656 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1657 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1658 }
1659 else
1660 {
1661 m_dwFlags |= CSF_USER_DB_LOCKED;
1662 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1663 }
1664 }
1665 else
1666 {
1667 if (m_dwFlags & CSF_USER_DB_LOCKED)
1668 {
1669 UnlockComponent(CID_USER_DB);
1670 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1671 }
1672 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1673 }
1674 }
1675 else
1676 {
1677 // Current user has no rights for user account management
1678 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1679 }
1680
1681 // Send responce
1682 SendMessage(&msg);
1683}
984542f8
VK
1684
1685
1686//
1687// Notify client on user database update
1688//
1689
1690void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1691{
1692 CSCPMessage msg;
1693
cb7ec554 1694 if (IsAuthenticated())
984542f8
VK
1695 {
1696 msg.SetCode(CMD_USER_DB_UPDATE);
1697 msg.SetId(0);
1698 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
984542f8
VK
1699
1700 switch(iCode)
1701 {
1702 case USER_DB_CREATE:
2d5c8ac8 1703 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8 1704 if (dwUserId & GROUP_FLAG)
984542f8 1705 msg.SetVariable(VID_USER_NAME, pGroup->szName);
984542f8 1706 else
984542f8 1707 msg.SetVariable(VID_USER_NAME, pUser->szName);
2d5c8ac8
VK
1708 break;
1709 case USER_DB_MODIFY:
1710 if (dwUserId & GROUP_FLAG)
1711 FillGroupInfoMessage(&msg, pGroup);
1712 else
1713 FillUserInfoMessage(&msg, pUser);
984542f8
VK
1714 break;
1715 default:
2d5c8ac8 1716 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8
VK
1717 break;
1718 }
1719
1720 SendMessage(&msg);
1721 }
1722}
017e1e13
VK
1723
1724
9ed4eaff
VK
1725//
1726// Change management status for the object
1727//
1728
1729void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1730{
1731 CSCPMessage msg;
1732 DWORD dwObjectId;
1733 NetObj *pObject;
1734
1735 // Prepare responce message
1736 msg.SetCode(CMD_REQUEST_COMPLETED);
1737 msg.SetId(pRequest->GetId());
1738
1739 // Get object id and check access rights
1740 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1741 pObject = FindObjectById(dwObjectId);
1742 if (pObject != NULL)
1743 {
1744 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1745 {
1746 BOOL bIsManaged;
1747
1748 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1749 pObject->SetMgmtStatus(bIsManaged);
1750 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1751 }
1752 else
1753 {
1754 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1755 }
1756 }
1757 else
1758 {
1759 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1760 }
1761
1762 // Send responce
1763 SendMessage(&msg);
1764}
1765
1766
017e1e13
VK
1767//
1768// Set user's password
1769//
1770
1771void ClientSession::SetPassword(CSCPMessage *pRequest)
1772{
1773 CSCPMessage msg;
1774 DWORD dwUserId;
1775
1776 // Prepare responce message
1777 msg.SetCode(CMD_REQUEST_COMPLETED);
1778 msg.SetId(pRequest->GetId());
1779
1780 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1781
1782 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1783 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1784 (dwUserId == m_dwUserId)) // User can change password for itself
1785 {
1786 DWORD dwResult;
6528a4d7 1787 BYTE szPassword[SHA1_DIGEST_SIZE];
017e1e13 1788
6528a4d7 1789 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
017e1e13
VK
1790 dwResult = SetUserPassword(dwUserId, szPassword);
1791 msg.SetVariable(VID_RCC, dwResult);
1792 }
1793 else
1794 {
1795 // Current user has no rights to change password for specific user
1796 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1797 }
1798
1799 // Send responce
1800 SendMessage(&msg);
1801}
7257eb7d
VK
1802
1803
1804//
1805// Send node's DCIs to client and lock data collection settings
1806//
1807
1808void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1809{
1810 CSCPMessage msg;
3c55b85d
VK
1811 DWORD dwObjectId;
1812 NetObj *pObject;
1813 BOOL bSuccess = FALSE;
7257eb7d
VK
1814
1815 // Prepare responce message
1816 msg.SetCode(CMD_REQUEST_COMPLETED);
1817 msg.SetId(pRequest->GetId());
1818
3c55b85d
VK
1819 // Get node id and check object class and access rights
1820 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1821 pObject = FindObjectById(dwObjectId);
1822 if (pObject != NULL)
1823 {
62d11997
VK
1824 if ((pObject->Type() == OBJECT_NODE) ||
1825 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1826 {
1827 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1828 {
1829 // Try to lock DCI list
62d11997 1830 bSuccess = ((Template *)pObject)->LockDCIList(m_dwIndex);
3c55b85d 1831 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
338493a0
VK
1832
1833 // Modify list of open nodes DCI lists
1834 if (bSuccess)
1835 {
1836 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1837 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1838 m_dwOpenDCIListSize++;
1839 }
3c55b85d
VK
1840 }
1841 else
1842 {
1843 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1844 }
1845 }
1846 else
1847 {
1848 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1849 }
1850 }
1851 else
1852 {
1853 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1854 }
7257eb7d
VK
1855
1856 // Send responce
1857 SendMessage(&msg);
3c55b85d
VK
1858
1859 // If DCI list was successfully locked, send it to client
1860 if (bSuccess)
62d11997 1861 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
7257eb7d
VK
1862}
1863
1864
1865//
1866// Unlock node's data collection settings
1867//
1868
1869void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1870{
1871 CSCPMessage msg;
3c55b85d
VK
1872 DWORD dwObjectId;
1873 NetObj *pObject;
7257eb7d
VK
1874
1875 // Prepare responce message
1876 msg.SetCode(CMD_REQUEST_COMPLETED);
1877 msg.SetId(pRequest->GetId());
1878
3c55b85d
VK
1879 // Get node id and check object class and access rights
1880 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1881 pObject = FindObjectById(dwObjectId);
1882 if (pObject != NULL)
1883 {
62d11997
VK
1884 if ((pObject->Type() == OBJECT_NODE) ||
1885 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1886 {
1887 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1888 {
1889 BOOL bSuccess;
1890
1891 // Try to unlock DCI list
62d11997 1892 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
3c55b85d 1893 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
338493a0
VK
1894
1895 // Modify list of open nodes DCI lists
1896 if (bSuccess)
1897 {
1898 DWORD i;
1899
1900 for(i = 0; i < m_dwOpenDCIListSize; i++)
1901 if (m_pOpenDCIList[i] == dwObjectId)
1902 {
1903 m_dwOpenDCIListSize--;
1904 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1905 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1906 break;
1907 }
1908 }
3c55b85d
VK
1909 }
1910 else
1911 {
1912 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1913 }
1914 }
1915 else
1916 {
1917 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1918 }
1919 }
1920 else
1921 {
1922 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1923 }
1924
7257eb7d
VK
1925 // Send responce
1926 SendMessage(&msg);
1927}
c1c39152
VK
1928
1929
1930//
9ed4eaff 1931// Create, modify, or delete data collection item for node
c1c39152
VK
1932//
1933
9ed4eaff 1934void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
c1c39152
VK
1935{
1936 CSCPMessage msg;
1937 DWORD dwObjectId;
1938 NetObj *pObject;
1939
1940 // Prepare responce message
1941 msg.SetCode(CMD_REQUEST_COMPLETED);
1942 msg.SetId(pRequest->GetId());
1943
9ed4eaff 1944 // Get node id and check object class and access rights
c1c39152
VK
1945 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1946 pObject = FindObjectById(dwObjectId);
1947 if (pObject != NULL)
1948 {
62d11997
VK
1949 if ((pObject->Type() == OBJECT_NODE) ||
1950 (pObject->Type() == OBJECT_TEMPLATE))
c1c39152 1951 {
62d11997 1952 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
9ed4eaff
VK
1953 {
1954 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1955 {
07a45e04 1956 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
9ed4eaff
VK
1957 DCItem *pItem;
1958 BOOL bSuccess;
1959
1960 switch(pRequest->GetCode())
1961 {
1962 case CMD_CREATE_NEW_DCI:
1963 // Create dummy DCI
1964 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
0ae741b9 1965 DCI_DT_INT, 60, 30, (Node *)pObject);
9ed4eaff 1966 pItem->SetStatus(ITEM_STATUS_DISABLED);
62d11997 1967 if (((Template *)pObject)->AddItem(pItem))
9ed4eaff
VK
1968 {
1969 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1970 // Return new item id to client
1971 msg.SetVariable(VID_DCI_ID, pItem->Id());
1972 }
1973 else // Unable to add item to node
1974 {
1975 delete pItem;
1976 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1977 }
1978 break;
1979 case CMD_MODIFY_NODE_DCI:
1980 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997
VK
1981 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1982 &pdwMapIndex, &pdwMapId);
07a45e04
VK
1983 if (bSuccess)
1984 {
1985 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1986
1987 // Send index to id mapping for newly created thresholds to client
1988 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1989 for(i = 0; i < dwNumMaps; i++)
1990 {
1991 pdwMapId[i] = htonl(pdwMapId[i]);
1992 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1993 }
1994 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1995 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
7247842d
VK
1996 safe_free(pdwMapId);
1997 safe_free(pdwMapIndex);
07a45e04
VK
1998 }
1999 else
2000 {
2001 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2002 }
9ed4eaff
VK
2003 break;
2004 case CMD_DELETE_NODE_DCI:
2005 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997 2006 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId);
9ed4eaff
VK
2007 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
2008 break;
2009 }
70573ffe
VK
2010 if (bSuccess)
2011 ((Template *)pObject)->SetDCIModificationFlag();
9ed4eaff
VK
2012 }
2013 else // User doesn't have MODIFY rights on object
2014 {
2015 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2016 }
2017 }
2018 else // Nodes DCI list not locked by this session
2019 {
2020 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2021 }
c1c39152 2022 }
9ed4eaff 2023 else // Object is not a node
c1c39152 2024 {
9ed4eaff 2025 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
5b9a1c7b
VK
2026 }
2027 }
2028 else // No object with given ID
2029 {
2030 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2031 }
2032
2033 // Send responce
2034 SendMessage(&msg);
2035}
2036
2037
2038//
2039// Change status for one or more DCIs
2040//
2041
2042void ClientSession::ChangeDCIStatus(CSCPMessage *pRequest)
2043{
2044 CSCPMessage msg;
2045 NetObj *pObject;
2046
2047 // Prepare responce message
2048 msg.SetCode(CMD_REQUEST_COMPLETED);
2049 msg.SetId(pRequest->GetId());
2050
2051 // Get node id and check object class and access rights
2052 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2053 if (pObject != NULL)
2054 {
2055 if ((pObject->Type() == OBJECT_NODE) ||
2056 (pObject->Type() == OBJECT_TEMPLATE))
2057 {
2058 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
2059 {
2060 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2061 {
2185f431
VK
2062 DWORD dwNumItems, *pdwItemList;
2063 int iStatus;
2064
2065 iStatus = pRequest->GetVariableShort(VID_DCI_STATUS);
2066 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2067 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2068 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2069 if (((Template *)pObject)->SetItemStatus(dwNumItems, pdwItemList, iStatus))
2070 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2071 else
2072 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2073 free(pdwItemList);
5b9a1c7b
VK
2074 }
2075 else // User doesn't have MODIFY rights on object
2076 {
2077 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2078 }
2079 }
2080 else // Nodes DCI list not locked by this session
2081 {
2082 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2083 }
2084 }
2085 else // Object is not a node
2086 {
2087 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
c1c39152
VK
2088 }
2089 }
9ed4eaff 2090 else // No object with given ID
c1c39152
VK
2091 {
2092 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2093 }
2094
2095 // Send responce
2096 SendMessage(&msg);
2097}
ebebc8ea
VK
2098
2099
933aee5c 2100//
62d11997 2101// Copy DCI from one node or template to another
933aee5c
VK
2102//
2103
2104void ClientSession::CopyDCI(CSCPMessage *pRequest)
2105{
2106 CSCPMessage msg;
2107 NetObj *pSource, *pDestination;
2108
2109 // Prepare responce message
2110 msg.SetCode(CMD_REQUEST_COMPLETED);
2111 msg.SetId(pRequest->GetId());
2112
2113 // Get source and destination
2114 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
2115 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
2116 if ((pSource != NULL) && (pDestination != NULL))
2117 {
2118 // Check object types
62d11997
VK
2119 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE)) &&
2120 (pDestination->Type() == OBJECT_NODE))
933aee5c 2121 {
62d11997 2122 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
933aee5c
VK
2123 {
2124 // Check access rights
2125 if ((pSource->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
2126 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2127 {
2128 // Attempt to lock destination's DCI list
079c3851
VK
2129 if ((pDestination->Id() == pSource->Id()) ||
2130 (((Template *)pDestination)->LockDCIList(m_dwIndex)))
933aee5c
VK
2131 {
2132 DWORD i, *pdwItemList, dwNumItems;
2133 const DCItem *pSrcItem;
2134 DCItem *pDstItem;
2135 int iErrors = 0;
2136
2137 // Get list of items to be copied
2138 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2139 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2140 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2141
2142 // Copy items
2143 for(i = 0; i < dwNumItems; i++)
2144 {
62d11997 2145 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
933aee5c
VK
2146 if (pSrcItem != NULL)
2147 {
2148 pDstItem = new DCItem(pSrcItem);
993fac06
VK
2149 pDstItem->ChangeBinding(CreateUniqueId(IDG_ITEM),
2150 (Template *)pDestination);
62d11997 2151 if (!((Template *)pDestination)->AddItem(pDstItem))
933aee5c
VK
2152 {
2153 delete pDstItem;
2154 iErrors++;
2155 }
2156 }
2157 else
2158 {
2159 iErrors++;
2160 }
2161 }
2162
2163 // Cleanup
2164 free(pdwItemList);
079c3851
VK
2165 if (pDestination->Id() != pSource->Id())
2166 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
933aee5c
VK
2167 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
2168 }
2169 else // Destination's DCI list already locked by someone else
2170 {
2171 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2172 }
2173 }
2174 else // User doesn't have enough rights on object(s)
2175 {
2176 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2177 }
2178 }
2179 else // Source node DCI list not locked by this session
2180 {
2181 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2182 }
2183 }
2184 else // Object(s) is not a node
2185 {
2186 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2187 }
2188 }
2189 else // No object(s) with given ID
2190 {
2191 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2192 }
2193
2194 // Send responce
2195 SendMessage(&msg);
2196}
2197
2198
ebebc8ea
VK
2199//
2200// Get collected data
2201//
2202
2203void ClientSession::GetCollectedData(CSCPMessage *pRequest)
2204{
2205 CSCPMessage msg;
2206 DWORD dwObjectId;
2207 NetObj *pObject;
6159a875 2208 BOOL bSuccess = FALSE;
2b9c1c41 2209 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
ebebc8ea
VK
2210
2211 // Prepare responce message
2212 msg.SetCode(CMD_REQUEST_COMPLETED);
2213 msg.SetId(pRequest->GetId());
2214
2215 // Get node id and check object class and access rights
2216 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2217 pObject = FindObjectById(dwObjectId);
2218 if (pObject != NULL)
2219 {
2220 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2221 {
2222 DB_ASYNC_RESULT hResult;
2223 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
6159a875 2224 DWORD dwAllocatedRows = 100, dwNumRows = 0;
bdce7422
VK
2225 char szQuery[512], szCond[256];
2226 int iPos = 0, iType;
2227 DCI_DATA_HEADER *pData = NULL;
6159a875 2228 DCI_DATA_ROW *pCurr;
bdce7422 2229
ebebc8ea
VK
2230 // Get request parameters
2231 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2232 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
2233 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
2234 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
2235
9f20696e 2236 szCond[0] = 0;
bdce7422
VK
2237 if (dwTimeFrom != 0)
2238 {
1dc90d86 2239 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
bdce7422
VK
2240 iPos = strlen(szCond);
2241 }
2242 if (dwTimeTo != 0)
2243 {
1dc90d86 2244 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
bdce7422
VK
2245 }
2246
4e839863
VK
2247 // Get item's data type to determine actual row size
2248 iType = ((Node *)pObject)->GetItemType(dwItemId);
2249
336ea27e
VK
2250 // Create database-dependent query for fetching N rows
2251 if (dwMaxRows > 0)
2252 {
2253 switch(g_dwDBSyntax)
2254 {
2255 case DB_SYNTAX_MSSQL:
2256 sprintf(szQuery, "SELECT TOP %ld idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2257 dwMaxRows, dwObjectId, dwItemId, szCond);
2258 break;
2259 case DB_SYNTAX_MYSQL:
2260 case DB_SYNTAX_PGSQL:
2261 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC LIMIT %ld",
2262 dwObjectId, dwItemId, szCond, dwMaxRows);
2263 break;
2264 default:
2265 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2266 dwObjectId, dwItemId, szCond);
2267 break;
2268 }
2269 }
2270 else
2271 {
2272 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2273 dwObjectId, dwItemId, szCond);
2274 }
ebebc8ea
VK
2275 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
2276 if (hResult != NULL)
2277 {
c7e30093
VK
2278 // Send CMD_REQUEST_COMPLETED message
2279 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2280 SendMessage(&msg);
2281
6159a875
VK
2282 // Allocate initial memory block and prepare data header
2283 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2284 pData->dwDataType = htonl((DWORD)iType);
2285 pData->dwItemId = htonl(dwItemId);
2286
2287 // Fill memory block with records
2288 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
ebebc8ea
VK
2289 while(DBFetch(hResult))
2290 {
6159a875 2291 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
bdce7422 2292 break;
6159a875
VK
2293
2294 // Extend buffer if we are at the end
2295 if (dwNumRows == dwAllocatedRows)
2296 {
2297 dwAllocatedRows += 50;
2298 pData = (DCI_DATA_HEADER *)realloc(pData,
2299 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2300 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
2301 }
2302
2303 dwNumRows++;
2304
2305 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
2306 switch(iType)
2307 {
0ae741b9
VK
2308 case DCI_DT_INT:
2309 case DCI_DT_UINT:
9f20696e
VK
2310 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
2311 break;
0ae741b9
VK
2312 case DCI_DT_INT64:
2313 case DCI_DT_UINT64:
0c6014e4 2314 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUInt64(hResult, 1));
0ae741b9 2315 break;
42d7ed00 2316 case DCI_DT_FLOAT:
9f20696e 2317 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
6159a875 2318 break;
42d7ed00 2319 case DCI_DT_STRING:
6159a875
VK
2320 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
2321 break;
2322 }
2323 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
ebebc8ea
VK
2324 }
2325 DBFreeAsyncResult(hResult);
9f20696e 2326 pData->dwNumRows = htonl(dwNumRows);
6159a875
VK
2327
2328 // Prepare and send raw message with fetched data
2329 m_pSendQueue->Put(
2330 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
2331 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
2332 pData, NULL));
2333 free(pData);
2334 bSuccess = TRUE;
ebebc8ea 2335 }
62d11997
VK
2336 else
2337 {
2338 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2339 }
ebebc8ea
VK
2340 }
2341 else
2342 {
2343 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2344 }
2345 }
2346 else // No object with given ID
2347 {
2348 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2349 }
2350
2351 // Send responce
6159a875
VK
2352 if (!bSuccess)
2353 SendMessage(&msg);
ebebc8ea 2354}
06e7be2f
VK
2355
2356
20aaa307
VK
2357//
2358// Send latest collected values for all DCIs of given node
2359//
2360
2361void ClientSession::SendLastValues(CSCPMessage *pRequest)
2362{
2363 CSCPMessage msg;
2364 NetObj *pObject;
2365
2366 // Prepare responce message
2367 msg.SetCode(CMD_REQUEST_COMPLETED);
2368 msg.SetId(pRequest->GetId());
2369
2370 // Get node id and check object class and access rights
2371 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2372 if (pObject != NULL)
2373 {
2374 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2375 {
2376 if (pObject->Type() == OBJECT_NODE)
2377 {
2378 msg.SetVariable(VID_RCC, ((Node *)pObject)->GetLastValues(&msg));
2379 }
2380 else
2381 {
2382 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2383 }
2384 }
2385 else
2386 {
2387 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2388 }
2389 }
2390 else // No object with given ID
2391 {
2392 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2393 }
2394
2395 // Send responce
2396 SendMessage(&msg);
2397}
2398
2399
06e7be2f
VK
2400//
2401// Open event processing policy
2402//
2403
2404void ClientSession::OpenEPP(DWORD dwRqId)
2405{
2406 CSCPMessage msg;
2407 char szBuffer[256];
2408 BOOL bSuccess = FALSE;
2409
2410 // Prepare responce message
2411 msg.SetCode(CMD_REQUEST_COMPLETED);
2412 msg.SetId(dwRqId);
2413
2414 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2415 {
2416 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
2417 {
2418 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2419 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2420 }
2421 else
2422 {
2423 m_dwFlags |= CSF_EPP_LOCKED;
2424 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2425 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
2426 bSuccess = TRUE;
2427 }
2428 }
2429 else
2430 {
2431 // Current user has no rights for event policy management
2432 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2433 }
2434
2435 // Send responce
2436 SendMessage(&msg);
2437
2438 // Send policy to client
2439 if (bSuccess)
2440 g_pEventPolicy->SendToClient(this, dwRqId);
2441}
2442
2443
2444//
2445// Close event processing policy
2446//
2447
2448void ClientSession::CloseEPP(DWORD dwRqId)
2449{
2450 CSCPMessage msg;
2451
2452 // Prepare responce message
2453 msg.SetCode(CMD_REQUEST_COMPLETED);
2454 msg.SetId(dwRqId);
2455
2456 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2457 {
2458 if (m_dwFlags & CSF_EPP_LOCKED)
2459 {
2460 UnlockComponent(CID_EPP);
2461 m_dwFlags &= ~CSF_EPP_LOCKED;
2462 }
2463 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2464 }
2465 else
2466 {
2467 // Current user has no rights for event policy management
2468 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2469 }
2470
2471 // Send responce
2472 SendMessage(&msg);
2473}
2474
2475
2476//
2477// Save event processing policy
2478//
2479
8f7e2482 2480void ClientSession::SaveEPP(CSCPMessage *pRequest)
06e7be2f 2481{
8f7e2482
VK
2482 CSCPMessage msg;
2483
2484 // Prepare responce message
2485 msg.SetCode(CMD_REQUEST_COMPLETED);
2486 msg.SetId(pRequest->GetId());
2487
2488 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2489 {
2490 if (m_dwFlags & CSF_EPP_LOCKED)
2491 {
2492 msg.SetVariable(VID_RCC, RCC_SUCCESS);
8f7e2482
VK
2493 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
2494 m_dwRecordsUploaded = 0;
043fe1ec
VK
2495 if (m_dwNumRecordsToUpload == 0)
2496 {
2497 g_pEventPolicy->ReplacePolicy(0, NULL);
2498 g_pEventPolicy->SaveToDB();
2499 }
2500 else
2501 {
2502 m_dwFlags |= CSF_EPP_UPLOAD;
2503 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2504 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2505 }
8f7e2482
VK
2506 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2507 }
2508 else
2509 {
2510 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2511 }
2512 }
2513 else
2514 {
2515 // Current user has no rights for event policy management
2516 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2517 }
2518
2519 // Send responce
2520 SendMessage(&msg);
06e7be2f
VK
2521}
2522
2523
2524//
8f7e2482 2525// Process EPP rule received from client
06e7be2f
VK
2526//
2527
8f7e2482 2528void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
06e7be2f 2529{
8f7e2482
VK
2530 if (!(m_dwFlags & CSF_EPP_LOCKED))
2531 {
2532 CSCPMessage msg;
2533
2534 msg.SetCode(CMD_REQUEST_COMPLETED);
2535 msg.SetId(pRequest->GetId());
2536 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2537 SendMessage(&msg);
2538 }
2539 else
2540 {
2541 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2542 {
2543 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2544 m_dwRecordsUploaded++;
2545 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2546 {
2547 CSCPMessage msg;
2548
2549 // All records received, replace event policy...
2550 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2551 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2552 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
043fe1ec 2553 g_pEventPolicy->SaveToDB();
8f7e2482
VK
2554 m_ppEPPRuleList = NULL;
2555
2556 // ... and send final confirmation
2557 msg.SetCode(CMD_REQUEST_COMPLETED);
2558 msg.SetId(pRequest->GetId());
2559 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2560 SendMessage(&msg);
2561
2562 m_dwFlags &= ~CSF_EPP_UPLOAD;
2563 }
2564 }
2565 }
06e7be2f
VK
2566}
2567
2568
2569//
2570// Send list of available MIB files to client
2571//
2572
2573void ClientSession::SendMIBList(DWORD dwRqId)
2574{
2575 CSCPMessage msg;
2576 DWORD dwId1, dwId2, dwNumFiles;
2577 DIR *dir;
2578 int iBufPos;
c9ccd685 2579 struct dirent *dptr;
06e7be2f
VK
2580 char szBuffer[MAX_PATH];
2581 BYTE md5Hash[MD5_DIGEST_SIZE];
2582
2583 // Prepare responce message
2584 msg.SetCode(CMD_MIB_LIST);
2585 msg.SetId(dwRqId);
2586
2587 // Read directory
2588 dwNumFiles = 0;
2589 strcpy(szBuffer, g_szDataDir);
2590 strcat(szBuffer, DDIR_MIBS);
2591 dir = opendir(szBuffer);
2592 if (dir != NULL)
2593 {
06f6e54c 2594 strcat(szBuffer, FS_PATH_SEPARATOR);
06e7be2f
VK
2595 iBufPos = strlen(szBuffer);
2596 dwId1 = VID_MIB_NAME_BASE;
2597 dwId2 = VID_MIB_HASH_BASE;
2598 while((dptr = readdir(dir)) != NULL)
2599 {
06f6e54c
VK
2600 if (dptr->d_name[0] == '.')
2601 continue;
2602
06e7be2f
VK
2603 strcpy(&szBuffer[iBufPos], dptr->d_name);
2604 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2605 {
2606 msg.SetVariable(dwId1++, dptr->d_name);
2607 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2608 dwNumFiles++;
2609 }
2610 }
2611 closedir(dir);
2612 }
2613
2614 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2615
2616 // Send responce
2617 SendMessage(&msg);
2618}
2619
2620
2621//
2622// Send requested MIB file to client
2623//
2624
2625void ClientSession::SendMIB(CSCPMessage *pRequest)
2626{
2627 CSCPMessage msg;
2628 BYTE *pFile;
2629 DWORD dwFileSize;
2630 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2631
2632 // Prepare responce message
2633 msg.SetCode(CMD_MIB);
2634 msg.SetId(pRequest->GetId());
2635
2636 // Get name of the requested file
2637 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2638
2639 // Load file into memory
2640 strcpy(szBuffer, g_szDataDir);
2641 strcat(szBuffer, DDIR_MIBS);
2642#ifdef _WIN32
2643 strcat(szBuffer, "\\");
2644#else
2645 strcat(szBuffer, "/");
2646#endif
2647 strcat(szBuffer, szMIB);
2648 pFile = LoadFile(szBuffer, &dwFileSize);
2649 if (pFile != NULL)
2650 {
2651 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2652 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2653 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2654 free(pFile);
2655 }
2656 else
2657 {
2658 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2659 }
2660
2661 // Send responce
2662 SendMessage(&msg);
3421c063
VK
2663}
2664
2665
ef44d5ea
VK
2666//
2667// Create new object
2668//
2669
2670void ClientSession::CreateObject(CSCPMessage *pRequest)
2671{
e6b958c4
VK
2672 CSCPMessage msg;
2673 NetObj *pObject, *pParent;
b61fe31e
VK
2674 int iClass, iServiceType;
2675 TCHAR *pDescription, szObjectName[MAX_OBJECT_NAME];
2676 TCHAR *pszRequest, *pszResponce;
b688074e 2677 DWORD dwIpAddr;
b61fe31e 2678 WORD wIpProto, wIpPort;
b688074e 2679 BOOL bParentAlwaysValid = FALSE;
e6b958c4
VK
2680
2681 // Prepare responce message
2682 msg.SetCode(CMD_REQUEST_COMPLETED);
2683 msg.SetId(pRequest->GetId());
2684
b688074e
VK
2685 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2686
e6b958c4
VK
2687 // Find parent object
2688 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
7cbe553e 2689 if (iClass == OBJECT_NODE)
b688074e
VK
2690 {
2691 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
7cbe553e
VK
2692 if ((pParent == NULL) && (dwIpAddr != 0))
2693 {
2694 pParent = FindSubnetForNode(dwIpAddr);
2695 bParentAlwaysValid = TRUE;
2696 }
b688074e
VK
2697 }
2698 if ((pParent != NULL) || (iClass == OBJECT_NODE))
e6b958c4
VK
2699 {
2700 // User should have create access to parent object
b688074e
VK
2701 if ((pParent != NULL) ?
2702 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2703 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
e6b958c4 2704 {
62d11997 2705 // Parent object should be of valid type
b688074e 2706 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
e6b958c4 2707 {
e6b958c4 2708 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
8f7e2482 2709 if (IsValidObjectName(szObjectName))
e6b958c4 2710 {
62d11997
VK
2711 // Create new object
2712 switch(iClass)
e6b958c4 2713 {
62d11997 2714 case OBJECT_NODE:
b688074e 2715 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
62d11997
VK
2716 DF_DEFAULT, szObjectName);
2717 break;
2718 case OBJECT_CONTAINER:
2719 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2720 pObject = new Container(szObjectName,
2721 pRequest->GetVariableLong(VID_CATEGORY),
2722 pDescription);
2723 safe_free(pDescription);
2724 NetObjInsert(pObject, TRUE);
2725 break;
2726 case OBJECT_TEMPLATEGROUP:
2727 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2728 pObject = new TemplateGroup(szObjectName, pDescription);
2729 safe_free(pDescription);
2730 NetObjInsert(pObject, TRUE);
2731 break;
2732 case OBJECT_TEMPLATE:
2733 pObject = new Template;
2734 pObject->SetName(szObjectName);
2735 NetObjInsert(pObject, TRUE);
2736 break;
b61fe31e
VK
2737 case OBJECT_NETWORKSERVICE:
2738 iServiceType = (int)pRequest->GetVariableShort(VID_SERVICE_TYPE);
2739 wIpProto = pRequest->GetVariableShort(VID_IP_PROTO);
2740 wIpPort = pRequest->GetVariableShort(VID_IP_PORT);
2741 pszRequest = pRequest->GetVariableStr(VID_SERVICE_REQUEST);
2742 pszResponce = pRequest->GetVariableStr(VID_SERVICE_RESPONCE);
2743 pObject = new NetworkService(iServiceType, wIpProto, wIpPort,
2744 pszRequest, pszResponce, (Node *)pParent);
2745 pObject->SetName(szObjectName);
2746 NetObjInsert(pObject, TRUE);
2747 break;
62d11997 2748 }
917aa2e6 2749
62d11997
VK
2750 // If creation was successful do binding
2751 if (pObject != NULL)
2752 {
7cbe553e
VK
2753 if (pParent != NULL) // parent can be NULL for nodes
2754 {
2755 pParent->AddChild(pObject);
2756 pObject->AddParent(pParent);
b61fe31e 2757 pParent->CalculateCompoundStatus();
7cbe553e 2758 }
62d11997
VK
2759 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2760 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
917aa2e6
VK
2761 }
2762 else
2763 {
62d11997 2764 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
917aa2e6 2765 }
e6b958c4
VK
2766 }
2767 else
2768 {
8f7e2482 2769 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
e6b958c4
VK
2770 }
2771 }
2772 else
2773 {
2774 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2775 }
2776 }
2777 else
2778 {
2779 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2780 }
2781 }
2782 else
2783 {
2784 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2785 }
2786
2787 // Send responce
2788 SendMessage(&msg);
2789}
2790
2791
2792//
2793// Bind/unbind object
2794//
2795
2796void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2797{
2798 CSCPMessage msg;
2799 NetObj *pParent, *pChild;
2800
2801 // Prepare responce message
2802 msg.SetCode(CMD_REQUEST_COMPLETED);
2803 msg.SetId(pRequest->GetId());
2804
2805 // Get parent and child objects
2806 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2807 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2808
2809 // Check access rights and change binding
2810 if ((pParent != NULL) && (pChild != NULL))
2811 {
2812 // User should have modify access to both objects
2813 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2814 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2815 {
2816 // Parent object should be container or service root
2817 if ((pParent->Type() == OBJECT_CONTAINER) ||
2818 (pParent->Type() == OBJECT_SERVICEROOT))
2819 {
2820 if (bBind)
2821 {
917aa2e6
VK
2822 // Prevent loops
2823 if (!pChild->IsChild(pParent->Id()))
2824 {
2825 pParent->AddChild(pChild);
2826 pChild->AddParent(pParent);
b61fe31e 2827 pParent->CalculateCompoundStatus();
917aa2e6
VK
2828 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2829 }
2830 else
2831 {
2832 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2833 }
e6b958c4
VK
2834 }
2835 else
2836 {
2837 pParent->DeleteChild(pChild);
2838 pChild->DeleteParent(pParent);
917aa2e6 2839 msg.SetVariable(VID_RCC, RCC_SUCCESS);
e6b958c4 2840 }
e6b958c4
VK
2841 }
2842 else
2843 {
2844 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2845 }
2846 }
2847 else
2848 {
2849 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2850 }
2851 }
2852 else
2853 {
2854 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2855 }
2856
2857 // Send responce
2858 SendMessage(&msg);
ef44d5ea 2859}
03482383
VK
2860
2861
88039e6c
VK
2862//
2863// Delete object
2864//
2865
2866void ClientSession::DeleteObject(CSCPMessage *pRequest)
2867{
2868 CSCPMessage msg;
2869 NetObj *pObject;
2870
2871 // Prepare responce message
2872 msg.SetCode(CMD_REQUEST_COMPLETED);
2873 msg.SetId(pRequest->GetId());
2874
2875 // Find object to be deleted
2876 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2877 if (pObject != NULL)
2878 {
2879 // Check if it is a built-in object, like "Entire Network"
2880 if (pObject->Id() >= 10)
2881 {
2882 // Check access rights
2883 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2884 {
9a029be8 2885 pObject->Delete(FALSE);
88039e6c
VK
2886 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2887 }
2888 else
2889 {
2890 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2891 }
2892 }
2893 else
2894 {
2895 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2896 }
2897 }
2898 else
2899 {
2900 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2901 }
2902
2903 // Send responce
2904 SendMessage(&msg);
2905}
2906
2907
03482383
VK
2908//
2909// Process changes in alarms
2910//
2911
2912void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2913{
2914 UPDATE_INFO *pUpdate;
2915 NetObj *pObject;
2916
cb7ec554 2917 if (IsAuthenticated())
03482383
VK
2918 {
2919 pObject = FindObjectById(pAlarm->dwSourceObject);
2920 if (pObject != NULL)
2921 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2922 {
2923 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2924 pUpdate->dwCategory = INFO_CAT_ALARM;
c9363772
VK
2925 pUpdate->dwCode = dwCode;
2926 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
03482383
VK
2927 m_pUpdateQueue->Put(pUpdate);
2928 }
2929 }
2930}
2931
2932
2933//
2934// Send all alarms to client
2935//
2936
2937void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2938{
2939 MutexLock(m_mutexSendAlarms, INFINITE);
2940 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2941 MutexUnlock(m_mutexSendAlarms);
2942}
ee20e615
VK
2943
2944
2945//
2946// Acknowlege alarm
2947//
2948
2949void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2950{
2951 CSCPMessage msg;
2952 NetObj *pObject;
2953 DWORD dwAlarmId;
2954
2955 // Prepare responce message
2956 msg.SetCode(CMD_REQUEST_COMPLETED);
2957 msg.SetId(pRequest->GetId());
2958
2959 // Get alarm id and it's source object
2960 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2961 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2962 if (pObject != NULL)
2963 {
2964 // User should have "acknowlege alarm" right to the object
2965 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2966 {
2967 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2968 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2969 }
2970 else
2971 {
2972 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2973 }
2974 }
2975 else
2976 {
2977 // Normally, for existing alarms pObject will not be NULL,
2978 // so we assume that alarm id is invalid
2979 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2980 }
2981
2982 // Send responce
2983 SendMessage(&msg);
2984}
c9363772
VK
2985
2986
ae3a55d9
VK
2987//
2988// Delete alarm
2989//
2990
2991void ClientSession::DeleteAlarm(CSCPMessage *pRequest)
2992{
2993 CSCPMessage msg;
2994 NetObj *pObject;
2995 DWORD dwAlarmId;
2996
2997 // Prepare responce message
2998 msg.SetCode(CMD_REQUEST_COMPLETED);
2999 msg.SetId(pRequest->GetId());
3000
3001 // Get alarm id and it's source object
3002 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
3003 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
3004 if (pObject != NULL)
3005 {
3006 // User should have "acknowlege alarm" right to the object
3007 // and system right "delete alarms"
3008 if ((pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS)) &&
3009 (m_dwSystemAccess & SYSTEM_ACCESS_DELETE_ALARMS))
3010 {
3011 g_alarmMgr.DeleteAlarm(dwAlarmId);
3012 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3013 }
3014 else
3015 {
3016 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3017 }
3018 }
3019 else
3020 {
3021 // Normally, for existing alarms pObject will not be NULL,
3022 // so we assume that alarm id is invalid
3023 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
3024 }
3025
3026 // Send responce
3027 SendMessage(&msg);
3028}
3029
3030
c9363772
VK
3031//
3032// Lock/unlock action configuration database
3033//
3034
3035void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
3036{
3037 CSCPMessage msg;
3038 char szBuffer[256];
3039
3040 // Prepare responce message
3041 msg.SetCode(CMD_REQUEST_COMPLETED);
3042 msg.SetId(dwRqId);
3043
3044 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3045 {
3046 if (bLock)
3047 {
3048 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3049 {
3050 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3051 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3052 }
3053 else
3054 {
3055 m_dwFlags |= CSF_ACTION_DB_LOCKED;
3056 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3057 }
3058 }
3059 else
3060 {
3061 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
3062 {
3063 UnlockComponent(CID_ACTION_DB);
3064 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
3065 }
3066 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3067 }
3068 }
3069 else
3070 {
3071 // Current user has no rights for action management
3072 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3073 }
3074
3075 // Send responce
3076 SendMessage(&msg);
3077}
3078
3079
3080//
3081// Create new action
3082//
3083
3084void ClientSession::CreateAction(CSCPMessage *pRequest)
3085{
3086 CSCPMessage msg;
3087
3088 // Prepare responce message
3089 msg.SetCode(CMD_REQUEST_COMPLETED);
3090 msg.SetId(pRequest->GetId());
3091
3092 // Check user rights
3093 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3094 {
3095 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3096 }
3097 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3098 {
3099 // Action database have to be locked before any
3100 // changes can be made
3101 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3102 }
3103 else
3104 {
3105 DWORD dwResult, dwActionId;
3106 char szActionName[MAX_USER_NAME];
3107
3108 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
3109 if (IsValidObjectName(szActionName))
3110 {
3111 dwResult = CreateNewAction(szActionName, &dwActionId);
3112 msg.SetVariable(VID_RCC, dwResult);
3113 if (dwResult == RCC_SUCCESS)
3114 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
3115 }
3116 else
3117 {
3118 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3119 }
3120 }
3121
3122 // Send responce
3123 SendMessage(&msg);
3124}
3125
3126
3127//
3128// Update existing action's data
3129//
3130
3131void ClientSession::UpdateAction(CSCPMessage *pRequest)
3132{
3133 CSCPMessage msg;
3134
3135 // Prepare responce message
3136 msg.SetCode(CMD_REQUEST_COMPLETED);
3137 msg.SetId(pRequest->GetId());
3138
3139 // Check user rights
3140 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3141 {
3142 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3143 }
3144 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3145 {
3146 // Action database have to be locked before any
3147 // changes can be made
3148 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3149 }
3150 else
3151 {
15b8d488 3152 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
c9363772
VK
3153 }
3154
3155 // Send responce
3156 SendMessage(&msg);
3157}
3158
3159
3160//
3161// Delete action
3162//
3163
3164void ClientSession::DeleteAction(CSCPMessage *pRequest)
3165{
3166 CSCPMessage msg;
3167 DWORD dwActionId;
3168
3169 // Prepare responce message
3170 msg.SetCode(CMD_REQUEST_COMPLETED);
3171 msg.SetId(pRequest->GetId());
3172
3173 // Check user rights
3174 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3175 {
3176 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3177 }
3178 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3179 {
3180 // Action database have to be locked before any
3181 // changes can be made
3182 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3183 }
3184 else
3185 {
3186 // Get Id of action to be deleted
3187 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
d72d004b
VK
3188 if (!g_pEventPolicy->ActionInUse(dwActionId))
3189 {
3190 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
3191 }
3192 else
3193 {
3194 msg.SetVariable(VID_RCC, RCC_ACTION_IN_USE);
3195 }
c9363772
VK
3196 }
3197
3198 // Send responce
3199 SendMessage(&msg);
3200}
3201
3202
3203//
3204// Process changes in actions
3205//
3206
3207void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
3208{
3209 UPDATE_INFO *pUpdate;
3210
cb7ec554 3211 if (IsAuthenticated())
c9363772
VK
3212 {
3213 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3214 {
3215 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
3216 pUpdate->dwCategory = INFO_CAT_ACTION;
3217 pUpdate->dwCode = dwCode;
3218 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
3219 m_pUpdateQueue->Put(pUpdate);
3220 }
3221 }
3222}
e91cb822
VK
3223
3224
3225//
3226// Send all actions to client
3227//
3228
3229void ClientSession::SendAllActions(DWORD dwRqId)
3230{
3231 CSCPMessage msg;
3232
3233 // Prepare responce message
3234 msg.SetCode(CMD_REQUEST_COMPLETED);
3235 msg.SetId(dwRqId);
3236
3237 // Check user rights
3238 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
3239 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
3240 {
3241 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3242 SendMessage(&msg);
3243 MutexLock(m_mutexSendActions, INFINITE);
3244 SendActionsToClient(this, dwRqId);
3245 MutexUnlock(m_mutexSendActions);
3246 }
3247 else
3248 {
3249 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3250 SendMessage(&msg);
3251 }
3252}
6849d9be
VK
3253
3254
3255//
3256// Send list of configured container categories to client
3257//
3258
3259void ClientSession::SendContainerCategories(DWORD dwRqId)
3260{
3261 CSCPMessage msg;
3262 DWORD i;
3263
3264 // Prepare responce message
3265 msg.SetCode(CMD_CONTAINER_CAT_DATA);
3266 msg.SetId(dwRqId);
3267
3268 for(i = 0; i < g_dwNumCategories; i++)
3269 {
3270 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
3271 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
3272 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
3273 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
3274 SendMessage(&msg);
3275 msg.DeleteAllVariables();
3276 }
3277
3278 // Send end-of-list indicator
3279 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
3280 SendMessage(&msg);
3281}
0b89f5fb
VK
3282
3283
3284//
3285// Perform a forced node poll
3286//
3287
3288void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
3289{
eb8b1960 3290 CSCPMessage msg;
d966d18a 3291 POLLER_START_DATA *pData;
eb8b1960 3292 NetObj *pObject;
d966d18a
VK
3293
3294 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
0ba90743 3295 pData->pSession = this;
d966d18a 3296 MutexLock(m_mutexPollerInit, INFINITE);
eb8b1960
VK
3297
3298 // Prepare responce message
d966d18a 3299 pData->dwRqId = pRequest->GetId();
eb8b1960 3300 msg.SetCode(CMD_POLLING_INFO);
d966d18a 3301 msg.SetId(pData->dwRqId);
eb8b1960
VK
3302
3303 // Get polling type
d966d18a 3304 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
eb8b1960
VK
3305
3306 // Find object to be deleted
3307 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3308 if (pObject != NULL)
3309 {
3310 // We can do polls only for node objects
3311 if ((pObject->Type() == OBJECT_NODE) &&
d966d18a 3312 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
eb8b1960
VK
3313 {
3314 // Check access rights
3315 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3316 {
3317 ((Node *)pObject)->IncRefCount();
5109017e 3318 m_dwRefCount++;
eb8b1960 3319
d966d18a
VK
3320 pData->pNode = (Node *)pObject;
3321 ThreadCreate(PollerThreadStarter, 0, pData);
3322 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3323 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
eb8b1960
VK
3324 }
3325 else
3326 {
3327 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3328 }
3329 }
3330 else
3331 {
3332 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3333 }
3334 }
3335 else
3336 {
3337 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3338 }
3339
3340 // Send responce
3341 SendMessage(&msg);
d966d18a 3342 MutexUnlock(m_mutexPollerInit);
eb8b1960
VK
3343}
3344
3345
3346//
3347// Send message fro poller to client
3348//
3349
d966d18a 3350void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
eb8b1960
VK
3351{
3352 CSCPMessage msg;
3353
3354 msg.SetCode(CMD_POLLING_INFO);
d966d18a 3355 msg.SetId(dwRqId);
eb8b1960
VK
3356 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3357 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
3358 SendMessage(&msg);
0b89f5fb 3359}
d966d18a
VK
3360
3361
3362//
3363// Node poller thread
3364//
3365
3366void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
3367{
3368 CSCPMessage msg;
3369
3370 // Wait while parent thread finishes initialization
3371 MutexLock(m_mutexPollerInit, INFINITE);
3372 MutexUnlock(m_mutexPollerInit);
3373
0ba90743
VK
3374 switch(iPollType)
3375 {
3376 case POLL_STATUS:
3377 pNode->StatusPoll(this, dwRqId);
3378 break;
3379 case POLL_CONFIGURATION:
3380 pNode->ConfigurationPoll(this, dwRqId);
3381 break;
3382 default:
3383 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
3384 break;
3385 }
d966d18a
VK
3386 pNode->DecRefCount();
3387
3388 msg.SetCode(CMD_POLLING_INFO);
3389 msg.SetId(dwRqId);
3390 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3391 SendMessage(&msg);
3392}
b562fca8
VK
3393
3394
3395//
3396// Receive event from user
3397//
3398
3399void ClientSession::OnTrap(CSCPMessage *pRequest)
3400{
3401 CSCPMessage msg;
3402 DWORD dwObjectId, dwEventCode;
3403 int i, iNumArgs;
3404 NetObj *pObject;
3405 TCHAR *pszArgList[32];
3406 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
3407 BOOL bSuccess;
3408
3409 // Prepare responce message
3410 msg.SetCode(CMD_REQUEST_COMPLETED);
3411 msg.SetId(pRequest->GetId());
3412
3413 // Find event's source object
3414 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3415 if (dwObjectId != 0)
3416 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
3417 else
3418 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
3419 if (pObject != NULL)
3420 {
3421 // User should have SEND_EVENTS access right to object
3422 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
3423 {
c19b2871 3424 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
b562fca8
VK
3425 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
3426 for(i = 0; i < iNumArgs; i++)
3427 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
3428
3429 // Following call is not very good, but I'm too lazy now
3430 // to change PostEvent()
3431 szFormat[iNumArgs] = 0;
3432 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
3433 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
3434 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
3435 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
3436 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
3437 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
3438 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
3439 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
6ed0d23d 3440 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
b562fca8
VK
3441
3442 // Cleanup
3443 for(i = 0; i < iNumArgs; i++)
3444 free(pszArgList[i]);
3445
3446 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
3447 }
3448 else
3449 {
3450 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3451 }
3452 }
3453 else
3454 {
3455 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3456 }
3457
3458 // Send responce
3459 SendMessage(&msg);
3460}
ed1140dc
VK
3461
3462
3463//
3464// Wake up node
3465//
3466
3467void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
3468{
3469 NetObj *pObject;
3470 CSCPMessage msg;
3471
3472 // Prepare responce message
3473 msg.SetCode(CMD_REQUEST_COMPLETED);
3474 msg.SetId(pRequest->GetId());
3475
3476 // Find node or interface object
3477 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3478 if (pObject != NULL)
3479 {
3480 if ((pObject->Type() == OBJECT_NODE) ||
3481 (pObject->Type() == OBJECT_INTERFACE))
3482 {
3483 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3484 {
3485 DWORD dwResult;
3486
3487 if (pObject->Type() == OBJECT_NODE)
3488 dwResult = ((Node *)pObject)->WakeUp();
3489 else
3490 dwResult = ((Interface *)pObject)->WakeUp();
3491 msg.SetVariable(VID_RCC, dwResult);
3492 }
3493 else
3494 {
3495 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3496 }
3497 }
3498 else
3499 {
80de4676
VK
3500 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3501 }
3502 }
3503 else
3504 {
3505 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3506 }
3507
3508 // Send responce
3509 SendMessage(&msg);
3510}
3511
3512
3513//
3514// Query specific parameter from node
3515//
3516
3517void ClientSession::QueryParameter(CSCPMessage *pRequest)
3518{
3519 NetObj *pObject;
3520 CSCPMessage msg;
3521
3522 // Prepare responce message
3523 msg.SetCode(CMD_REQUEST_COMPLETED);
3524 msg.SetId(pRequest->GetId());
3525
3526 // Find node object
3527 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3528 if (pObject != NULL)
3529 {
3530 if (pObject->Type() == OBJECT_NODE)
3531 {
3532 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3533 {
3534 DWORD dwResult;
3535 TCHAR szBuffer[256], szName[MAX_PARAM_NAME];
3536
3537 pRequest->GetVariableStr(VID_NAME, szName, MAX_PARAM_NAME);
3538 dwResult = ((Node *)pObject)->GetItemForClient(pRequest->GetVariableShort(VID_DCI_SOURCE_TYPE),
3539 szName, szBuffer, 256);
3540 msg.SetVariable(VID_RCC, dwResult);
3541 if (dwResult == RCC_SUCCESS)
3542 msg.SetVariable(VID_VALUE, szBuffer);
3543 }
3544 else
3545 {
3546 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3547 }
3548 }
3549 else
3550 {
ed1140dc
VK
3551 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3552 }
3553 }
3554 else
3555 {
3556 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3557 }
3558
3559 // Send responce
3560 SendMessage(&msg);
3561}
b4895bbe
VK
3562
3563
3564//
693119d6 3565// Edit trap configuration record
b4895bbe
VK
3566//
3567
693119d6 3568void ClientSession::EditTrap(int iOperation, CSCPMessage *pRequest)
b4895bbe 3569{
106e7ae3 3570 CSCPMessage msg;
693119d6 3571 DWORD dwTrapId, dwResult;
106e7ae3
VK
3572
3573 // Prepare responce message
3574 msg.SetCode(CMD_REQUEST_COMPLETED);
3575 msg.SetId(pRequest->GetId());
3576
3577 // Check access rights
3578 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3579 {
3580 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3581 {
693119d6
VK
3582 switch(iOperation)
3583 {
3584 case TRAP_CREATE:
3585 dwResult = CreateNewTrap(&dwTrapId);
3586 msg.SetVariable(VID_RCC, dwResult);
3587 if (dwResult == RCC_SUCCESS)
3588 msg.SetVariable(VID_TRAP_ID, dwTrapId); // Send id of new trap to client
3589 break;
3590 case TRAP_UPDATE:
3591 msg.SetVariable(VID_RCC, UpdateTrapFromMsg(pRequest));
3592 break;
3593 case TRAP_DELETE:
3594 dwTrapId = pRequest->GetVariableLong(VID_TRAP_ID);
3595 msg.SetVariable(VID_RCC, DeleteTrap(dwTrapId));
3596 break;
3597 default:
3598 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
3599 break;
3600 }
106e7ae3
VK
3601 }
3602 else
3603 {
3604 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3605 }
3606 }
3607 else
3608 {
3609 // Current user has no rights for trap management
3610 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3611 }
3612
3613 // Send responce
3614 SendMessage(&msg);
b4895bbe
VK
3615}
3616
3617
3618//
3619// Lock/unlock trap configuration
3620//
3621
3622void ClientSession::LockTrapCfg(DWORD dwRqId, BOOL bLock)
3623{
840eb902
VK
3624 CSCPMessage msg;
3625 char szBuffer[256];
3626
3627 // Prepare responce message
3628 msg.SetCode(CMD_REQUEST_COMPLETED);
3629 msg.SetId(dwRqId);
3630
3631 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3632 {
3633 if (bLock)
3634 {
3635 if (!LockComponent(CID_TRAP_CFG, m_dwIndex, m_szUserName, NULL, szBuffer))
3636 {
3637 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3638 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3639 }
3640 else
3641 {
3642 m_dwFlags |= CSF_TRAP_CFG_LOCKED;
3643 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3644 }
3645 }
3646 else
3647 {
3648 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3649 {
3650 UnlockComponent(CID_TRAP_CFG);
3651 m_dwFlags &= ~CSF_TRAP_CFG_LOCKED;
3652 }
3653 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3654 }
3655 }
3656 else
3657 {
3658 // Current user has no rights for trap management
3659 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3660 }
3661
3662 // Send responce
3663 SendMessage(&msg);
b4895bbe
VK
3664}
3665
3666
3667//
3668// Send all trap configuration records to client
3669//
3670
3671void ClientSession::SendAllTraps(DWORD dwRqId)
3672{
840eb902
VK
3673 CSCPMessage msg;
3674 BOOL bSuccess = FALSE;
3675
3676 // Prepare responce message
3677 msg.SetCode(CMD_REQUEST_COMPLETED);
3678 msg.SetId(dwRqId);
3679
3680 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3681 {
3682 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3683 {
3684 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3685 SendMessage(&msg);
3686 bSuccess = TRUE;
3687 SendTrapsToClient(this, dwRqId);
3688 }
3689 else
3690 {
3691 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3692 }
3693 }
3694 else
3695 {
3696 // Current user has no rights for trap management
3697 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3698 }
3699
3700 // Send responce
3701 if (!bSuccess)
3702 SendMessage(&msg);
b4895bbe 3703}
1c8b8363
VK
3704
3705
5be45ff2
VK
3706//
3707// Lock/unlock package database
3708//
3709
3710void ClientSession::LockPackageDB(DWORD dwRqId, BOOL bLock)
3711{
3712 CSCPMessage msg;
3713 char szBuffer[256];
3714
3715 // Prepare responce message
3716 msg.SetCode(CMD_REQUEST_COMPLETED);
3717 msg.SetId(dwRqId);
3718
3719 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3720 {
3721 if (bLock)
3722 {
3723 if (!LockComponent(CID_PACKAGE_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3724