Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

555 lines
18 KiB

  1. /*---------------------------------------------------------------------------
  2. File: Monitor.cpp
  3. Comments: Functions to monitor the status of the DCT Agents.
  4. This involves spawning a thread which periodically reads the dispatch log,
  5. and scans the result directory for result files.
  6. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  7. Proprietary and confidential to Mission Critical Software, Inc.
  8. REVISION LOG ENTRY
  9. Revision By: Christy Boles
  10. Revised on 03/15/99 15:43:35
  11. ---------------------------------------------------------------------------
  12. */
  13. #include "StdAfx.h"
  14. #include "Resource.h"
  15. #include "Common.hpp"
  16. #include "Err.hpp"
  17. #include "UString.hpp"
  18. #include "TNode.hpp"
  19. #include "ServList.hpp"
  20. #include "Globals.h"
  21. #include "Monitor.h"
  22. #include "ResStr.h"
  23. #include <lm.h> // to remove result share
  24. //#import "\bin\McsVarSetMin.tlb" no_namespace , named_guids
  25. //#import "\bin\DBManager.tlb" no_namespace, named_guids
  26. #import "VarSet.tlb" no_namespace , named_guids rename("property", "aproperty")
  27. #import "DBMgr.tlb" no_namespace, named_guids
  28. //#include "..\Common\Include\McsPI.h"
  29. #include "McsPI.h"
  30. #include "McsPI_i.c"
  31. #include "afxdao.h"
  32. void LookForResults(WCHAR * dir = NULL);
  33. void WaitForMoreResults(WCHAR * dir);
  34. void ProcessResults(TServerNode * pServer, WCHAR const * directory, WCHAR const * filename);
  35. GlobalData gData;
  36. DWORD __stdcall ResultMonitorFn(void * arg)
  37. {
  38. WCHAR logdir[MAX_PATH] = L"";
  39. BOOL bFirstPassDone;
  40. CoInitialize(NULL);
  41. gData.GetFirstPassDone(&bFirstPassDone);
  42. // wait until the other monitoring thread has a chance to build the server list,
  43. // so we can check for pre-existing input files before using the changenotify mechanism
  44. while ( ! bFirstPassDone || !*logdir )
  45. {
  46. Sleep(500);
  47. gData.GetFirstPassDone(&bFirstPassDone);
  48. gData.GetResultDir(logdir);
  49. }
  50. LookForResults(logdir);
  51. WaitForMoreResults(logdir);
  52. CoUninitialize();
  53. return 0;
  54. }
  55. void WaitForMoreResults(WCHAR * logdir)
  56. {
  57. WCHAR resultWC[MAX_PATH];
  58. HANDLE hFind = INVALID_HANDLE_VALUE;
  59. BOOL bDone;
  60. long nIntervalSeconds;
  61. safecopy(resultWC,logdir);
  62. gData.GetDone(&bDone);
  63. gData.GetWaitInterval(&nIntervalSeconds);
  64. while (! bDone)
  65. {
  66. if (hFind == INVALID_HANDLE_VALUE)
  67. {
  68. hFind = FindFirstChangeNotification(resultWC, FALSE, FILE_NOTIFY_CHANGE_FILE_NAME);
  69. }
  70. if (hFind != INVALID_HANDLE_VALUE)
  71. WaitForSingleObject(hFind,nIntervalSeconds * 1000 );
  72. else
  73. Sleep(nIntervalSeconds * 1000);
  74. LookForResults(logdir);
  75. if (hFind != INVALID_HANDLE_VALUE)
  76. {
  77. if (! FindNextChangeNotification(hFind))
  78. {
  79. FindCloseChangeNotification(hFind);
  80. hFind = INVALID_HANDLE_VALUE;
  81. }
  82. }
  83. gData.GetDone(&bDone); // we still listen to global done
  84. // in case that we use it to force a stop
  85. gData.GetWaitInterval(&nIntervalSeconds);
  86. ComputerStats stats;
  87. gData.GetComputerStats(&stats);
  88. // if all agents either finished or failed, we consider it done
  89. if (stats.numFinished + stats.numError >= stats.total)
  90. break;
  91. }
  92. if (hFind != INVALID_HANDLE_VALUE)
  93. FindCloseChangeNotification(hFind);
  94. gData.SetDone(TRUE);
  95. }
  96. void LookForResults(WCHAR * arglogdir)
  97. {
  98. TNodeListEnum e;
  99. TServerNode * s;
  100. DWORD nInstalled = 0;
  101. DWORD nRunning = 0;
  102. DWORD nFinished = 0;
  103. DWORD nError = 0;
  104. HWND gListWnd;
  105. HWND gSummaryWnd;
  106. WCHAR logdir[MAX_PATH];
  107. if ( ! (arglogdir && *arglogdir) )
  108. {
  109. gData.GetResultDir(logdir);
  110. }
  111. else
  112. {
  113. safecopy(logdir,arglogdir);
  114. }
  115. for ( s = (TServerNode*)e.OpenFirst(gData.GetUnsafeServerList()) ; s ; gData.Lock(),s = (TServerNode*)e.Next(),gData.Unlock() )
  116. {
  117. if ( s->IsInstalled() )
  118. nInstalled++;
  119. if (s->HasFailed())
  120. nError++;
  121. // only when result has been processed do we consider it finished
  122. else if (s->IsFinished() && s->IsResultPullingTried() && (!s->HasResult() || s->IsResultProcessed()))
  123. nFinished++;
  124. else
  125. nRunning++;
  126. // Check jobs that finished, got result pulled but not yet processed
  127. if ( *s->GetJobFile() && s->IsFinished() && s->IsResultPullingTried()
  128. && s->HasResult() && !s->IsResultProcessed() )
  129. {
  130. // Look for results
  131. WCHAR resultWC[MAX_PATH];
  132. HANDLE hFind;
  133. WIN32_FIND_DATA fdata;
  134. WCHAR sTime[32];
  135. if ( logdir[UStrLen(logdir)-1] == L'\\' )
  136. {
  137. swprintf(resultWC,L"%s%s.result",logdir,s->GetJobFile());
  138. }
  139. else
  140. {
  141. swprintf(resultWC,L"%s\\%s.result",logdir,s->GetJobFile());
  142. }
  143. hFind = FindFirstFile(resultWC,&fdata);
  144. s->SetTimeStamp(gTTime.FormatIsoLcl( gTTime.Now( NULL ), sTime ));
  145. if ( hFind != INVALID_HANDLE_VALUE )
  146. {
  147. ProcessResults(s,logdir,fdata.cFileName);
  148. s->SetResultProcessed(TRUE);
  149. nRunning--;
  150. nFinished++;
  151. FindClose(hFind);
  152. }
  153. gData.GetListWindow(&gListWnd);
  154. SendMessage(gListWnd,DCT_UPDATE_ENTRY,NULL,(LPARAM)s);
  155. }
  156. }
  157. e.Close();
  158. // Update the summary window
  159. ComputerStats stat;
  160. // get the total servers number
  161. gData.GetComputerStats(&stat);
  162. stat.numError = nError;
  163. stat.numFinished = nFinished;
  164. stat.numRunning = nRunning;
  165. stat.numInstalled = nInstalled;
  166. gData.SetComputerStats(&stat);
  167. gData.GetSummaryWindow(&gSummaryWnd);
  168. SendMessage(gSummaryWnd,DCT_UPDATE_COUNTS,0,(LPARAM)&stat);
  169. }
  170. BOOL // ret- TRUE if successful
  171. ReadResults(
  172. TServerNode * pServer, // in - pointer to server node containing server name
  173. WCHAR const * directory, // in - directory where results files are stored
  174. WCHAR const * filename, // in - filename for this agent's job
  175. DetailStats * pStats, // out- counts of items processed by the agent
  176. CString & plugInText, // out- text results from plug-ins
  177. BOOL bStore // in - bool, whether to store plug-in text
  178. )
  179. {
  180. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  181. WCHAR path[MAX_PATH];
  182. HRESULT hr = S_OK;
  183. BOOL bSuccess = FALSE;
  184. if ( directory[UStrLen(directory)-1] == '\\' )
  185. {
  186. swprintf(path,L"%ls%ls",directory,filename);
  187. }
  188. else
  189. {
  190. swprintf(path,L"%ls\\%ls",directory,filename);
  191. }
  192. // Read the varset data from the file
  193. IVarSetPtr pVarSet;
  194. IStoragePtr store;
  195. // attempt to open result file
  196. for (int nTries = 0; nTries < 6; nTries++)
  197. {
  198. hr = StgOpenStorage(path, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &store);
  199. // if sharing or lock violation then...
  200. if ((hr == STG_E_SHAREVIOLATION) || (hr == STG_E_LOCKVIOLATION))
  201. {
  202. // wait one second before trying again
  203. Sleep(1000);
  204. }
  205. else
  206. {
  207. // otherwise stop trying
  208. break;
  209. }
  210. }
  211. if (SUCCEEDED(hr))
  212. {
  213. // load VarSet from file
  214. hr = OleLoad(store, IID_IVarSet, NULL, (void**)&pVarSet);
  215. }
  216. if ( SUCCEEDED(hr) )
  217. {
  218. pStats->directoriesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Directories_Changed));
  219. pStats->directoriesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Directories_Examined));
  220. pStats->directoriesUnchanged = (pStats->directoriesExamined - pStats->directoriesChanged);
  221. pStats->filesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Files_Changed));
  222. pStats->filesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Files_Examined));
  223. pStats->filesUnchanged = (pStats->filesExamined - pStats->filesChanged );
  224. pStats->sharesChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Shares_Changed));
  225. pStats->sharesExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Shares_Examined));
  226. pStats->sharesUnchanged = (pStats->sharesExamined - pStats->sharesChanged );
  227. pStats->membersChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Members_Changed));
  228. pStats->membersExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_Members_Examined));
  229. pStats->membersUnchanged = (pStats->membersExamined - pStats->membersChanged );
  230. pStats->rightsChanged = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_UserRights_Changed));
  231. pStats->rightsExamined = (long)pVarSet->get(GET_BSTR(DCTVS_Stats_UserRights_Examined));
  232. pStats->rightsUnchanged = (pStats->rightsExamined - pStats->rightsChanged );
  233. long level = pVarSet->get(GET_BSTR(DCTVS_Results_ErrorLevel));
  234. _bstr_t logfile = pVarSet->get(GET_BSTR(DCTVS_Results_LogFile));
  235. _bstr_t logfileIsInvalid = pVarSet->get(GET_BSTR(DCTVS_Results_LogFileIsInvalid));
  236. BOOL bLogfileIsInvalid =
  237. (!logfileIsInvalid == false && !UStrICmp(logfileIsInvalid, GET_STRING(IDS_YES))) ? TRUE : FALSE;
  238. if ( level > 2 )
  239. {
  240. CString message;
  241. message.FormatMessage(IDS_SeeLogForAgentErrors_S,(WCHAR*)logfile);
  242. pServer->SetMessageText(message.GetBuffer(0));
  243. }
  244. pServer->SetSeverity(level);
  245. // build the UNC path for the log file
  246. WCHAR logPath[MAX_PATH];
  247. swprintf(logPath,L"\\\\%s\\%c$\\%s",pServer->GetServer(),((WCHAR*)logfile)[0],((WCHAR*)logfile) + 3);
  248. if (bLogfileIsInvalid)
  249. {
  250. pServer->SetLogPath(logfile);
  251. pServer->SetLogPathValid(FALSE);
  252. }
  253. else
  254. {
  255. pServer->SetLogPath(logPath);
  256. pServer->SetLogPathValid(TRUE);
  257. }
  258. bSuccess = TRUE;
  259. // Try to get information from any plug-ins that ran
  260. // create the COM object for each plug-in
  261. _bstr_t bStrGuid;
  262. WCHAR key[300];
  263. CLSID clsid;
  264. for ( int i = 0 ; ; i++ )
  265. {
  266. swprintf(key,L"Plugin.%ld",i);
  267. bStrGuid = pVarSet->get(key);
  268. if ( bStrGuid.length() == 0 )
  269. break;
  270. IMcsDomPlugIn * pPlugIn = NULL;
  271. hr = CLSIDFromString(bStrGuid,&clsid);
  272. if ( SUCCEEDED(hr) )
  273. {
  274. hr = CoCreateInstance(clsid,NULL,CLSCTX_ALL,IID_IMcsDomPlugIn,(void**)&pPlugIn);
  275. if ( SUCCEEDED(hr) )
  276. {
  277. BSTR name = NULL;
  278. BSTR result = NULL;
  279. hr = pPlugIn->GetName(&name);
  280. if ( SUCCEEDED(hr) )
  281. {
  282. hr = pPlugIn->GetResultString(pVarSet,&result);
  283. if ( SUCCEEDED(hr) )
  284. {
  285. plugInText += (WCHAR*)name;
  286. plugInText += L"\n";
  287. plugInText += (WCHAR*)result;
  288. plugInText += L"\n\n";
  289. SysFreeString(result);
  290. }
  291. SysFreeString(name);
  292. if ( bStore )
  293. {
  294. pVarSet->put(L"LocalServer",pServer->GetServer());
  295. pPlugIn->StoreResults(pVarSet);
  296. }
  297. }
  298. pPlugIn->Release();
  299. }
  300. }
  301. }
  302. }
  303. else
  304. {
  305. CString message;
  306. CString title;
  307. if ( hr != STG_E_SHAREVIOLATION && hr != STG_E_LOCKVIOLATION )
  308. {
  309. message.FormatMessage(IDS_FailedToLoadResults,filename,hr);
  310. title.LoadString(IDS_MessageTitle);
  311. if ( hr != STG_E_FILENOTFOUND )
  312. MessageBox(NULL,message,title,MB_OK | MB_ICONERROR);
  313. }
  314. else
  315. {
  316. // the agent has still not finished writing its results file, for some reason
  317. // we'll check it again later
  318. pServer->SetStatus(pServer->GetStatus() & ~Agent_Status_Finished);
  319. }
  320. }
  321. return bSuccess;
  322. }
  323. void
  324. ProcessSecRefs(
  325. TServerNode * pServer,
  326. WCHAR const * directory,
  327. WCHAR const * filename
  328. )
  329. {
  330. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  331. const DWORD NOREF = 0;
  332. WCHAR path[MAX_PATH];
  333. DWORD rc = 0;
  334. BOOL bSuccess = FALSE;
  335. FILE * pFile;
  336. WCHAR * pDot;
  337. if ( directory[UStrLen(directory)-1] == '\\' )
  338. {
  339. swprintf(path,L"%ls%ls",directory,filename);
  340. }
  341. else
  342. {
  343. swprintf(path,L"%ls\\%ls",directory,filename);
  344. }
  345. // check to see if a secrefs file was written
  346. pDot = wcsrchr(path,L'.');
  347. if ( pDot )
  348. {
  349. UStrCpy(pDot,L".secrefs");
  350. pFile = _wfopen(path,L"rb");
  351. if ( pFile )
  352. {
  353. IIManageDBPtr pDB;
  354. rc = pDB.CreateInstance(CLSID_IManageDB);
  355. if ( SUCCEEDED(rc) )
  356. {
  357. // there are some secrefs here, load them into the database
  358. WCHAR account[300] = L"";
  359. WCHAR type[100] = L"";
  360. DWORD nOwner = 0;
  361. DWORD nGroup = 0;
  362. DWORD nDacl = 0;
  363. DWORD nSacl = 0;
  364. WCHAR domPart[300];
  365. WCHAR acctPart[300];
  366. WCHAR acctSid[300] = L"";
  367. WCHAR * slash;
  368. CString typeString;
  369. //remove any old references for this machine in the table
  370. _variant_t var;
  371. WCHAR sFilter[MAX_PATH];
  372. wsprintf(sFilter, L"Server = \"%s\"", pServer->GetServer());
  373. var = sFilter;
  374. rc = pDB->raw_ClearTable(L"AccountRefs", var);
  375. //move past the UNICODE Byte Order Mark
  376. fgetwc(pFile);
  377. //get entries
  378. while ( 7 == fwscanf(pFile,L"%[^,],%[^,],%[^,],%ld,%ld,%ld,%ld\r\n",account,acctSid,type,&nOwner,&nGroup,&nDacl,&nSacl) )
  379. {
  380. safecopy(domPart,account);
  381. slash = wcschr(domPart,L'\\');
  382. if ( slash )
  383. {
  384. *slash = 0;
  385. UStrCpy(acctPart,slash+1);
  386. }
  387. else
  388. {
  389. domPart[0] = 0;
  390. safecopy(acctPart,account);
  391. }
  392. //for sIDs with no resolvable account, change domain and account to (Unknown)
  393. if ((wcsstr(account, L"S-") == account) && (domPart[0] == 0))
  394. {
  395. wcscpy(acctPart, GET_STRING(IDS_UnknownSid));
  396. wcscpy(domPart, GET_STRING(IDS_UnknownSid));
  397. }
  398. if (nOwner != NOREF)
  399. {
  400. typeString.FormatMessage(IDS_OwnerRef_S,type);
  401. rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nOwner,typeString.AllocSysString());
  402. }
  403. if (nGroup != NOREF)
  404. {
  405. typeString.FormatMessage(IDS_GroupRef_S,type);
  406. rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nGroup,typeString.AllocSysString());
  407. }
  408. if (nDacl != NOREF)
  409. {
  410. //since local group members are not referenced in DACL, but we use that
  411. //field to keep track of reference, use a different type string
  412. if (!UStrCmp(type, GET_STRING(IDS_STReference_Member)))
  413. typeString.FormatMessage(IDS_MemberRef_S);
  414. else
  415. typeString.FormatMessage(IDS_DACLRef_S,type);
  416. rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nDacl,typeString.AllocSysString());
  417. }
  418. if (nSacl != NOREF)
  419. {
  420. typeString.FormatMessage(IDS_SACLRef_S,type);
  421. rc = pDB->raw_AddAcctRef(domPart,acctPart,acctSid,pServer->GetServer(),nSacl,typeString.AllocSysString());
  422. }
  423. // make sure there's not any data left over in these
  424. account[0] = 0;
  425. type[0] = 0;
  426. acctSid[0] = 0;
  427. nOwner = 0;
  428. nGroup = 0;
  429. nDacl = 0;
  430. nSacl = 0;
  431. }
  432. }
  433. fclose(pFile);
  434. }
  435. }
  436. }
  437. void
  438. ProcessResults(
  439. TServerNode * pServer,
  440. WCHAR const * directory,
  441. WCHAR const * filename
  442. )
  443. {
  444. HRESULT hr = S_OK;
  445. DetailStats stats;
  446. HWND hWnd;
  447. CString PLText;
  448. memset(&stats,0,(sizeof stats));
  449. if ( ReadResults(pServer,directory,filename,&stats,PLText,TRUE) )
  450. {
  451. if ( ! pServer->HasFailed() && ! pServer->GetSeverity() )
  452. {
  453. pServer->SetMessageText(L"");
  454. }
  455. gData.AddDetailStats(&stats);
  456. gData.GetSummaryWindow(&hWnd);
  457. // get the stats for this job, and send them to the summary window
  458. // SendMessage(hWnd, DCT_UPDATE_TOTALS, 0, (long)&stats);
  459. SendMessage(hWnd, DCT_UPDATE_TOTALS, 0, (LPARAM)&stats);
  460. }
  461. // also get import the security references
  462. if (pServer->IsAccountReferenceResultExpected())
  463. ProcessSecRefs(pServer,directory,filename);
  464. }