Source code of Windows XP (NT5)
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.

619 lines
22 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // MAIN.C / ChkDskW
  4. //
  5. // Microsoft Confidential
  6. // Copyright (c) Microsoft Corporation 1998
  7. // All rights reserved
  8. //
  9. // 8/98 - Jason Cohen (JCOHEN)
  10. //
  11. //////////////////////////////////////////////////////////////////////////////
  12. // Include file(s).
  13. //
  14. #include "main.h"
  15. #include "fmifs.h"
  16. // Internal global variable(s).
  17. //
  18. static BOOL g_bSuccess;
  19. static HWND g_hProgressDlg;
  20. static HICON g_hIconScan[3];
  21. // External global variable(s).
  22. //
  23. extern HINSTANCE g_hInstance;
  24. extern DWORD g_dwFlags;
  25. // Internal function prototype(s).
  26. //
  27. static DWORD WINAPI ThreadChkdsk(LPVOID);
  28. static BOOL CALLBACK FmifsCallback(FMIFS_PACKET_TYPE, ULONG, PVOID);
  29. static VOID UpdateStatus(LPSTR);
  30. static VOID SummaryDialog(HWND, LPTSTR, BOOL);
  31. static INT_PTR CALLBACK SummaryProc(HWND, UINT, WPARAM, LPARAM);
  32. static BOOL Summary_OnInitDialog(HWND, HWND, LPARAM);
  33. static FARPROC LoadDllFunction(LPTSTR, LPCSTR, HINSTANCE *);
  34. HANDLE SpawnChkdsk(HWND hDlg, DWORD dwDrives)
  35. {
  36. DWORD dwThreadId;
  37. // Set that we are scanning a drive currently.
  38. //
  39. g_dwFlags |= SCANDISK_SCANNING;
  40. g_dwFlags &= ~SCANDISK_CANCELSCAN;
  41. // Set up the global variables needed.
  42. //
  43. g_bSuccess = FALSE;
  44. g_hProgressDlg = hDlg;
  45. // Load the icons for the scanning animation.
  46. //
  47. g_hIconScan[0] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN1));
  48. g_hIconScan[1] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN2));
  49. g_hIconScan[2] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN3));
  50. // Create the thread that will run chkdsk.
  51. //
  52. return CreateThread(NULL, 0, ThreadChkdsk, (LPVOID)(ULONG_PTR)dwDrives, 0, &dwThreadId);
  53. }
  54. static DWORD WINAPI ThreadChkdsk(LPVOID dwDrives)
  55. {
  56. HINSTANCE hFmifsDll;
  57. FARPROC Chkdsk;
  58. WCHAR szwFileSystem[16],
  59. szwDrive[] = L"A:\\";
  60. TCHAR szBuffer[256];
  61. INT nCount,
  62. nIndex;
  63. LPINT lpnSelected,
  64. lpnIndex;
  65. LPTSTR lpBuffer,
  66. lpCaption,
  67. lpCapPre;
  68. DWORD_PTR dwMask;
  69. BOOL bContinue,
  70. bSurface,
  71. bFix,
  72. bAllHappy = FALSE;
  73. // Load and run the Chkdsk function.
  74. //
  75. if ( (Chkdsk = LoadDllFunction(_T("FMIFS.DLL"), "Chkdsk", &hFmifsDll)) == NULL )
  76. return 0;
  77. // Get the number of selected items and allocate a buffer to hold all the indexs.
  78. //
  79. if ( ( (nCount = (INT)SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETSELCOUNT, 0, 0L)) > 0 ) &&
  80. ( lpnSelected = (LPINT) MALLOC(nCount * sizeof(INT)) ) )
  81. {
  82. // Now get the list of selected items.
  83. //
  84. if ( (nCount = (INT)SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETSELITEMS, nCount, (LPARAM) lpnSelected)) > 0 )
  85. {
  86. // Disable the controls.
  87. //
  88. EnableWindow(GetDlgItem(g_hProgressDlg, IDOK), FALSE);
  89. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVESTEXT), FALSE);
  90. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVES), FALSE);
  91. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_SURFACE), FALSE);
  92. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_AUTOFIX), FALSE);
  93. // Change the text of the IDCANCEL button to Cancel (from Close).
  94. //
  95. if ( lpBuffer = AllocateString(NULL, IDS_CANCEL) )
  96. {
  97. SetDlgItemText(g_hProgressDlg, IDCANCEL, lpBuffer);
  98. FREE(lpBuffer);
  99. }
  100. // Get the scan options.
  101. //
  102. bSurface = IsDlgButtonChecked(g_hProgressDlg, IDC_SURFACE);
  103. bFix = IsDlgButtonChecked(g_hProgressDlg, IDC_AUTOFIX);
  104. // Get the caption prefix.
  105. //
  106. lpCapPre = AllocateString(NULL, IDS_RESULTS);
  107. // Loop through all the drives in the list box to see if they
  108. // are selected.
  109. //
  110. lpnIndex = lpnSelected;
  111. nIndex = 0;
  112. bAllHappy = TRUE;
  113. for (dwMask = 1; ((DWORD_PTR) dwDrives & ~(dwMask - 1)) && ( !(g_dwFlags & SCANDISK_CANCELSCAN) ); dwMask <<= 1)
  114. {
  115. // Is this drive in the list box.
  116. //
  117. if ( (DWORD_PTR) dwDrives & dwMask )
  118. {
  119. // Test to see if this item is the
  120. // next selected one.
  121. //
  122. if ( *lpnIndex == nIndex )
  123. {
  124. //
  125. // Ok, try and run chkdsk on this drive.
  126. //
  127. // Get the file system type.
  128. //
  129. bContinue = TRUE;
  130. while ( bContinue && !GetVolumeInformationW(szwDrive, NULL, 0, NULL, NULL, NULL, szwFileSystem, sizeof(szwFileSystem)) )
  131. {
  132. bContinue = FALSE;
  133. if ( ( GetLastError() == ERROR_NOT_READY ) &&
  134. ( lpBuffer = AllocateString(NULL, IDS_NOTREADY) ) )
  135. {
  136. if ( MessageBox(g_hProgressDlg, lpBuffer, NULL, MB_RETRYCANCEL | MB_ICONERROR) == IDRETRY )
  137. bContinue = TRUE;
  138. FREE(lpBuffer);
  139. }
  140. }
  141. if ( bContinue )
  142. {
  143. // Now finally launch Chkdsk.
  144. //
  145. Chkdsk(szwDrive, szwFileSystem, FALSE, FALSE, FALSE, bSurface, NULL, FALSE, FmifsCallback);
  146. // Make sure the user didn't cancel.
  147. //
  148. if ( !(g_dwFlags & SCANDISK_CANCELSCAN) )
  149. {
  150. // Check to see if the scan on this drive returned with errors or not.
  151. //
  152. if ( g_bSuccess )
  153. {
  154. // Get the text to use as the caption for the summary box.
  155. //
  156. if (lpCapPre)
  157. lstrcpy(szBuffer, lpCapPre);
  158. else
  159. szBuffer[0] = _T('\0');
  160. if ( SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETTEXT, *lpnIndex, (LPARAM) szBuffer + (lstrlen(szBuffer) * sizeof(TCHAR))) > 0 )
  161. lpCaption = szBuffer;
  162. else
  163. lpCaption = NULL;
  164. // Display the summary message for this drive.
  165. //
  166. SummaryDialog(g_hProgressDlg, NULL, g_bSuccess);
  167. }
  168. else
  169. {
  170. bAllHappy = FALSE;
  171. // If there were errors on this drive and the user
  172. // wants to automatically fix them, we need to run
  173. // the check disk function again with the fix error
  174. // flag set (/F). We don't do this first because if
  175. // the drive can't be locked it won't even scan the
  176. // drive to see if there is an error before asking to
  177. // check on reboot.
  178. //
  179. if ( bFix )
  180. Chkdsk(szwDrive, szwFileSystem, TRUE, FALSE, FALSE, bSurface, NULL, FALSE, FmifsCallback);
  181. }
  182. }
  183. // Make sure the memory for the summary dialog is freed.
  184. //
  185. SummaryDialog(NULL, NULL, FALSE);
  186. // Reset the progress control.
  187. //
  188. SendDlgItemMessage(g_hProgressDlg, IDC_PROGRESS, PBM_SETPOS, 0, 0L);
  189. SetDlgItemText(g_hProgressDlg, IDC_STATUS, NULLSTR);
  190. }
  191. lpnIndex++;
  192. }
  193. // Keep an index of what list box
  194. // item this should be.
  195. //
  196. nIndex++;
  197. }
  198. // Go look at the next drive
  199. //
  200. szwDrive[0]++;
  201. }
  202. // Free the caption prefix.
  203. //
  204. FREE(lpCapPre);
  205. // Renable the controls.
  206. //
  207. EnableWindow(GetDlgItem(g_hProgressDlg, IDOK), TRUE);
  208. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVES), TRUE);
  209. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVESTEXT), TRUE);
  210. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_SURFACE), TRUE);
  211. EnableWindow(GetDlgItem(g_hProgressDlg, IDC_AUTOFIX), TRUE);
  212. // Change the text of the IDCANCEL button back to Close.
  213. //
  214. if ( lpBuffer = AllocateString(NULL, IDS_CLOSE) )
  215. {
  216. SetDlgItemText(g_hProgressDlg, IDCANCEL, lpBuffer);
  217. FREE(lpBuffer);
  218. }
  219. }
  220. FREE(lpnSelected);
  221. }
  222. // Free the DLL library.
  223. //
  224. FreeLibrary(hFmifsDll);
  225. // Reset the scaning bit.
  226. //
  227. g_dwFlags &= ~SCANDISK_SCANNING;
  228. // If we are in SAGERUN mode, end the dialog now that
  229. // we are finished scanning.
  230. //
  231. if ( g_dwFlags & SCANDISK_SAGERUN )
  232. EndDialog(g_hProgressDlg, 0);
  233. // Return the success or failure.
  234. //
  235. return (DWORD) bAllHappy;
  236. }
  237. static BOOL CALLBACK FmifsCallback(FMIFS_PACKET_TYPE PacketType, ULONG PacketLength, PVOID PacketData)
  238. {
  239. #ifdef _DEBUG
  240. DWORD dwBytes;
  241. TCHAR szDebug[1024] = NULLSTR;
  242. HANDLE hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  243. switch (PacketType)
  244. {
  245. case FmIfsPercentCompleted:
  246. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsPercentCompleted (%d%%)\r\n"), ((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted);
  247. break;
  248. case FmIfsFormatReport:
  249. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFormatReport\r\n"));
  250. break;
  251. case FmIfsInsertDisk:
  252. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsInsertDisk\r\n"));
  253. break;
  254. case FmIfsIncompatibleFileSystem:
  255. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIncompatibleFileSystem\r\n"));
  256. break;
  257. case FmIfsFormattingDestination:
  258. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFormattingDestination\r\n"));
  259. break;
  260. case FmIfsIncompatibleMedia:
  261. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIncompatibleMedia\r\n"));
  262. break;
  263. case FmIfsAccessDenied:
  264. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsAccessDenied\r\n"));
  265. break;
  266. case FmIfsMediaWriteProtected:
  267. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsMediaWriteProtected\r\n"));
  268. break;
  269. case FmIfsCantLock:
  270. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCantLock\r\n"));
  271. break;
  272. case FmIfsCantQuickFormat:
  273. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCantQuickFormat\r\n"));
  274. break;
  275. case FmIfsIoError:
  276. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIoError\r\n"));
  277. break;
  278. case FmIfsFinished:
  279. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFinished (%s)\r\n"), ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success ? _T("TRUE") : _T("FALSE"));
  280. break;
  281. case FmIfsBadLabel:
  282. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsBadLabel\r\n"));
  283. break;
  284. case FmIfsCheckOnReboot:
  285. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCheckOnReboot\r\n"));
  286. break;
  287. case FmIfsTextMessage:
  288. break;
  289. case FmIfsHiddenStatus:
  290. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsHiddenStatus\r\n"));
  291. break;
  292. case FmIfsClusterSizeTooSmall:
  293. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsClusterSizeTooSmall\r\n"));
  294. break;
  295. case FmIfsClusterSizeTooBig:
  296. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsClusterSizeTooBig\r\n"));
  297. break;
  298. case FmIfsVolumeTooSmall:
  299. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsVolumeTooSmall\r\n"));
  300. break;
  301. case FmIfsVolumeTooBig:
  302. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsVolumeTooBig\r\n"));
  303. break;
  304. case FmIfsNoMediaInDevice:
  305. wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsNoMediaInDevice\r\n"));
  306. break;
  307. }
  308. if ( hFile != INVALID_HANDLE_VALUE )
  309. {
  310. if ( szDebug[0] )
  311. {
  312. SetFilePointer(hFile, 0, 0, FILE_END);
  313. WriteFile(hFile, szDebug, lstrlen(szDebug) * sizeof(TCHAR), &dwBytes, NULL);
  314. }
  315. CloseHandle(hFile);
  316. }
  317. #endif // _DEBUG
  318. switch (PacketType)
  319. {
  320. case FmIfsPercentCompleted:
  321. // Advance the current position of the progress bar
  322. // to the percent returned.
  323. //
  324. SendDlgItemMessage(g_hProgressDlg, IDC_PROGRESS, PBM_SETPOS, ((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted, 0L);
  325. SendDlgItemMessage(g_hProgressDlg, IDC_SCANDISK, STM_SETIMAGE, IMAGE_ICON, (LPARAM) g_hIconScan[((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted % 3]);
  326. break;
  327. case FmIfsFinished:
  328. g_bSuccess = !((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
  329. break;
  330. case FmIfsTextMessage:
  331. UpdateStatus(((PFMIFS_TEXT_MESSAGE) PacketData)->Message);
  332. break;
  333. case FmIfsCheckOnReboot:
  334. ((PFMIFS_CHECKONREBOOT_INFORMATION) PacketData)->QueryResult =
  335. (MessageBox(g_hProgressDlg, _T("This drive contains errors and must be checked on startup.\n\n")
  336. _T("Do you want this drive to be checked next time you restart you computer?"), _T("Scandisk"), MB_YESNO | MB_ICONERROR) == IDYES);
  337. break;
  338. }
  339. return ( !(g_dwFlags & SCANDISK_CANCELSCAN) );
  340. }
  341. static VOID UpdateStatus(LPSTR lpText)
  342. {
  343. TCHAR szTextOut[256];
  344. LPTSTR lpChkDsk = NULL,
  345. lpScanDisk = NULL,
  346. lpSearch,
  347. lpCopy,
  348. lpNewText;
  349. DWORD dwLen;
  350. HANDLE hFile = INVALID_HANDLE_VALUE;
  351. #ifdef _UNICODE
  352. TCHAR wcHeader = 0x0000;
  353. TCHAR szNewText[256];
  354. #endif // _UNICODE
  355. #ifdef _UNICODE
  356. if ( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpText, -1, szNewText, sizeof(szNewText)) )
  357. {
  358. // If this is unicode, make sure the poitner passed in points to a unicode string.
  359. //
  360. lpNewText = szNewText;
  361. // See if we need to write the header bit so that notepad will
  362. // see the file as unicode.
  363. //
  364. if ( (hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE )
  365. wcHeader = 0xFEFF;
  366. #else // _UNICODE
  367. lpNewText = lpText;
  368. #endif // _UNICODE
  369. // Write to the log file.
  370. //
  371. if ( ( hFile != INVALID_HANDLE_VALUE ) ||
  372. ( (hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE ) )
  373. {
  374. #ifdef _UNICODE
  375. if ( wcHeader )
  376. WriteFile(hFile, &wcHeader, sizeof(WCHAR), &dwLen, NULL);
  377. #endif // _UNICODE
  378. SetFilePointer(hFile, 0, 0, FILE_END);
  379. WriteFile(hFile, (LPTSTR) lpNewText, lstrlen((LPTSTR) lpNewText) * sizeof(TCHAR), &dwLen, NULL);
  380. CloseHandle(hFile);
  381. }
  382. // Remove proceeding characters we don't want (space, \r, \n, \t).
  383. //
  384. for (lpSearch = (LPTSTR) lpNewText; (*lpSearch == _T(' ')) || (*lpSearch == _T('\r')) || (*lpSearch == _T('\n')) || (*lpSearch == _T('\t')); lpSearch++);
  385. if ( ISNUM(*lpSearch) )
  386. {
  387. // We want this info for the summary page.
  388. //
  389. SummaryDialog(g_hProgressDlg, lpSearch, FALSE);
  390. }
  391. else
  392. {
  393. if ( ( lpChkDsk = AllocateString(NULL, IDS_CHKDSK) ) &&
  394. ( lpScanDisk = AllocateString(NULL, IDS_SCANDISK) ) )
  395. {
  396. dwLen = lstrlen(lpChkDsk);
  397. lpCopy = szTextOut;
  398. while ( (*lpSearch != _T('\0')) && (*lpSearch != _T('\r')) )
  399. {
  400. if ( _tcsncmp(lpSearch, lpChkDsk, dwLen) == 0 )
  401. {
  402. lstrcpy(lpCopy, lpScanDisk);
  403. lpSearch += dwLen;
  404. lpCopy += lstrlen(lpScanDisk);
  405. }
  406. else
  407. *lpCopy++ = *lpSearch++;
  408. }
  409. *lpCopy = _T('\0');
  410. SetDlgItemText(g_hProgressDlg, IDC_STATUS, szTextOut);
  411. }
  412. FREE(lpScanDisk);
  413. FREE(lpChkDsk);
  414. }
  415. #ifdef _UNICODE
  416. }
  417. #endif // _UNICODE
  418. }
  419. static VOID SummaryDialog(HWND hWndParent, LPTSTR lpText, BOOL bSuccess)
  420. {
  421. static LPTSTR lpSumText[16];
  422. static DWORD dwIndex = 0;
  423. LPTSTR lpSearch;
  424. // First check to make sure lpText is a valid pointer. If it is NULL
  425. // then we must be showing the summary dialog and/or freeing the memory.
  426. //
  427. if ( lpText )
  428. {
  429. // Make sure we don't already have 16 strings in our buffer.
  430. //
  431. if ( dwIndex < 16 )
  432. {
  433. //
  434. // lpText should already point to the first digit of the number
  435. // part of the summary.
  436. //
  437. // We need a pointer to the text after the number. We will search
  438. // for the first space, which should divide the number and the text.
  439. //
  440. for (lpSearch = lpText; (*lpSearch) && (*lpSearch != _T(' ')); lpSearch++);
  441. // Now that we know where the number ends, we can allocate a buffer for it
  442. // and copy the number into it.
  443. //
  444. if ( lpSumText[dwIndex++] = (LPTSTR) MALLOC((size_t)((lpSearch - lpText + 1) * sizeof(TCHAR))) )
  445. lstrcpyn(lpSumText[dwIndex - 1], lpText, (size_t)(lpSearch - lpText + 1));
  446. // We should advance lpSearch to point to the text description, because now
  447. // it should point to a space (unless we hit the end of the string before the space).
  448. //
  449. if ( *lpSearch )
  450. lpSearch++;
  451. // Now we need to know where the text description ends. We just want to search
  452. // for the first new line or line feed character.
  453. //
  454. for (lpText = lpSearch; (*lpSearch) && (*lpSearch != _T('\r')) && (*lpSearch != _T('\n')); lpSearch++);
  455. // Now that we know where the text ends, we can allocate a buffer for it
  456. // also and copy the text into it.
  457. //
  458. if ( lpSumText[dwIndex++] = (LPTSTR) MALLOC((size_t)((lpSearch - lpText + 1) * sizeof(TCHAR))) )
  459. lstrcpyn(lpSumText[dwIndex - 1], lpText, (size_t)(lpSearch - lpText + 1));
  460. }
  461. }
  462. else
  463. {
  464. // We check to make sure dwIndex still isn't zero, because if it is,
  465. // there is no text to display in the summary dialog or to free.
  466. //
  467. if ( dwIndex > 0 )
  468. {
  469. // If the hwnd is valid and the text is null, then we are
  470. // going to display the summary box.
  471. //
  472. if ( hWndParent )
  473. DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_SUMMARY), hWndParent, SummaryProc, (LPARAM) lpSumText);
  474. //
  475. // Now free the memory because eaither a NULL was passed in for the hwnd
  476. // or we already displayed the dialog and now the memory needs to be freed.
  477. //
  478. // Loop through all the strings that may have
  479. // been allocated by going back from where the index
  480. // is now.
  481. //
  482. // Note that some of the pointers may contain NULL
  483. // if a malloc failed, but the FREE() macro will check
  484. // with that before freeing the memory.
  485. //
  486. while ( dwIndex-- > 0 )
  487. FREE(lpSumText[dwIndex]);
  488. // Reset the index so that it doesn't get messed up
  489. // the next time we display a summary.
  490. //
  491. dwIndex = 0;
  492. }
  493. }
  494. }
  495. static INT_PTR CALLBACK SummaryProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  496. {
  497. switch (uMsg)
  498. {
  499. HANDLE_MSG(hDlg, WM_INITDIALOG, Summary_OnInitDialog);
  500. case WM_COMMAND:
  501. if ( (INT) LOWORD(wParam) != IDOK )
  502. return TRUE;
  503. case WM_CLOSE:
  504. EndDialog(hDlg, 0);
  505. return 0;
  506. }
  507. return FALSE;
  508. }
  509. static BOOL Summary_OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam)
  510. {
  511. INT nSumId[] =
  512. {
  513. IDC_SUM1A, IDC_SUM1B, IDC_SUM2A, IDC_SUM2B,
  514. IDC_SUM3A, IDC_SUM3B, IDC_SUM4A, IDC_SUM4B,
  515. IDC_SUM5A, IDC_SUM5B, IDC_SUM6A, IDC_SUM6B,
  516. IDC_SUM7A, IDC_SUM7B, IDC_SUM8A, IDC_SUM8B
  517. };
  518. LPTSTR *lpStrings = (LPTSTR *) lParam;
  519. DWORD dwIndex;
  520. for (dwIndex = 0; dwIndex < 16; dwIndex++)
  521. SetDlgItemText(hDlg, nSumId[dwIndex], *(lpStrings++));
  522. return FALSE;
  523. }
  524. static FARPROC LoadDllFunction(LPTSTR lpDll, LPCSTR lpFunction, HINSTANCE * lphDll)
  525. {
  526. FARPROC hFunc = NULL;
  527. if ( (*lphDll) = LoadLibrary(lpDll) )
  528. {
  529. if ( (hFunc = GetProcAddress(*lphDll, lpFunction)) == NULL )
  530. {
  531. FreeLibrary(*lphDll);
  532. *lphDll = NULL;
  533. }
  534. }
  535. else
  536. *lphDll = NULL;
  537. return hFunc;
  538. }