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.

1009 lines
33 KiB

  1. /****************************************************************************
  2. PROGRAM: mttf.c
  3. AUTHOR: Lars Opstad (LarsOp) 3/16/93
  4. PURPOSE: NT Mean-time-to-failure reporting tool.
  5. FUNCTIONS:
  6. WinMain() - check for local file, read ini file and display dialogs
  7. SignonDlgProc() - processes messages for signon dialog
  8. EventDlgProc() - processes messages for event (other problem) dialog
  9. COMMENTS:
  10. This program displays 2 dialog boxes to prompt the user for
  11. what type of problem occurred.
  12. Every polling period, the time in the mttf data file is updated
  13. (as either busy or idle based on percent of cpu usage). If a machine
  14. is idle for more than 4 hrs, the "gone" field is increased by the time
  15. gone. Whenever the program starts, the user is prompted for why they
  16. rebooted or logged off. Other problems should be logged as they happen.
  17. If any machine can not access the server file for some reason, the
  18. data is stored in c:\mttf.dat until the next time the server file is
  19. opened. At such a time, the server file is updated and the local file
  20. is deleted.
  21. ****************************************************************************/
  22. #include <nt.h>
  23. #include <ntrtl.h>
  24. #include <nturtl.h>
  25. #include "mttf.h" /* specific to this program */
  26. //
  27. // For internal use, include header for NetMessageBufferSend and set up
  28. // alert name and unicode buffers for NetMessageBufferSend.
  29. //
  30. #ifndef CUSTOMER
  31. #include <lm.h>
  32. #define AlertName "DavidAn"
  33. WCHAR UniAlertName[16];
  34. WCHAR UnicodeBuffer[1024];
  35. #endif
  36. #define IniFileName "Mttf.ini"
  37. #define LocalFileName "c:\\mttf.dat"
  38. #define DEFAULT_IDLE_LIMIT 10
  39. #define DEFAULT_POLLING_PERIOD 30
  40. #define CONSEC_IDLE_LIMIT 4*60
  41. #define POLLING_PRODUCT 60000
  42. #define HUNDREDNS_TO_MS 10000
  43. #define MAX_RETRIES 10
  44. HANDLE hInst; // current instance
  45. HWND hCopying; // handle to copying dialog box
  46. DWORD PollingPeriod = DEFAULT_POLLING_PERIOD;
  47. DWORD IdlePercentage = DEFAULT_IDLE_LIMIT;
  48. char ResultsFile[MAX_DIR], NameFile[MAX_DIR];
  49. BOOL Enabled=TRUE;
  50. BOOL LocalExists=FALSE;
  51. DWORD Version;
  52. DWORD ConsecIdle=0;
  53. SYSTEM_PERFORMANCE_INFORMATION PerfInfo;
  54. SYSTEM_PERFORMANCE_INFORMATION PreviousPerfInfo;
  55. /****************************************************************************
  56. FUNCTION: WinMain(HANDLE, HANDLE, LPSTR, int)
  57. PURPOSE: Check for local file, read ini file and display dialogs.
  58. COMMENTS:
  59. Check to see if local data file exists and set flag appropriately.
  60. Initialize the performance information.
  61. Read the IniFile.
  62. Display signon dialog.
  63. Display event dialog (minimized).
  64. ****************************************************************************/
  65. int WINAPI
  66. WinMain(
  67. HINSTANCE hInstance,
  68. HINSTANCE hPrevInstance,
  69. LPSTR lpCmdLine,
  70. int nCmdShow
  71. )
  72. {
  73. OFSTRUCT ofstruct;
  74. hInst = hInstance;
  75. //
  76. // Check for local file (if exists, write it to server at next opportunity)
  77. //
  78. LocalExists=(HFILE_ERROR!=OpenFile(LocalFileName, &ofstruct, OF_EXIST));
  79. //
  80. // Initialize performance information
  81. //
  82. Version=GetVersion();
  83. NtQuerySystemInformation(
  84. SystemPerformanceInformation,
  85. &PerfInfo,
  86. sizeof(PerfInfo),
  87. NULL
  88. );
  89. //
  90. // Read ini file
  91. //
  92. ReadIniFile();
  93. //
  94. // For Internal use, convert alert name to unicode for NetMessageBufferSend.
  95. //
  96. #ifndef CUSTOMER
  97. MultiByteToWideChar(CP_ACP, MB_COMPOSITE, AlertName, sizeof(UniAlertName)/2, UniAlertName, sizeof(UniAlertName)/2);
  98. #endif
  99. //
  100. // Display signon dlg
  101. //
  102. DialogBox(hInstance, (LPCSTR)IDD_SIGNON, NULL, SignonDlgProc);
  103. //
  104. // Display event dialog
  105. //
  106. DialogBox(hInstance, (LPCSTR) IDD_EVENT, NULL, EventDlgProc);
  107. return(0);
  108. } // WinMain()
  109. /*****************************************************************************
  110. FUNCTION: ReadIniFile ( )
  111. PURPOSE: Read values from INI file using GetPrivateProfileString/Int
  112. COMMENTS:
  113. This reads entries from the mttf.ini file (in windows nt directory)
  114. for NameFile, ResultsFile, PollingPeriod and IdlePercent. Any non-
  115. existent entry returns a default.
  116. *****************************************************************************/
  117. VOID
  118. ReadIniFile (
  119. )
  120. {
  121. GetPrivateProfileString("Mttf",
  122. "NameFile",
  123. "",
  124. NameFile,
  125. MAX_DIR,
  126. IniFileName);
  127. GetPrivateProfileString("Mttf",
  128. "ResultsFile",
  129. "",
  130. ResultsFile,
  131. MAX_DIR,
  132. IniFileName);
  133. PollingPeriod = GetPrivateProfileInt("Mttf",
  134. "PollingPeriod",
  135. DEFAULT_POLLING_PERIOD,
  136. IniFileName);
  137. IdlePercentage = GetPrivateProfileInt("Mttf",
  138. "IdlePercent",
  139. DEFAULT_IDLE_LIMIT,
  140. IniFileName);
  141. }
  142. /****************************************************************************
  143. FUNCTION: DWORD CpuUsage ( )
  144. PURPOSE: Returns percentage of cpu usage for last polling period.
  145. COMMENTS:
  146. Computes time spent in the idle thread.
  147. Divides this number by the number of 100nanoseconds in a millisecond.
  148. (This division is to prevent over-flows in later computations.)
  149. Returns 100-PercentIdle to get percent busy.
  150. ****************************************************************************/
  151. DWORD
  152. CpuUsage(
  153. )
  154. {
  155. LARGE_INTEGER EndTime, BeginTime, ElapsedTime;
  156. DWORD PercentIdle, Remainder;
  157. PreviousPerfInfo = PerfInfo;
  158. //
  159. // Get current perf info
  160. //
  161. NtQuerySystemInformation(
  162. SystemPerformanceInformation,
  163. &PerfInfo,
  164. sizeof(PerfInfo),
  165. NULL
  166. );
  167. //
  168. // Get times from PerfInfo and PreviousPerfInfo
  169. //
  170. EndTime = *(PLARGE_INTEGER)&PerfInfo.IdleProcessTime;
  171. BeginTime = *(PLARGE_INTEGER)&PreviousPerfInfo.IdleProcessTime;
  172. //
  173. // Convert from 100 NS to Milliseconds
  174. //
  175. EndTime = RtlExtendedLargeIntegerDivide(EndTime, HUNDREDNS_TO_MS, &Remainder);
  176. BeginTime = RtlExtendedLargeIntegerDivide(BeginTime, HUNDREDNS_TO_MS, &Remainder);
  177. //
  178. // Compute elapsed time and percent idle
  179. //
  180. ElapsedTime = RtlLargeIntegerSubtract(EndTime,BeginTime);
  181. PercentIdle = (ElapsedTime.LowPart) / ((POLLING_PRODUCT/100)*PollingPeriod);
  182. //
  183. // Sometimes it takes significantly longer than PollingPeriod
  184. // to make a round trip.
  185. //
  186. if ( PercentIdle > 100 ) {
  187. PercentIdle = 100;
  188. }
  189. //
  190. // return cpuusage (100-PercentIdle)
  191. //
  192. return 100-PercentIdle;
  193. }
  194. /****************************************************************************
  195. FUNCTION: IncrementStats (StatType)
  196. PURPOSE: Increments the specified stat and writes new data to mttf.dat.
  197. COMMENTS:
  198. Increment the specified stat. For MTTF_TIME, check if it is busy
  199. or idle by comparing the CpuUsage to IdlePercentage. If a machine
  200. is idle for 4 hrs consecutively, first time this is true set the
  201. IdleConsec stat to the total ConsecIdle value, otherwise set to
  202. polling period. (IdleConsec should never exceed Idle.)
  203. Open mttf.dat. If opening the server fails (10 times), open the
  204. local data file. If server opened and local file also exists,
  205. open local file also for transfer.
  206. Search through data file for matching build number, add all values
  207. and write new record. (Continue until local file is gone if
  208. transferring.)
  209. ****************************************************************************/
  210. VOID
  211. IncrementStats(
  212. StatType stattype
  213. )
  214. {
  215. HANDLE fhandle,localHandle;
  216. StatFileRecord newRec, curRec;
  217. DWORD numBytes;
  218. BOOL localToServer=FALSE;
  219. CHAR buffer[1024];
  220. int i;
  221. //
  222. // Initialize all values to zero
  223. //
  224. memset(&newRec, 0, sizeof(newRec));
  225. newRec.Version=Version;
  226. //
  227. // Increment the appropriate stat.
  228. //
  229. switch (stattype) {
  230. //
  231. // MTTF_TIME stat: Get cpu usage and set idle/busy and percent fields.
  232. //
  233. // If idle for more than CONSEC_IDLE_LIMIT, Set IdleConsec.
  234. // If difference is less than polling period (first time), set to total
  235. // ConsecIdle; otherwise, just PollingPeriod.
  236. //
  237. case MTTF_TIME:
  238. //
  239. // Has the CPU been "busy"?
  240. //
  241. if ((newRec.PercentTotal=CpuUsage()) > IdlePercentage) {
  242. //
  243. // Yes, set busy to polling period and clear ConsecIdle.
  244. //
  245. newRec.Busy = PollingPeriod;
  246. ConsecIdle=0;
  247. } else {
  248. //
  249. // No, not busy, increment consec idle by PollingPeriod.
  250. // (Set value of idle to polling period.)
  251. //
  252. // If ConsecIdle is greater than IDLE_LIMIT, set IdleConsec.
  253. // If first time, set IdleConsec to ConsecIdle, else PollingPer.
  254. //
  255. ConsecIdle+=(newRec.Idle = PollingPeriod);
  256. if (ConsecIdle>=CONSEC_IDLE_LIMIT) {
  257. if (ConsecIdle < CONSEC_IDLE_LIMIT + PollingPeriod) {
  258. newRec.IdleConsec=ConsecIdle;
  259. } else {
  260. newRec.IdleConsec=PollingPeriod;
  261. }
  262. }
  263. }
  264. //
  265. // Weight PercentTotal by number of minutes in polling period.
  266. //
  267. newRec.PercentTotal *= PollingPeriod;
  268. break;
  269. //
  270. // MTTF_COLD: Set cold boot count to 1
  271. //
  272. case MTTF_COLD:
  273. newRec.Cold = 1;
  274. break;
  275. //
  276. // MTTF_WARM: Set warm boot count to 1
  277. //
  278. case MTTF_WARM:
  279. newRec.Warm = 1;
  280. break;
  281. //
  282. // MTTF_OTHER: Set other problem count to 1
  283. //
  284. case MTTF_OTHER:
  285. newRec.Other = 1;
  286. break;
  287. default:
  288. ;
  289. }
  290. //
  291. // If there is a ResultsFile name entered in the INI file,
  292. //
  293. if (ResultsFile[0]) {
  294. //
  295. // Try to open the server file (MAX_RETRIES times).
  296. //
  297. for (i=0;i<MAX_RETRIES;i++) {
  298. if (INVALID_HANDLE_VALUE!=(fhandle = CreateFile(ResultsFile,
  299. GENERIC_READ|GENERIC_WRITE,
  300. FILE_SHARE_READ,
  301. NULL,
  302. OPEN_ALWAYS,
  303. FILE_ATTRIBUTE_NORMAL,
  304. NULL))) {
  305. break;
  306. }
  307. Sleep(500); // wait a half second if it failed.
  308. }
  309. } else {
  310. //
  311. // If ResultsFile name is blank, set i to MAX_RETRIES to force open
  312. // of local data file.
  313. //
  314. i=MAX_RETRIES;
  315. }
  316. //
  317. // If i is MAX_RETRIES, server file failed to open, so open local file.
  318. //
  319. if (i==MAX_RETRIES) {
  320. if (INVALID_HANDLE_VALUE==(fhandle = CreateFile(LocalFileName,
  321. GENERIC_READ|GENERIC_WRITE,
  322. FILE_SHARE_READ,
  323. NULL,
  324. OPEN_ALWAYS,
  325. FILE_ATTRIBUTE_NORMAL,
  326. NULL))) {
  327. return;
  328. }
  329. LocalExists=TRUE; // Set flag to indicate local file exists
  330. } else {
  331. //
  332. // If the server file opened and the local file exists, open local for
  333. // transfer (indicated by localToServer).
  334. //
  335. if (LocalExists) {
  336. localToServer=TRUE;
  337. if (INVALID_HANDLE_VALUE==(localHandle = CreateFile(LocalFileName,
  338. GENERIC_READ,
  339. FILE_SHARE_READ,
  340. NULL,
  341. OPEN_ALWAYS,
  342. FILE_ATTRIBUTE_NORMAL,
  343. NULL))) {
  344. localToServer=FALSE;
  345. return;
  346. }
  347. }
  348. }
  349. //
  350. // Outer loop is to continue searching in case of transferring local
  351. // file to server.
  352. //
  353. do {
  354. //
  355. // Loop through data file until versions match or end of file found.
  356. //
  357. while (1) {
  358. //
  359. // If ReadFile fails, close files (and send message if internal).
  360. //
  361. if (!ReadFile(fhandle, &curRec, sizeof(curRec), &numBytes, NULL)) {
  362. CloseHandle(fhandle);
  363. if (localToServer) {
  364. CloseHandle(localHandle);
  365. DeleteFile(LocalFileName);
  366. LocalExists=FALSE;
  367. }
  368. #ifndef CUSTOMER
  369. sprintf(buffer,
  370. "Mttf error reading %s (error code %ld).\nPlease rename file.",
  371. //
  372. // If the local file exists and not transferring,
  373. // local file is open; otherwise, server file.
  374. //
  375. (LocalExists & !localToServer ? LocalFileName : ResultsFile),
  376. GetLastError());
  377. MultiByteToWideChar(CP_ACP, MB_COMPOSITE, buffer, sizeof(buffer), UnicodeBuffer, sizeof(UnicodeBuffer)/2);
  378. NetMessageBufferSend(NULL, UniAlertName, NULL, (LPBYTE)UnicodeBuffer, 2 * strlen(buffer));
  379. #endif
  380. return;
  381. }
  382. //
  383. // If numBytes is 0, end of file reached; break out of while to
  384. // add a new record.
  385. //
  386. if (numBytes==0) {
  387. break;
  388. }
  389. //
  390. // If numBytes is not record size, report an error and close files.
  391. //
  392. // Reporting is a local message box for customers and a popup internally.
  393. //
  394. if (numBytes != sizeof(curRec)) {
  395. #ifdef CUSTOMER
  396. sprintf(buffer,
  397. "Error reading %s (error code %ld).\n\nPlease have "
  398. "your administrator rename the file and contact "
  399. "Microsoft regarding the Mttf (mean time to failure) "
  400. "reporting tool.",
  401. //
  402. // If the local file exists and not transferring,
  403. // local file is open; otherwise, server file.
  404. //
  405. (LocalExists & !localToServer ? LocalFileName : ResultsFile),
  406. GetLastError());
  407. MessageBox(NULL, buffer, "Read File Error", MB_OK|MB_ICONHAND);
  408. #else
  409. sprintf(buffer,
  410. "Mttf error reading %s (error code %ld).\n(Byte count wrong.) Please rename file.",
  411. //
  412. // If the local file exists and not transferring,
  413. // local file is open; otherwise, server file.
  414. //
  415. (LocalExists & !localToServer ? LocalFileName : ResultsFile),
  416. GetLastError());
  417. MultiByteToWideChar(CP_ACP, MB_COMPOSITE, buffer, sizeof(buffer), UnicodeBuffer, sizeof(UnicodeBuffer)/2);
  418. NetMessageBufferSend(NULL, UniAlertName, NULL, (LPBYTE)UnicodeBuffer, 2 * strlen(buffer));
  419. #endif
  420. CloseHandle(fhandle);
  421. if (localToServer) {
  422. CloseHandle(localHandle);
  423. DeleteFile(LocalFileName);
  424. LocalExists=FALSE;
  425. }
  426. return;
  427. }
  428. //
  429. // If Versions match, increment all other stats, rewind file and
  430. // break out of while to do write.
  431. //
  432. if (curRec.Version==newRec.Version) {
  433. newRec.Idle += curRec.Idle;
  434. newRec.IdleConsec += curRec.IdleConsec;
  435. newRec.Busy += curRec.Busy;
  436. newRec.PercentTotal += curRec.PercentTotal;
  437. newRec.Warm += curRec.Warm;
  438. newRec.Cold += curRec.Cold;
  439. newRec.Other += curRec.Other;
  440. SetFilePointer(fhandle, -(LONG)sizeof(curRec), NULL, FILE_CURRENT);
  441. break;
  442. }
  443. }
  444. //
  445. // Write newRec at current location (end of file for new record)
  446. //
  447. WriteFile(fhandle, &newRec, sizeof(newRec), &numBytes, NULL);
  448. //
  449. // if transferring from local to server, read the next record from
  450. // the local file, rewind data file and loop again until end of
  451. // (local) file.
  452. //
  453. if (localToServer) {
  454. //
  455. // If ReadFile fails, close files (and send popup internally)
  456. //
  457. if (!ReadFile(localHandle, &newRec, sizeof(curRec), &numBytes, NULL)) {
  458. CloseHandle(fhandle);
  459. CloseHandle(localHandle);
  460. LocalExists=FALSE;
  461. DeleteFile(LocalFileName);
  462. #ifndef CUSTOMER
  463. sprintf(buffer,
  464. "Mttf error reading %s (error code %ld).\nLocal file access failed...data will be lost.",
  465. LocalFileName,
  466. GetLastError());
  467. MultiByteToWideChar(CP_ACP, MB_COMPOSITE, buffer, sizeof(buffer), UnicodeBuffer, sizeof(UnicodeBuffer)/2);
  468. NetMessageBufferSend(NULL, UniAlertName, NULL, (LPBYTE)UnicodeBuffer, 2 * strlen(buffer));
  469. #endif
  470. return;
  471. }
  472. if (numBytes==0) {
  473. //
  474. // Done transferring, close both files, delete local and set
  475. // LocalExists and localToServer to FALSE.
  476. //
  477. CloseHandle(localHandle);
  478. DeleteFile(LocalFileName);
  479. LocalExists=localToServer=FALSE;
  480. CloseHandle(fhandle);
  481. return;
  482. }
  483. //
  484. // if numBytes is not record size, close files (and send popup internally)
  485. //
  486. if (numBytes != sizeof(curRec)) {
  487. #ifndef CUSTOMER
  488. sprintf(buffer,
  489. "Mttf error reading %s (error code %ld).\n(Byte count wrong.) Data will be lost.",
  490. LocalFileName,
  491. GetLastError());
  492. MultiByteToWideChar(CP_ACP, MB_COMPOSITE, buffer, sizeof(buffer), UnicodeBuffer, sizeof(UnicodeBuffer)/2);
  493. NetMessageBufferSend(NULL, UniAlertName, NULL, (LPBYTE)UnicodeBuffer, 2 * strlen(buffer));
  494. #endif
  495. CloseHandle(fhandle);
  496. CloseHandle(localHandle);
  497. DeleteFile(LocalFileName);
  498. LocalExists=FALSE;
  499. return;
  500. }
  501. SetFilePointer(fhandle,0, NULL, FILE_BEGIN);
  502. } else {
  503. //
  504. // If not transferring, close file and exit
  505. //
  506. CloseHandle(fhandle);
  507. return;
  508. }
  509. } while (localToServer);
  510. }
  511. /****************************************************************************
  512. FUNCTION: CheckAndAddName ( )
  513. PURPOSE: Checks name file for machine name and build number at startup.
  514. COMMENTS:
  515. Writes various system info to name file if the machine doesn't have
  516. an entry for this build. This was an add-on to collect info on how
  517. many machines were actually running NT.
  518. ****************************************************************************/
  519. VOID
  520. CheckAndAddName(
  521. )
  522. {
  523. NameFileRecord newRec, curRec;
  524. HANDLE fhandle;
  525. DWORD numBytes,i,ulLength=MAX_NAME;
  526. DWORD dwVersion;
  527. SYSTEMTIME sysTime;
  528. MEMORYSTATUS memstat;
  529. SYSTEM_INFO sysinfo;
  530. //
  531. // If the NameFile name is blank, exit
  532. //
  533. if (0==NameFile[0]) {
  534. return;
  535. }
  536. //
  537. // Set record to zero.
  538. //
  539. memset(&newRec, 0, sizeof(newRec));
  540. GetComputerName(newRec.MachineName, &ulLength);
  541. GetSystemInfo(&sysinfo); // Get system info
  542. switch(sysinfo.wProcessorArchitecture) {
  543. case PROCESSOR_ARCHITECTURE_INTEL:
  544. newRec.MachineType=X86_CPU;
  545. break;
  546. case PROCESSOR_ARCHITECTURE_MIPS:
  547. newRec.MachineType=MIP_CPU;
  548. break;
  549. case PROCESSOR_ARCHITECTURE_ALPHA:
  550. newRec.MachineType=AXP_CPU;
  551. break;
  552. case PROCESSOR_ARCHITECTURE_PPC:
  553. newRec.MachineType=PPC_CPU;
  554. break;
  555. default:
  556. newRec.MachineType=UNKNOWN_CPU;
  557. break;
  558. };
  559. dwVersion=GetVersion();
  560. sprintf(newRec.Build, "%3ld", dwVersion>>16);
  561. memstat.dwLength=sizeof(memstat);
  562. GlobalMemoryStatus(&memstat); // Get memory info
  563. sprintf(newRec.Mem, "%5ldMB",memstat.dwTotalPhys/(1024*1024));
  564. ulLength=MAX_NAME;
  565. GetUserName(newRec.UserName, &ulLength);
  566. GetLocalTime(&sysTime);
  567. sprintf(newRec.DateAndTime, "%2d/%2d/%4d %2d:%02ld",
  568. sysTime.wMonth, sysTime.wDay, sysTime.wYear,
  569. sysTime.wHour, sysTime.wMinute);
  570. newRec.Tab1=newRec.Tab2=newRec.Tab3=newRec.Tab4=newRec.Tab5=9;
  571. newRec.CRLF[0]=13;
  572. newRec.CRLF[1]=10;
  573. //
  574. // Try to open NameFile, for shared read access.
  575. //
  576. if (INVALID_HANDLE_VALUE==(fhandle = CreateFile(NameFile,
  577. GENERIC_READ,
  578. FILE_SHARE_READ,
  579. NULL,
  580. OPEN_ALWAYS,
  581. FILE_ATTRIBUTE_NORMAL,
  582. NULL))) {
  583. return;
  584. }
  585. //
  586. // Read each record until a match or end-of-file is encountered.
  587. //
  588. while (ReadFile(fhandle, &curRec, sizeof(curRec), &numBytes, NULL)) {
  589. //
  590. // At end of file, break out and write new record.
  591. //
  592. if (numBytes==0) {
  593. break;
  594. }
  595. //
  596. // If there is a match, close the file and return.
  597. //
  598. if (0==strcmp(curRec.Build, newRec.Build) &&
  599. 0==strcmp(curRec.MachineName, newRec.MachineName)) {
  600. CloseHandle(fhandle);
  601. return;
  602. }
  603. }
  604. //
  605. // Close the name file and try to open it for ExclusiveWrite
  606. //
  607. CloseHandle(fhandle);
  608. for (i=0;i<MAX_RETRIES;i++) {
  609. if (INVALID_HANDLE_VALUE!=(fhandle = CreateFile(NameFile,
  610. GENERIC_READ|GENERIC_WRITE,
  611. FILE_SHARE_READ,
  612. NULL,
  613. OPEN_ALWAYS,
  614. FILE_ATTRIBUTE_NORMAL,
  615. NULL))) {
  616. break;
  617. }
  618. Sleep(500); // wait if open failed.
  619. }
  620. //
  621. // If open succeeded, go to the end of file and write newRec.
  622. //
  623. if (i<MAX_RETRIES) {
  624. SetFilePointer(fhandle, 0, &numBytes, FILE_END);
  625. WriteFile(fhandle, &newRec, sizeof(newRec), &numBytes, NULL);
  626. CloseHandle(fhandle);
  627. }
  628. }
  629. /****************************************************************************
  630. FUNCTION: SignonDlgProc(HWND, UINT, UINT, UINT)
  631. PURPOSE: Dialog procedure for signon dialog.
  632. COMMENTS: The signon dialog
  633. WM_INITDIALOG: Checks machine name in name file and sets focus.
  634. WM_COMMAND: Process the button press:
  635. IDOK: Get input values and check for validity.
  636. IDCANCEL: Kill the app.
  637. IDB_HELP: Descriptive message box
  638. ****************************************************************************/
  639. INT_PTR
  640. SignonDlgProc(
  641. HWND hDlg,
  642. UINT message,
  643. WPARAM wParam,
  644. LPARAM lParam
  645. )
  646. {
  647. switch (message)
  648. {
  649. case WM_INITDIALOG: // Checks machinename in namefile and sets focus
  650. CheckAndAddName();
  651. CheckRadioButton(hDlg, IDS_NORMAL, IDS_COLD, IDS_NORMAL);
  652. return (TRUE);
  653. case WM_COMMAND: // command: button pressed
  654. switch (wParam) // which button
  655. {
  656. //
  657. // OK: Update the appropriate stat if not "Normal Boot"
  658. //
  659. case IDOK:
  660. case IDCANCEL:
  661. if (IsDlgButtonChecked(hDlg, IDS_WARM)) {
  662. IncrementStats(MTTF_WARM);
  663. } else {
  664. if (IsDlgButtonChecked(hDlg, IDS_COLD)) {
  665. IncrementStats(MTTF_COLD);
  666. }
  667. }
  668. EndDialog(hDlg, TRUE);
  669. return (TRUE);
  670. //
  671. // HELP: Descriptive message box (.HLP file would be overkill)
  672. //
  673. case IDB_HELP:
  674. MessageBox( NULL,
  675. "Mttf tracks the amount of time your machine stays up, "
  676. "the number of cold and warm boots, and "
  677. "the number of other problems that occur on your machine. "
  678. "All this information is written to a server that is "
  679. "specified in mttf.ini (in your Windows NT directory).\n\n"
  680. "The app should be placed in your start-up group and "
  681. "you should respond accurately (if there was a problem) "
  682. "on startup. When you encounter other problems -- where "
  683. "the system did not require a reboot, but encountered "
  684. "anything you consider a problem -- double-click on the "
  685. "Mttf icon and press the Other Problem button.\n\n"
  686. "When you are running some test that is outside of the "
  687. "realm of normal usage (e.g. Stress), please disable Mttf "
  688. "by double-clicking the icon and pressing disable. When "
  689. "you are done with this test, please press the Enable "
  690. "button to continue reporting.",
  691. "Mean Time to Failure Help",
  692. MB_OK
  693. );
  694. return (TRUE);
  695. default:
  696. break;
  697. } // switch (wParam)
  698. break;
  699. default:
  700. break;
  701. } // switch (message)
  702. return (FALSE); // Didn't process a message
  703. } // SignonDlgProc()
  704. /****************************************************************************
  705. FUNCTION: EventDlgProc(HWND, UINT, UINT, UINT)
  706. PURPOSE: Processes timer and button events (disable and other problems).
  707. COMMENTS: Processes the following messages:
  708. WM_INITDIALOG: Minimize dialog and start timer
  709. WM_CLOSE...: End app
  710. WM_TIMER: Update Time stat (busy or idle)
  711. WM_COMMAND: Process the button press:
  712. IDOK: Log Other problem (and minimize).
  713. IDCANCEL: Minimize without action.
  714. IDE_DISABLE: Disable or enable mttf reporting.
  715. IDB_HELP: Descriptive message box.
  716. ****************************************************************************/
  717. INT_PTR
  718. EventDlgProc(
  719. HWND hDlg,
  720. UINT message,
  721. WPARAM wParam,
  722. LPARAM lParam
  723. )
  724. {
  725. switch (message)
  726. {
  727. case WM_INITDIALOG: // minimize and start timer
  728. SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR)LoadIcon(hInst,"mttf"));
  729. SendMessage(hDlg, WM_SYSCOMMAND, SC_ICON, 0);
  730. SetTimer(hDlg, 1, POLLING_PRODUCT*PollingPeriod, NULL);
  731. break;
  732. case WM_CLOSE:
  733. case WM_DESTROY:
  734. case WM_ENDSESSION:
  735. case WM_QUIT:
  736. EndDialog(hDlg,0);
  737. break;
  738. case WM_TIMER:
  739. IncrementStats(MTTF_TIME);
  740. break;
  741. case WM_COMMAND: // button was pressed
  742. switch(LOWORD(wParam)) // which one
  743. {
  744. //
  745. // OK: Other problem encountered increment # of others.
  746. //
  747. case IDOK:
  748. SendMessage(hDlg, WM_SYSCOMMAND, SC_ICON, 0);
  749. IncrementStats(MTTF_OTHER);
  750. break;
  751. //
  752. // DISABLE: Disable/Enable Mttf polling.
  753. //
  754. case IDE_DISABLE:
  755. SendMessage(hDlg, WM_SYSCOMMAND, SC_ICON, 0);
  756. //
  757. // Based on whether enabling or disabling, change button and window title
  758. //
  759. if (Enabled) {
  760. SetWindowText((HWND) lParam,"&Enable Mttf Reporting");
  761. SetWindowText(hDlg, "Mttf (Disabled)");
  762. KillTimer(hDlg, 1);
  763. Enabled = FALSE;
  764. } else {
  765. SetWindowText((HWND) lParam,"&Disable Mttf Reporting");
  766. SetWindowText(hDlg, "Mttf (Enabled)");
  767. SetTimer(hDlg, 1, POLLING_PRODUCT*PollingPeriod, NULL);
  768. NtQuerySystemInformation(
  769. SystemPerformanceInformation,
  770. &PerfInfo,
  771. sizeof(PerfInfo),
  772. NULL
  773. );
  774. Enabled = TRUE;
  775. }
  776. break;
  777. //
  778. // CANCEL: Minimize app (no problem)
  779. //
  780. case IDCANCEL:
  781. SendMessage(hDlg, WM_SYSCOMMAND, SC_ICON, 0);
  782. return (TRUE);
  783. //
  784. // HELP: Descriptive message box (.HLP file would be overkill)
  785. //
  786. case IDB_HELP:
  787. MessageBox( NULL,
  788. "Mttf tracks the amount of time your machine stays up, "
  789. "the number of cold and warm boots, and "
  790. "the number of other problems that occur on your machine. "
  791. "All this information is written to a server that is "
  792. "specified in mttf.ini (in your Windows NT directory).\n\n"
  793. "The app should be placed in your start-up group and "
  794. "you should respond accurately (if there was a problem) "
  795. "on startup. When you encounter other problems -- where "
  796. "the system did not require a reboot, but encountered "
  797. "anything you consider a problem -- double-click on the "
  798. "Mttf icon and press the Other Problem button.\n\n"
  799. "When you are running some test that is outside of the "
  800. "realm of normal usage (e.g. Stress), please disable Mttf "
  801. "by double-clicking the icon and pressing disable. When "
  802. "you are done with this test, please press the Enable "
  803. "button to continue reporting.",
  804. "Mean Time to Failure Help",
  805. MB_OK
  806. );
  807. return (TRUE);
  808. default:
  809. ;
  810. } // switch (LOWORD(wParam))
  811. break;
  812. default:
  813. ;
  814. } // switch (message)
  815. return FALSE;
  816. } // EventDlgProc()