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.

775 lines
25 KiB

  1. #include "stdafx.h"
  2. #include "global.h"
  3. // to include CkdMonINI class definition
  4. #include "ini.h"
  5. #include "SMTP.h"
  6. // The name of current service
  7. // This variable is declared in global.cpp
  8. extern _TCHAR szServiceName[MAX_PATH];
  9. // just to get any kind of error through GetError() routine
  10. // This variable is declared in global.cpp
  11. extern _TCHAR szError[MAX_PATH];
  12. // this is used by LoadINI function also. So it is made global
  13. CkdMonINI kdMonINI;
  14. void kdMon() {
  15. // SMTP object
  16. CSMTP smtpObj;
  17. // This variable is used by IsSignaledToStop() function.
  18. // open the stop event which is created by kdMonSvc
  19. // For any event, the name of the event matters and the handle does not.
  20. HANDLE hStopEvent = NULL;
  21. // open the cszStopEvent which is meant to signal this thread to stop.
  22. // this signalling is done by main service thread when WM_QUIT is received
  23. hStopEvent = OpenEvent( EVENT_ALL_ACCESS,
  24. FALSE, // = handle can not be inherited
  25. (LPCTSTR)_T(cszStopEvent));
  26. if ( hStopEvent == NULL ) {
  27. GetError(szError);
  28. LogFatalEvent(_T("kdMon->OpenEvent: %s"), szError);
  29. AddServiceLog(_T("Error: kdMon->OpenEvent: %s\r\n"), szError);
  30. goto endkdMon;
  31. }
  32. BOOL bLoop;
  33. bLoop = TRUE;
  34. while(bLoop) {
  35. AddServiceLog(_T("\r\n- - - - - - @ @ @ @ @ @ @ @ @ @ - - - - - - - - - - - @ @ @ @ @ @ @ @ @ @ @ - - - - - - - \r\n"));
  36. // temperory boolean to receive return values from functions
  37. BOOL bRet;
  38. // load the values from INI file
  39. // since INI file is read each time the loop gets executed,
  40. // we can change the running parameters of the service on the fly
  41. // If values loading is not successful then close the service : bLoop = FALSE;
  42. bRet = LoadINI();
  43. if ( bRet == FALSE ) {
  44. bLoop = FALSE;
  45. goto closeandwait;
  46. }
  47. bRet = smtpObj.InitSMTP();
  48. // if SMTP can not be initiated, then do nothing. try in next database cycle.
  49. if ( bRet == FALSE ) {
  50. goto closeandwait;
  51. }
  52. // generate an array to store failure counts for each server
  53. ULONG *pulFailureCounts;
  54. pulFailureCounts = NULL;
  55. pulFailureCounts = (ULONG *) malloc (kdMonINI.dwServerCount * sizeof(ULONG));
  56. if ( pulFailureCounts == NULL ) {
  57. AddServiceLog(_T("Error: kdMon->malloc: Insufficient memory\r\n"));
  58. LogFatalEvent(_T("kdMon->malloc: Insufficient memory"));
  59. bLoop = FALSE;
  60. goto closeandwait;
  61. }
  62. // generate an array to store timestamp for count from each server
  63. ULONG *pulTimeStamps;
  64. pulTimeStamps = NULL;
  65. pulTimeStamps = (ULONG *) malloc (kdMonINI.dwServerCount * sizeof(ULONG));
  66. if ( pulTimeStamps == NULL ) {
  67. AddServiceLog(_T("Error: kdMon->malloc: Insufficient memory\r\n"));
  68. LogFatalEvent(_T("kdMon->malloc: Insufficient memory"));
  69. bLoop = FALSE;
  70. goto closeandwait;
  71. }
  72. // load the values from registry for the server to be monitored
  73. // since INI file is read each time the loop gets executed,
  74. // we can change the server names on the fly
  75. // we get counts for each server in pulFailureCounts
  76. // we get corresponding TimeStamps in pulTimeStamps
  77. bRet = ReadRegValues( kdMonINI.ppszServerNameArray,
  78. kdMonINI.dwServerCount,
  79. pulFailureCounts,
  80. pulTimeStamps);
  81. if ( bRet == FALSE )
  82. goto closeandwait;
  83. // counter to go through server names
  84. UINT uiServerCtr;
  85. for( uiServerCtr = 0; uiServerCtr < kdMonINI.dwServerCount; uiServerCtr++) {
  86. // prepare Log File Name on the server
  87. _TCHAR szKDFailureLogFile[MAX_PATH * 2];
  88. _stprintf(szKDFailureLogFile, _T("\\\\%s\\%s"),
  89. kdMonINI.ppszServerNameArray[uiServerCtr],
  90. kdMonINI.szDebuggerLogFile);
  91. ULONG ulRet;
  92. // scan the log file and get the count of number of lines
  93. ulRet = ScanLogFile(szKDFailureLogFile);
  94. // AddServiceLog(_T("ulRet = %ld\r\n"), ulRet);
  95. if ( ulRet == E_FILE_NOT_FOUND ) {
  96. // file not found means there are no Debugger errors
  97. // So put count = 0 and go on with next server
  98. pulFailureCounts[uiServerCtr] = 0;
  99. continue;
  100. }
  101. if ( ulRet == E_PATH_NOT_FOUND ) {
  102. // path not found means there is some network error
  103. // So put count = -1 so next time this count wont be valid
  104. // and go on with next server
  105. pulFailureCounts[uiServerCtr] = -1;
  106. continue;
  107. }
  108. // some other error occurred
  109. if ( ulRet == E_OTHER_FILE_ERROR ) {
  110. // So put count = -1 so next time this count wont be valid
  111. // and go on with next server
  112. pulFailureCounts[uiServerCtr] = -1;
  113. continue;
  114. }
  115. ULONG ulNumLines;
  116. ulNumLines = ulRet;
  117. // if previous count was -1 i.e. invalid, just put new count and move on
  118. // similar if previous TimeStamp was invalid
  119. if ( (pulFailureCounts[uiServerCtr] == -1) ||
  120. pulTimeStamps[uiServerCtr] == -1) {
  121. pulFailureCounts[uiServerCtr] = ulNumLines;
  122. continue;
  123. }
  124. // get the current system time
  125. // ulTimeStamp is like 200112171558
  126. ULONG ulCurrentTimeStamp;
  127. ulCurrentTimeStamp = GetCurrentTimeStamp();
  128. if ( ulCurrentTimeStamp == -1 ) {
  129. pulFailureCounts[uiServerCtr] = ulNumLines;
  130. continue;
  131. }
  132. // we have kdMonINI.dwRepeatTime in minutes (say 78)
  133. // take out hours and minutes (1 Hr 18 Min)
  134. // between 0112181608 and 0112181726 there is difference of 1 Hr 18 Min
  135. // but decimal difference is 118
  136. // between 0112181650 and 0112181808 there is difference of 1 Hr 18 Min
  137. // but decimal difference is 158
  138. // so we have some calculation here
  139. // what we will do is add the kdMonINI.dwRepeatTime to OldTS
  140. // modify the previous timestamp to do the comparison
  141. ULONG ulModifiedTS;
  142. ulModifiedTS = AddTime(pulTimeStamps[uiServerCtr], kdMonINI.dwRepeatTime);
  143. AddServiceLog(_T("Server: %s, OldTS: %ld, NewTS: %ld, OldCnt: %ld, NewCnt: %ld, ulModifiedTS = %ld\r\n"),
  144. kdMonINI.ppszServerNameArray[uiServerCtr],
  145. pulTimeStamps[uiServerCtr],
  146. ulCurrentTimeStamp,
  147. pulFailureCounts[uiServerCtr],
  148. ulNumLines, ulModifiedTS);
  149. // check the timestamp difference. Keep margin of 3
  150. // if the previous timestamp was > dwRepeatTime ago then dont do anything
  151. // just record the new count This case happens when there is a Servername in
  152. // INI, then it is removed for some time and then it is added again
  153. // this helps to send false mails out
  154. if ( ulCurrentTimeStamp > (ulModifiedTS + 3) ) {
  155. AddServiceLog(_T("Previous record invalid. ulCurrentTimeStamp: %ld, ulModifiedTS: %ld"),
  156. ulCurrentTimeStamp, ulModifiedTS);
  157. pulFailureCounts[uiServerCtr] = ulNumLines;
  158. continue;
  159. }
  160. // check the difference between current and previous counts
  161. ULONG ulFailures;
  162. ulFailures = ulNumLines - pulFailureCounts[uiServerCtr];
  163. if ( ulFailures >= kdMonINI.dwDebuggerThreshold ) {
  164. AddServiceLog(_T("KD failed. %ld errors in %ld minutes\r\n"),
  165. ulFailures, kdMonINI.dwRepeatTime);
  166. // fill the mail parameters structure
  167. StructMailParams stMailParams;
  168. _tcscpy(stMailParams.szFrom, kdMonINI.szFromMailID);
  169. _tcscpy(stMailParams.szTo, kdMonINI.szToMailID);
  170. _tcscpy(stMailParams.szServerName, kdMonINI.ppszServerNameArray[uiServerCtr]);
  171. stMailParams.ulFailures = ulFailures;
  172. stMailParams.ulInterval = kdMonINI.dwRepeatTime;
  173. stMailParams.ulCurrentTimestamp = ulCurrentTimeStamp;
  174. BOOL bRet;
  175. bRet = smtpObj.SendMail(stMailParams);
  176. // dont care even if you were not able to send mail
  177. //if ( bRet == FALSE )
  178. // goto nextserver;
  179. }
  180. // store new count in the array
  181. pulFailureCounts[uiServerCtr] = ulNumLines;
  182. // see if the date has changed, if yes then move the previous logfile to
  183. // new location
  184. // example of date change OldTS: 200112182348, NewTS: 200112190048
  185. // so divide timestamp by 10000 and you get 20011218 and 20011219 compare
  186. ULONG ulOldDate, ulNewDate;
  187. ulOldDate = pulTimeStamps[uiServerCtr]/10000;
  188. ulNewDate = ulCurrentTimeStamp/10000;
  189. if ( (ulNewDate - ulOldDate) >= 1 ) {
  190. AddServiceLog(_T("Day changed. Oldday: %ld, Newday: %ld\r\n"),
  191. ulOldDate, ulNewDate);
  192. // Log File Name
  193. _TCHAR szKDFailureLogFile[MAX_PATH * 2];
  194. _stprintf(szKDFailureLogFile, _T("\\\\%s\\%s"),
  195. kdMonINI.ppszServerNameArray[uiServerCtr],
  196. kdMonINI.szDebuggerLogFile);
  197. // now since date has changed, prepare archive filename
  198. _TCHAR szTimeStamp[MAX_PATH];
  199. _ltot(ulOldDate, szTimeStamp, 10);
  200. // prepare Archive Log File Name on the server
  201. _TCHAR szKDFailureArchiveFile[MAX_PATH * 2];
  202. _stprintf(szKDFailureArchiveFile, _T("%s\\%s_FailedAddCrash%s.log"),
  203. kdMonINI.szDebuggerLogArchiveDir,
  204. kdMonINI.ppszServerNameArray[uiServerCtr],
  205. szTimeStamp);
  206. AddServiceLog(_T("Moving file (%s -> %s)\r\n"),
  207. szKDFailureLogFile, szKDFailureArchiveFile);
  208. // copy file to destination
  209. if ( CopyFile(szKDFailureLogFile, szKDFailureArchiveFile, FALSE) ) {
  210. // try to delete the original kd failure log file
  211. if ( DeleteFile(szKDFailureLogFile) ) {
  212. // set new count to 0 since log has been moved successfully
  213. pulFailureCounts[uiServerCtr] = 0;
  214. }
  215. else {
  216. GetError(szError);
  217. AddServiceLog(_T("Error: kdMon->DeleteFile(%s): %s \r\n"),
  218. szKDFailureLogFile, szError);
  219. LogEvent(_T("Error: kdMon->DeleteFile(%s): %s"),
  220. szKDFailureLogFile, szError);
  221. // try to delete the copied file
  222. if ( DeleteFile(szKDFailureArchiveFile) ) {
  223. ;
  224. }
  225. else {
  226. GetError(szError);
  227. AddServiceLog(_T("Error: kdMon->DeleteFile(%s): %s \r\n"),
  228. szKDFailureArchiveFile, szError);
  229. LogEvent(_T("Error: kdMon->DeleteFile(%s): %s"),
  230. szKDFailureArchiveFile, szError);
  231. }
  232. }
  233. }
  234. else {
  235. GetError(szError);
  236. AddServiceLog(_T("Error: kdMon->CopyFile(%s, %s): %s \r\n"),
  237. szKDFailureLogFile, szKDFailureArchiveFile, szError);
  238. LogEvent(_T("Error: kdMon->CopyFile(%s, %s): %s"),
  239. szKDFailureLogFile, szKDFailureArchiveFile, szError);
  240. }
  241. }
  242. }
  243. // write the values to registry for the servers to be monitored
  244. // counts for each server are in pulFailureCounts
  245. // timestamp is current time
  246. bRet = WriteRegValues( kdMonINI.ppszServerNameArray,
  247. kdMonINI.dwServerCount,
  248. pulFailureCounts);
  249. if ( bRet == FALSE )
  250. goto closeandwait;
  251. closeandwait:
  252. // cleanup SMTP resources
  253. bRet = smtpObj.SMTPCleanup();
  254. if( bRet == FALSE ) {
  255. AddServiceLog(_T("Error: smtpObj.SMTPCleanup failed\r\n"));
  256. LogFatalEvent(_T("smtpObj.SMTPCleanup failed"));
  257. }
  258. // free uiFailureCounts
  259. if (pulFailureCounts != NULL)
  260. free(pulFailureCounts);
  261. // free pulTimeStamps
  262. if (pulTimeStamps != NULL)
  263. free(pulTimeStamps);
  264. // break the while loop if bLoop is false
  265. if (bLoop == FALSE) {
  266. goto endkdMon;
  267. }
  268. bRet = IsSignaledToStop(hStopEvent, kdMonINI.dwRepeatTime * 60 * 1000);
  269. if (bRet == TRUE) {
  270. goto endkdMon;
  271. }
  272. } // while(bLoop)
  273. endkdMon:
  274. if (hStopEvent != NULL) CloseHandle(hStopEvent);
  275. return;
  276. }
  277. BOOL IsSignaledToStop(const HANDLE hStopEvent, DWORD dwMilliSeconds)
  278. {
  279. DWORD dwRetVal;
  280. dwRetVal = WaitForSingleObject( hStopEvent, dwMilliSeconds );
  281. if ( dwRetVal == WAIT_FAILED ) {
  282. GetError(szError);
  283. LogFatalEvent(_T("IsSignaledToStop->WaitForSingleObject: %s"), szError);
  284. AddServiceLog(_T("Error: IsSignaledToStop->WaitForSingleObject: %s\r\n"), szError);
  285. // thread is supposed to stop now since there is a fatal error
  286. return TRUE;
  287. }
  288. if ( dwRetVal == WAIT_OBJECT_0 ) {
  289. LogEvent(_T("Worker Thread received Stop Event."));
  290. AddServiceLog(_T("Worker Thread received Stop Event.\r\n"));
  291. // thread is supposed to stop now since there is a stop event occured
  292. return TRUE;
  293. }
  294. // thread is not yet signaled to stop
  295. return FALSE;
  296. }
  297. // this procedure loads the values from INI file
  298. BOOL LoadINI() {
  299. DWORD dwRetVal;
  300. //
  301. // prepare INI file path
  302. //
  303. _TCHAR szCurrentDirectory[MAX_PATH];
  304. dwRetVal = GetCurrentDirectory( sizeof(szCurrentDirectory) / sizeof(_TCHAR),
  305. (LPTSTR) szCurrentDirectory);
  306. if ( dwRetVal == 0 ) {
  307. LogFatalEvent(_T("LoadINI->GetCurrentDirectory: %s"), szError);
  308. AddServiceLog(_T("Error: LoadINI->GetCurrentDirectory: %s\r\n"), szError);
  309. // return FALSE indicating some error has occurred
  310. return FALSE;
  311. }
  312. _TCHAR szINIFilePath[MAX_PATH];
  313. _stprintf(szINIFilePath, _T("%s\\%s"), szCurrentDirectory, _T(cszkdMonINIFile));
  314. // check if the kdMon INI file is there or not
  315. HANDLE hINIFile;
  316. WIN32_FIND_DATA w32FindData = {0};
  317. // try to get the handle to the file
  318. hINIFile = FindFirstFile( (LPCTSTR) szINIFilePath,
  319. &w32FindData);
  320. // if file is not there then the handle is invalid
  321. if(hINIFile == INVALID_HANDLE_VALUE){
  322. LogFatalEvent(_T("There is no kdMon INI file : %s"), szINIFilePath);
  323. AddServiceLog(_T("Error: There is no kdMon INI file : %s \r\n"), szINIFilePath);
  324. return FALSE;
  325. }
  326. else{
  327. FindClose(hINIFile);
  328. }
  329. BOOL bRetVal;
  330. bRetVal = kdMonINI.LoadValues(szINIFilePath);
  331. if ( bRetVal == FALSE ) return bRetVal;
  332. //
  333. // check if values are getting in properly from INI file
  334. //
  335. AddServiceLog(_T("\r\n============== I N I V A L U E S ==============\r\n"));
  336. AddServiceLog(_T("szToMailID : %s \r\n"), kdMonINI.szToMailID);
  337. AddServiceLog(_T("szFromMailID : %s \r\n"), kdMonINI.szFromMailID);
  338. AddServiceLog(_T("dwRepeatTime : %ld \r\n"), kdMonINI.dwRepeatTime);
  339. AddServiceLog(_T("szDebuggerLogFile : %s \r\n"), kdMonINI.szDebuggerLogFile);
  340. AddServiceLog(_T("szDebuggerLogArchiveDir : %s \r\n"), kdMonINI.szDebuggerLogArchiveDir);
  341. AddServiceLog(_T("dwDebuggerThreshold : %ld \r\n"), kdMonINI.dwDebuggerThreshold);
  342. AddServiceLog(_T("szServers : %s \r\n"), kdMonINI.szServers);
  343. AddServiceLog(_T("dwServerCount : %ld \r\n"), kdMonINI.dwServerCount);
  344. for ( UINT i = 0; i < kdMonINI.dwServerCount; i++ ) {
  345. AddServiceLog(_T("kdMonINI.ppszServerNameArray[%ld] : %s \r\n"), i, kdMonINI.ppszServerNameArray[i]);
  346. }
  347. AddServiceLog(_T("\r\n===================================================\r\n"));
  348. // successfully loaded INI file
  349. return TRUE;
  350. }
  351. // each server name in ppszNames, get the count and corresponding timestamp
  352. // store the count in the pulCounts array
  353. // store the timestamp in the pulTimeStamps array
  354. BOOL ReadRegValues(_TCHAR **ppszNames, DWORD dwTotalNames, ULONG *pulCounts, ULONG *pulTimeStamps)
  355. {
  356. // open HKEY_LOCAL_MACHINE\Software\Microsoft\kdMon registry key
  357. CRegKey keyServerName;
  358. LONG lRes;
  359. _TCHAR szKeyName[MAX_PATH];
  360. _tcscpy(szKeyName, _T("Software\\Microsoft\\"));
  361. _tcscat(szKeyName, szServiceName);
  362. lRes = keyServerName.Create(HKEY_LOCAL_MACHINE, szKeyName);
  363. if ( lRes != ERROR_SUCCESS ) {
  364. AddServiceLog(_T("Error: ReadRegValues->keyServerName.Create: Unable to open the key\r\n"));
  365. LogFatalEvent(_T("ReadRegValues->keyServerName.Create: Unable to open the key"));
  366. return FALSE;
  367. }
  368. // for each server name, get the previous count and timestamp value from registry
  369. for (DWORD i = 0; i < dwTotalNames; i++){
  370. _TCHAR szValue[MAX_PATH];
  371. DWORD dwBufferSize;
  372. dwBufferSize = MAX_PATH;
  373. lRes = keyServerName.QueryValue(szValue, ppszNames[i], &dwBufferSize);
  374. if ( lRes != ERROR_SUCCESS ) {
  375. // means there is no such value
  376. AddServiceLog(_T("ReadRegValues->keyServerName.QueryValue: Unable to query value %s\r\n"), ppszNames[i]);
  377. LogEvent(_T("ReadRegValues->keyServerName.QueryValue: Unable to query value %s"), ppszNames[i]);
  378. // There was no entry for server name in registry
  379. // set the count to -1
  380. pulCounts[i] = -1;
  381. // set timestamp to -1
  382. pulTimeStamps[i] = -1;
  383. // go on with the next server name
  384. continue;
  385. }
  386. // the value got is of the form <count>|<datetime>
  387. // # strtok returns pointer to the next token found in szValue
  388. // # while the pointer is returned, the '|' is replaced by '\0'
  389. // # so if u print strToken then it will print the characters till the null
  390. // # character
  391. // get the first token which is the previous count
  392. _TCHAR* pszToken;
  393. pszToken = NULL;
  394. pszToken = _tcstok(szValue, _T("|"));
  395. if(pszToken == NULL){
  396. AddServiceLog(_T("Error: ReadRegValues: Wrong value retrieved for %s\r\n"), ppszNames[i]);
  397. LogEvent(_T("ReadRegValues: Wrong value retrieved for %s"), ppszNames[i]);
  398. // Previous count was an invalid value
  399. // set the count to -1
  400. pulCounts[i] = -1;
  401. // set timestamp to -1
  402. pulTimeStamps[i] = -1;
  403. // go on with the next server name
  404. continue;
  405. }
  406. // set the count
  407. pulCounts[i] = _ttoi(pszToken);
  408. // get the second token which is the timestamp of the count
  409. pszToken = _tcstok(NULL, _T("|"));
  410. if(pszToken == NULL){
  411. AddServiceLog(_T("Error: ReadRegValues: No timestamp found for %s\r\n"), ppszNames[i]);
  412. LogEvent(_T("ReadRegValues: No timestamp found for %s"), ppszNames[i]);
  413. // no timestamp found
  414. // set timestamp to -1
  415. pulTimeStamps[i] = -1;
  416. // dont do timestamp validation, go on with the next server name
  417. continue;
  418. }
  419. // set the timestamp
  420. pulTimeStamps[i] = _ttol(pszToken);
  421. }
  422. // for (i = 0; i < dwTotalNames; i++){
  423. // AddServiceLog(_T("%s Value : %ld %ld\r\n"), ppszNames[i], pulCounts[i], pulTimeStamps[i]);
  424. // }
  425. return TRUE;
  426. }
  427. // write values in the pulCounts to registry. Timestamp is current timestamp
  428. BOOL WriteRegValues(_TCHAR **ppszNames, DWORD dwTotalNames, ULONG *pulCounts)
  429. {
  430. // open HKEY_LOCAL_MACHINE\Software\Microsoft\kdMon registry key
  431. CRegKey keyServerName;
  432. LONG lRes;
  433. _TCHAR szKeyName[MAX_PATH];
  434. _tcscpy(szKeyName, _T("Software\\Microsoft\\"));
  435. _tcscat(szKeyName, szServiceName);
  436. lRes = keyServerName.Create(HKEY_LOCAL_MACHINE, szKeyName);
  437. if ( lRes != ERROR_SUCCESS ) {
  438. AddServiceLog(_T("Error: ReadRegValues->keyServerName.Create: Unable to open the key\r\n"));
  439. LogFatalEvent(_T("ReadRegValues->keyServerName.Create: Unable to open the key"));
  440. return FALSE;
  441. }
  442. // for each server name, write the current count and timestamp value in registry
  443. for (DWORD i = 0; i < dwTotalNames; i++){
  444. // prepare the value to write
  445. _TCHAR szValue[MAX_PATH];
  446. // get integer count in a string
  447. _itot(pulCounts[i], szValue, 10);
  448. // put delemiter
  449. _tcscat(szValue, _T("|"));
  450. // prepare the timestamp
  451. // get the current system time
  452. // ulTimeStamp is like 200112171558
  453. ULONG ulTimeStamp;
  454. ulTimeStamp = GetCurrentTimeStamp();
  455. _TCHAR szTimeStamp[MAX_PATH];
  456. _ltot(ulTimeStamp, szTimeStamp, 10);
  457. // prepare final KeyValue
  458. _tcscat(szValue, szTimeStamp);
  459. lRes = keyServerName.SetValue(szValue, ppszNames[i]);
  460. if ( lRes != ERROR_SUCCESS ) {
  461. // means there is no value
  462. AddServiceLog(_T("Error: WriteRegValues->keyServerName.SetValue: Unable to set value %s\r\n"), ppszNames[i]);
  463. LogFatalEvent(_T("WriteRegValues->keyServerName.SetValue: Unable to set value %s"), ppszNames[i]);
  464. return FALSE;
  465. }
  466. }
  467. return TRUE;
  468. }
  469. ULONG ScanLogFile(_TCHAR *pszFileName)
  470. {
  471. ULONG ulRet = -1;
  472. HANDLE hFile;
  473. hFile = CreateFile( pszFileName,
  474. GENERIC_READ,
  475. 0, // No sharing of file
  476. NULL, // No security
  477. OPEN_EXISTING, // Open if exist
  478. FILE_ATTRIBUTE_NORMAL, // Normal file
  479. NULL); // No attr. template
  480. if (hFile == INVALID_HANDLE_VALUE)
  481. {
  482. // DWORD to get an error
  483. DWORD dwError;
  484. dwError = GetLastError();
  485. GetError(szError);
  486. AddServiceLog(_T("Error: ScanLogFile->CreateFile(%s): %s"), pszFileName, szError);
  487. LogEvent(_T("ScanLogFile->CreateFile(%s): %s"), pszFileName, szError);
  488. // ERROR_PATH_NOT_FOUND is Win32 Error Code
  489. // E_PATH_NOT_FOUND is locally defined code
  490. if ( dwError == ERROR_PATH_NOT_FOUND ) {
  491. return (ULONG)E_PATH_NOT_FOUND;
  492. }
  493. if ( dwError == ERROR_FILE_NOT_FOUND ) {
  494. return (ULONG)E_FILE_NOT_FOUND;
  495. }
  496. return (ULONG)E_OTHER_FILE_ERROR;
  497. }
  498. DWORD dwPos;
  499. // Reach the file start
  500. dwPos = SetFilePointer( hFile,
  501. 0, // Low 32 bits of distance to move
  502. NULL, // High 32 bits of distance to move
  503. FILE_BEGIN); // Starting point
  504. // If High Word is NULL, error meas dwPos = INVALID_SET_FILE_POINTER
  505. if(dwPos == INVALID_SET_FILE_POINTER){
  506. GetError(szError);
  507. AddServiceLog(_T("Error: ScanLogFile->SetFilePointer: %s\r\n"), szError);
  508. LogFatalEvent(_T("ScanLogFile->SetFilePointer: %s"), szError);
  509. goto endScanLogFile;
  510. }
  511. // to get status of the read operation
  512. // If the function succeeds and the number of bytes read is zero,
  513. // the file pointer was beyond the current end of the file
  514. DWORD dwBytesRead;
  515. // buffer to read from file
  516. // **** THIS NEEDS TO BE char* since the file is in ASCII and not UNICODE
  517. char szBuffer[MAX_PATH * 2];
  518. // count for Number of lines
  519. ULONG ulNumberOfLines;
  520. ulNumberOfLines = 0;
  521. // loop till the fileend is reached
  522. while(1) {
  523. BOOL bRet;
  524. bRet = ReadFile( hFile,
  525. szBuffer,
  526. sizeof(szBuffer) * sizeof(char), // number of BYTES to read
  527. &dwBytesRead, // BYTES read
  528. NULL); // OVERLAPPED structure
  529. // return if read failed
  530. if ( bRet == FALSE ) {
  531. GetError(szError);
  532. AddServiceLog(_T("Error: ScanLogFile->ReadFile(%s): %s\r\n"), pszFileName, szError);
  533. LogFatalEvent(_T("ScanLogFile->ReadFile(%s): %s"), pszFileName, szError);
  534. goto endScanLogFile;
  535. }
  536. // means file end is reached
  537. if ( dwBytesRead == 0 ) {
  538. ulRet = ulNumberOfLines;
  539. break;
  540. }
  541. // **** THIS NEEDS TO BE char* since the file is in ASCII and not UNICODE
  542. char *pszBuffPtr;
  543. pszBuffPtr = szBuffer;
  544. // to denote that a line has started
  545. BOOL bLineStarted;
  546. bLineStarted = FALSE;
  547. // read buffer one by one till dwBytesRead bytes are read
  548. for ( ; dwBytesRead > 0; dwBytesRead-- ) {
  549. // **** _T('\n') not needed since the file is in ASCII and not UNICODE
  550. // if endof line is encountered and line has started then increase line number
  551. if ( (*pszBuffPtr == '\n') && (bLineStarted == TRUE) ) {
  552. ulNumberOfLines++;
  553. bLineStarted = FALSE;
  554. } else if ( (*pszBuffPtr != '\n') &&
  555. (*pszBuffPtr != '\t') &&
  556. (*pszBuffPtr != '\r') &&
  557. (*pszBuffPtr != ' ') ) {
  558. // if a non widespace character is encountered then line has started
  559. bLineStarted = TRUE;
  560. }
  561. // goto next character
  562. pszBuffPtr++;
  563. }
  564. }
  565. endScanLogFile :
  566. CloseHandle(hFile);
  567. return ulRet;
  568. }
  569. ULONG GetCurrentTimeStamp() {
  570. // prepare the timestamp
  571. // get the current system time
  572. SYSTEMTIME UniversalTime;
  573. GetSystemTime(&UniversalTime);
  574. SYSTEMTIME systime;
  575. BOOL bRet;
  576. bRet = SystemTimeToTzSpecificLocalTime ( NULL, // current local settings
  577. &UniversalTime,
  578. &systime);
  579. if ( bRet == 0 ) {
  580. GetError(szError);
  581. AddServiceLog(_T("Error: GetCurrentTimeStamp->SystemTimeToTzSpecificLocalTime: %s \r\n"),
  582. szError);
  583. LogFatalEvent(_T("GetCurrentTimeStamp->SystemTimeToTzSpecificLocalTime: %s"),
  584. szError);
  585. return (ULONG) -1;
  586. }
  587. // ulTimeStamp is like 200112171558
  588. ULONG ulTimeStamp;
  589. ulTimeStamp = 0;
  590. ulTimeStamp += systime.wMinute;
  591. ulTimeStamp += systime.wHour * 100;
  592. ulTimeStamp += systime.wDay * 10000;
  593. ulTimeStamp += systime.wMonth * 1000000;
  594. ulTimeStamp += (systime.wYear - 2000) * 100000000;
  595. return ulTimeStamp;
  596. }
  597. // to add a specific time to a timestamp
  598. ULONG AddTime(ULONG ulTimeStamp, ULONG ulMinutes){
  599. // we have kdMonINI.dwRepeatTime in minutes (say 78)
  600. // take out hours and minutes (1 Hr 18 Min)
  601. // between 0112181608 and 0112181726 there is difference of 1 Hr 18 Min
  602. // but decimal difference is 118
  603. // between 0112181650 and 0112181808 there is difference of 1 Hr 18 Min
  604. // but decimal difference is 158
  605. // so we have some calculation here
  606. // what we will do is add the kdMonINI.dwRepeatTime to OldTS
  607. ULONG ulTmpHr, ulTmpMin;
  608. ulTmpHr = (ULONG) (ulMinutes / 60);
  609. ulTmpMin = (ULONG) (ulMinutes % 60);
  610. ULONG ulPrevYr, ulPrevMon, ulPrevDate, ulPrevHr, ulPrevMin;
  611. ulPrevMin = ulTimeStamp % 100;
  612. ulTimeStamp = ulTimeStamp / 100;
  613. ulPrevHr = ulTimeStamp % 100;
  614. ulTimeStamp = ulTimeStamp / 100;
  615. ulPrevDate = ulTimeStamp % 100;
  616. ulTimeStamp = ulTimeStamp / 100;
  617. ulPrevMon = ulTimeStamp % 100;
  618. ulTimeStamp = ulTimeStamp / 100;
  619. ulPrevYr = ulTimeStamp % 100;
  620. ULONG ulNewYr, ulNewMon, ulNewDate, ulNewHr, ulNewMin;
  621. ulNewYr = ulNewMon = ulNewDate = ulNewHr = ulNewMin = 0;
  622. ulNewMin = ulPrevMin + ulTmpMin;
  623. ulNewHr = ulPrevHr + ulTmpHr;
  624. ulNewDate = ulPrevDate;
  625. ulNewMon = ulPrevMon;
  626. ulNewYr = ulPrevYr;
  627. if ( ulNewMin >= 60 ) {
  628. ulNewHr++;
  629. ulNewMin = ulNewMin - 60;
  630. }
  631. if ( ulNewHr >= 24 ) {
  632. ulNewDate++;
  633. ulNewHr = ulNewHr - 24;
  634. }
  635. if ( ulPrevMon == 1 || ulPrevMon == 3 || ulPrevMon == 5 || ulPrevMon == 7 ||
  636. ulPrevMon == 8 || ulPrevMon == 10 || ulPrevMon == 12 ) {
  637. if ( ulNewDate >= 32 ) {
  638. ulNewMon++;
  639. ulNewDate = 1;
  640. }
  641. } else if ( ulPrevMon == 4 || ulPrevMon == 6 || ulPrevMon == 9 || ulPrevMon == 11 ) {
  642. if ( ulNewDate >= 31 ) {
  643. ulNewMon++;
  644. ulNewDate = 1;
  645. }
  646. } else if ( ulPrevMon == 2 && (ulPrevYr % 4) == 0 ) {
  647. // leap year
  648. if ( ulNewDate >= 30 ) {
  649. ulNewMon++;
  650. ulNewDate = 1;
  651. }
  652. } else if ( ulPrevMon == 2 && (ulPrevYr % 4) != 0 ) {
  653. // not a leap year
  654. if ( ulNewDate >= 29 ) {
  655. ulNewMon++;
  656. ulNewDate = 1;
  657. }
  658. }
  659. if ( ulNewMon >= 13 ) {
  660. ulNewYr++;
  661. ulNewMon = 1;
  662. }
  663. ULONG ulModifiedTS;
  664. ulModifiedTS = ulNewYr;
  665. ulModifiedTS = ulModifiedTS * 100 + ulNewMon;
  666. ulModifiedTS = ulModifiedTS * 100 + ulNewDate;
  667. ulModifiedTS = ulModifiedTS * 100 + ulNewHr;
  668. ulModifiedTS = ulModifiedTS * 100 + ulNewMin;
  669. return ulModifiedTS;
  670. }