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.

680 lines
16 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. utils.c
  5. Abstract:
  6. Contains some functions used by all modules.
  7. Author:
  8. Bogdan Andreiu (bogdana) 10-Feb-1997
  9. Jason Allor (jasonall) 24-Feb-1998 (took over the project)
  10. Revision History:
  11. 10-Feb-1997 bogdana
  12. First draft: the greatest part of the functions
  13. 20_Feb-1997 bogdana
  14. Added three multistring processing functions
  15. 19-Mar-1997 bogdana
  16. Added LogLine and modified LogOCFunction
  17. 12-Apr-1997 bogdana
  18. Modified the multistring processing routines
  19. --*/
  20. #include "octest.h"
  21. /*++
  22. Routine Description: (3.1)
  23. Logs information about the OC Function received from the OC Manager
  24. Arguments:
  25. lpcvComponentId: the name of the component (PVOID because it might be
  26. ANSI or Unicode)
  27. lpcvSubcomponentId: the subcomponent's name (NULL if none)
  28. uiFunction: one of OC_XXX functions
  29. uiParam1: the first param of the call
  30. pvParam2: the second param of the call
  31. Return Value:
  32. void
  33. --*/
  34. VOID LogOCFunction(IN LPCVOID lpcvComponentId,
  35. IN LPCVOID lpcvSubcomponentId,
  36. IN UINT uiFunction,
  37. IN UINT uiParam1,
  38. IN PVOID pvParam2)
  39. {
  40. double fn = 3.1;
  41. UINT uiCount;
  42. TCHAR tszMsg[MAX_MSG_LEN];
  43. WCHAR wszFromANSI[MAX_MSG_LEN];
  44. CHAR cszFromUnicode[MAX_MSG_LEN];
  45. DWORD dwEndVariation;
  46. PSETUP_INIT_COMPONENT psicInitComp;
  47. SYSTEMTIME st;
  48. //
  49. // Don't log OC_PRIVATE_BASE calls. There are too many of them
  50. // and they just clutter up the log. Failures will still be logged.
  51. //
  52. if (uiFunction >= OC_PRIVATE_BASE) return;
  53. //
  54. // Display the current time. This is a way of checking if the
  55. // notifications are received in the proper sequence.
  56. //
  57. GetLocalTime(&st);
  58. _stprintf (tszMsg, TEXT("[%02.2d:%02.2d:%02.2d] "),
  59. (INT)st.wHour, (INT)st.wMinute, (INT)st.wSecond);
  60. //
  61. // The second line contains the function and the return value
  62. //
  63. for (uiCount = 0; uiCount < MAX_OC_FUNCTIONS; uiCount++)
  64. {
  65. if (octFunctionNames[uiCount].uiOCFunction == uiFunction)
  66. {
  67. _stprintf(tszMsg, TEXT("%s %s"),
  68. tszMsg, octFunctionNames[uiCount].tszOCText);
  69. break;
  70. }
  71. }
  72. Log(fn, INFO, TEXT("-----------------------------------"));
  73. LogBlankLine();
  74. Log(fn, INFO, tszMsg);
  75. if (uiFunction != OC_PREINITIALIZE)
  76. {
  77. if (!lpcvComponentId || _tcscmp((PTSTR)lpcvComponentId, TEXT("")) == 0)
  78. {
  79. _stprintf(tszMsg, TEXT("Component = (null) "));
  80. }
  81. else
  82. {
  83. _stprintf(tszMsg, TEXT("Component = %s "), (PTSTR)lpcvComponentId);
  84. }
  85. if (!lpcvSubcomponentId ||
  86. _tcscmp((PTSTR)lpcvSubcomponentId, TEXT("")) == 0)
  87. {
  88. _stprintf(tszMsg, TEXT("%sSubcomponent = (null)"), tszMsg);
  89. }
  90. else
  91. {
  92. _stprintf(tszMsg, TEXT("%sSubcomponent = %s"),
  93. tszMsg, (PTSTR)lpcvSubcomponentId);
  94. }
  95. }
  96. else
  97. {
  98. //
  99. // The SubcomponentId should be the non-native version,
  100. // if it is supported by the OC Manager
  101. //
  102. #ifdef UNICODE
  103. if (uiParam1 & OCFLAG_UNICODE)
  104. {
  105. //
  106. // The ComponentId is Unicode
  107. //
  108. if (uiParam1 & OCFLAG_ANSI)
  109. {
  110. //
  111. // The second param is ANSI, convert to Unicode for
  112. // printing it
  113. //
  114. mbstowcs(wszFromANSI,
  115. (PCHAR)lpcvSubcomponentId,
  116. strlen((PCHAR)lpcvSubcomponentId));
  117. wszFromANSI[strlen((PCHAR)lpcvSubcomponentId)] = L'\0';
  118. }
  119. else
  120. {
  121. //
  122. // Nothing to do if ANSI not supported
  123. //
  124. wszFromANSI[0] = TEXT('\0');
  125. }
  126. _stprintf(tszMsg, TEXT("Component = %s (Unicode) %s (ANSI)"),
  127. lpcvComponentId, wszFromANSI);
  128. }
  129. else
  130. {
  131. //
  132. // Only ANSI supported
  133. //
  134. mbstowcs(wszFromANSI,
  135. (PCHAR)lpcvComponentId,
  136. strlen((PCHAR)lpcvComponentId));
  137. wszFromANSI[strlen((PCHAR)lpcvSubcomponentId)] = L'\0';
  138. _stprintf(tszMsg, TEXT("Component = %s (ANSI only)"), wszFromANSI);
  139. }
  140. #else
  141. //
  142. // ANSI
  143. //
  144. if (uiParam1 & OCFLAG_UNICODE)
  145. {
  146. //
  147. // The ComponentId is Unicode
  148. //
  149. wcstombs(cszFromUnicode,
  150. (PWCHAR)lpcvComponentId,
  151. wcslen((PWCHAR)lpcvComponentId));
  152. cszFromUnicode[wcslen((PWCHAR)lpcvComponentId)] = '\0';
  153. sprintf(tszMsg, "Component = %s (ANSI) %s (Unicode)",
  154. (PCHAR)lpcvSubcomponentId, cszFromUnicode);
  155. }
  156. else
  157. {
  158. sprintf(tszMsg, "Component = %s (ANSI only)",
  159. (PCHAR)lpcvSubcomponentId);
  160. }
  161. #endif
  162. }
  163. //
  164. // Log this first line of information
  165. //
  166. Log(fn, INFO, tszMsg);
  167. //
  168. // Check if the function is in range
  169. //
  170. __ASSERT(uiCount < MAX_OC_FUNCTION);
  171. //
  172. // Now we're ready to print the details
  173. //
  174. switch (uiFunction)
  175. {
  176. case OC_PREINITIALIZE:
  177. break;
  178. case OC_INIT_COMPONENT:
  179. //
  180. // We have a bunch of information to print here
  181. //
  182. psicInitComp = (PSETUP_INIT_COMPONENT)pvParam2;
  183. //
  184. // Assert that the Param2 is not NULL, we can dereference it
  185. //
  186. __ASSERT(psicInitComp != NULL);
  187. Log(fn, INFO, TEXT("OCManagerVersion = %d"),
  188. psicInitComp->OCManagerVersion);
  189. Log(fn, INFO, TEXT("ComponentVersion = %d"),
  190. psicInitComp->ComponentVersion);
  191. //
  192. // The mode first
  193. //
  194. _tcscpy(tszMsg, TEXT("Mode "));
  195. switch (psicInitComp->SetupData.SetupMode)
  196. {
  197. case SETUPMODE_UNKNOWN:
  198. _tcscat(tszMsg, TEXT("Unknown"));
  199. break;
  200. case SETUPMODE_MINIMAL:
  201. _tcscat(tszMsg, TEXT("Minimal"));
  202. break;
  203. case SETUPMODE_TYPICAL:
  204. _tcscat(tszMsg, TEXT("Typical"));
  205. break;
  206. case SETUPMODE_LAPTOP:
  207. _tcscat(tszMsg, TEXT("Laptop"));
  208. break;
  209. case SETUPMODE_CUSTOM:
  210. _tcscat(tszMsg, TEXT("Custom"));
  211. break;
  212. default:
  213. break;
  214. }
  215. //
  216. // ... then the product type
  217. //
  218. _tcscat(tszMsg, TEXT(" ProductType "));
  219. switch (psicInitComp->SetupData.ProductType)
  220. {
  221. case PRODUCT_WORKSTATION:
  222. _tcscat(tszMsg, TEXT("Workstation"));
  223. break;
  224. case PRODUCT_SERVER_PRIMARY:
  225. _tcscat(tszMsg, TEXT("Server Primary"));
  226. break;
  227. case PRODUCT_SERVER_STANDALONE:
  228. _tcscat(tszMsg, TEXT("Server Standalone"));
  229. break;
  230. case PRODUCT_SERVER_SECONDARY:
  231. _tcscat(tszMsg, TEXT("Server Secondary"));
  232. break;
  233. default:
  234. break;
  235. }
  236. //
  237. // ... then the operation
  238. //
  239. _tcscat(tszMsg, TEXT(" Operation "));
  240. switch (psicInitComp->SetupData.OperationFlags)
  241. {
  242. case SETUPOP_WIN31UPGRADE:
  243. _tcscat(tszMsg, TEXT("Win 3.1"));
  244. break;
  245. case SETUPOP_WIN95UPGRADE:
  246. _tcscat(tszMsg, TEXT("Win95"));
  247. break;
  248. case SETUPOP_NTUPGRADE:
  249. _tcscat(tszMsg, TEXT("NT"));
  250. break;
  251. case SETUPOP_BATCH:
  252. _tcscat(tszMsg, TEXT("Batch"));
  253. break;
  254. case SETUPOP_STANDALONE:
  255. _tcscat(tszMsg, TEXT("Standalone"));
  256. break;
  257. default:
  258. break;
  259. }
  260. Log(fn, INFO, tszMsg);
  261. ZeroMemory(tszMsg, MAX_MSG_LEN);
  262. if (psicInitComp->SetupData.SourcePath[0] != TEXT('\0'))
  263. {
  264. _stprintf(tszMsg, TEXT("Source Path = %s"),
  265. psicInitComp->SetupData.SourcePath);
  266. }
  267. if (psicInitComp->SetupData.UnattendFile[0] != TEXT('\0'))
  268. {
  269. _stprintf(tszMsg, TEXT("%s, UnattendedFile = %s"),
  270. tszMsg, psicInitComp->SetupData.UnattendFile);
  271. }
  272. break;
  273. case OC_SET_LANGUAGE:
  274. Log(fn, INFO, TEXT("Primary = %d Secondary = %d"),
  275. PRIMARYLANGID((WORD)uiParam1),
  276. SUBLANGID((WORD)uiParam1));
  277. break;
  278. case OC_QUERY_IMAGE:
  279. break;
  280. case OC_REQUEST_PAGES:
  281. switch (uiParam1)
  282. {
  283. case WizPagesWelcome:
  284. _tcscpy(tszMsg, TEXT("Welcome Pages "));
  285. break;
  286. case WizPagesMode:
  287. _tcscpy(tszMsg, TEXT("Mode Pages"));
  288. break;
  289. case WizPagesEarly:
  290. _tcscpy(tszMsg, TEXT("Early Pages"));
  291. break;
  292. case WizPagesPrenet:
  293. _tcscpy(tszMsg, TEXT("Prenet Pages"));
  294. break;
  295. case WizPagesPostnet:
  296. _tcscpy(tszMsg, TEXT("Postnet Pages"));
  297. break;
  298. case WizPagesLate:
  299. _tcscpy(tszMsg, TEXT("Late Pages"));
  300. break;
  301. case WizPagesFinal:
  302. _tcscpy(tszMsg, TEXT("Final Pages"));
  303. break;
  304. default:
  305. break;
  306. }
  307. Log(fn, INFO, TEXT("Maximum %s = %d"),
  308. tszMsg, ((PSETUP_REQUEST_PAGES)pvParam2)->MaxPages);
  309. break;
  310. case OC_QUERY_CHANGE_SEL_STATE:
  311. Log(fn, INFO, TEXT("Component %s %s"),
  312. ((uiParam1 == 0)?TEXT("unselected"):TEXT("selected")),
  313. (((INT)pvParam2 == OCQ_ACTUAL_SELECTION)?TEXT("Now"):TEXT("")));
  314. break;
  315. default:
  316. break;
  317. }
  318. LogBlankLine();
  319. return;
  320. } // LogOCFunction //
  321. /*++
  322. Routine Description:
  323. Check if a radio button is checked or not.
  324. Arguments:
  325. hwndDialog - handle to the dialog box.
  326. CtrlId - the Control ID.
  327. Return Value:
  328. TRUE if the button is checked, FALSE if not.
  329. --*/
  330. BOOL QueryButtonCheck(IN HWND hwndDlg,
  331. IN INT iCtrlID)
  332. {
  333. HWND hwndCtrl = GetDlgItem(hwndDlg, iCtrlID);
  334. INT iCheck = (INT)SendMessage(hwndCtrl, BM_GETCHECK, 0, 0);
  335. return (iCheck == BST_CHECKED);
  336. } // QueryButtonCheck //
  337. /*++
  338. Routine Description:
  339. Prints the space required on each drive.
  340. Arguments:
  341. DiskSpace - the structure that describes the disk space required.
  342. Return Value:
  343. None.
  344. --*/
  345. VOID PrintSpaceOnDrives(IN HDSKSPC DiskSpace)
  346. {
  347. DWORD dwRequiredSize, dwReturnBufferSize;
  348. PTCHAR tszReturnBuffer, tszPointerToStringToFree;
  349. TCHAR tszMsg[MAX_MSG_LEN];
  350. LONGLONG llSpaceRequired;
  351. SetupQueryDrivesInDiskSpaceList(DiskSpace, NULL, 0, &dwRequiredSize);
  352. dwReturnBufferSize = dwRequiredSize;
  353. __Malloc(&tszReturnBuffer, (dwReturnBufferSize * sizeof(TCHAR)));
  354. SetupQueryDrivesInDiskSpaceList(DiskSpace,
  355. tszReturnBuffer,
  356. dwReturnBufferSize,
  357. &dwRequiredSize);
  358. //
  359. // We need to do this because we'll modify ReturnBuffer
  360. //
  361. tszPointerToStringToFree = tszReturnBuffer;
  362. if (GetLastError() == NO_ERROR)
  363. {
  364. //
  365. // Parse the ReturnBuffer
  366. //
  367. while (*tszReturnBuffer != TEXT('\0'))
  368. {
  369. SetupQuerySpaceRequiredOnDrive(DiskSpace,
  370. tszReturnBuffer,
  371. &llSpaceRequired,
  372. 0, 0);
  373. _stprintf(tszMsg, TEXT("Drive: %s Space required = %I64x, %I64d\n"),
  374. tszReturnBuffer, llSpaceRequired, llSpaceRequired);
  375. OutputDebugString(tszMsg);
  376. //
  377. // The next string is ahead
  378. //
  379. tszReturnBuffer += _tcslen(tszReturnBuffer) + 1;
  380. }
  381. }
  382. __Free(&tszPointerToStringToFree);
  383. return;
  384. } // PrintSpaceOnDrives //
  385. //
  386. // Routines that deal with multistrings.
  387. // All assume that the multistring is double NULL terminated
  388. //
  389. /*++
  390. Routine Description:
  391. Converts a multistring to a string, by replacing the '\0' characters with
  392. blanks. Both strings should be properly allocated.
  393. Arguments:
  394. MultiStr - supplies the multi string.
  395. Str - recieves the string.
  396. Return Value:
  397. None.
  398. --*/
  399. VOID MultiStringToString(IN PTSTR tszMultiStr,
  400. OUT PTSTR tszStr)
  401. {
  402. PTSTR tszAux;
  403. __ASSERT((tszMultiStr != NULL) && (tszStr != NULL));
  404. tszAux = tszMultiStr;
  405. while (*tszAux != TEXT('\0'))
  406. {
  407. _tcscpy(tszStr, tszAux);
  408. //
  409. // Replace the '\0' with ' ' and terminate correctly Str
  410. //
  411. tszStr[tszAux - tszMultiStr + _tcslen(tszAux)] = TEXT(' ');
  412. tszStr[tszAux - tszMultiStr + _tcslen(tszAux) + 1] = TEXT('\0');
  413. tszAux += _tcslen(tszAux) + 1;
  414. }
  415. //
  416. // End properly Str (the last ' ' is useless)
  417. //
  418. tszStr[tszAux - tszMultiStr + _tcslen(tszAux)] = TEXT('\0');
  419. return;
  420. } // MultiStringToString //
  421. /*++
  422. Routine Description:
  423. Calculates the size of a multi string (we can't use _tcslen).
  424. Note that the size is in BYTES
  425. Arguments:
  426. tszMultiStr - the multi string.
  427. Return Value:
  428. The length (in bytes) of the multi string.
  429. --*/
  430. INT MultiStringSize(IN PTSTR tszMultiStr)
  431. {
  432. PTSTR tszAux;
  433. UINT uiLength = 0;
  434. __ASSERT(tszMultiStr != NULL);
  435. tszAux = tszMultiStr;
  436. while (*tszAux != TEXT('\0'))
  437. {
  438. //
  439. // We should count the '\0' after the string
  440. //
  441. uiLength += _tcslen(tszAux) + 1;
  442. tszAux += _tcslen(tszAux) + 1;
  443. }
  444. //
  445. // We didn't count the ending '\0', so add it now
  446. //
  447. return ((uiLength + 1) * sizeof(TCHAR));
  448. } // MultiStringSize //
  449. /*++
  450. Routine Description:
  451. Copies a multistring.
  452. Arguments:
  453. tszMultiStrDestination: the destination multi string.
  454. tszMultiStrSource: the source multi string.
  455. Return Value:
  456. None.
  457. --*/
  458. VOID CopyMultiString(OUT PTSTR tszMultiStrDestination,
  459. IN PTSTR tszMultiStrSource)
  460. {
  461. UINT uiCount = 0;
  462. PTSTR tszAuxS, tszAuxD;
  463. __ASSERT((tszMultiStrSource != NULL) && (tszMultiStrDestination != NULL));
  464. tszAuxS = tszMultiStrSource;
  465. tszAuxD = tszMultiStrDestination;
  466. //
  467. // Copies the multi string
  468. //
  469. while (*tszAuxS != TEXT('\0'))
  470. {
  471. _tcscpy(tszAuxD, tszAuxS);
  472. tszAuxD += _tcslen(tszAuxD) + 1;
  473. tszAuxS += _tcslen(tszAuxS) + 1;
  474. }
  475. //
  476. // Add the terminating NULL
  477. //
  478. *tszAuxD = TEXT('\0');
  479. return;
  480. } // CopyMultiString //
  481. /*++
  482. Routine Description: InitGlobals
  483. Initializes global variables
  484. Arguments:
  485. none
  486. Return Value:
  487. void
  488. --*/
  489. VOID InitGlobals()
  490. {
  491. g_bUsePrivateFunctions = FALSE;
  492. g_bFirstTime = TRUE;
  493. g_uiCurrentPage = 0;
  494. g_bAccessViolation = FALSE;
  495. g_bTestExtended = FALSE;
  496. nStepsFinal = NO_STEPS_FINAL;
  497. g_bNoWizPage = FALSE;
  498. g_bCrashUnicode = FALSE;
  499. g_bInvalidBitmap = FALSE;
  500. g_bHugeSize = FALSE;
  501. g_bCloseInf = FALSE;
  502. hInfGlobal = NULL;
  503. g_bNoNeedMedia = TRUE;
  504. g_bCleanReg = FALSE;
  505. g_uiFunctionToAV = 32574;
  506. g_bNoLangSupport = FALSE;
  507. g_bReboot = FALSE;
  508. } // InitGlobals //