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.

2593 lines
91 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. mini.c
  5. Abstract:
  6. This module contains code that supports the installation and initialization
  7. of a system's network adapter card under the MiniNT environment. Its functions
  8. include changing the ComputerName to a randomly generated string, establishing
  9. the system as being part of a local workgroup, and installing the necessary
  10. drivers (via PnP) for the detected network adapter card. This functionality
  11. relies upon the existence of WINBOM.INI and its following sections:
  12. [Factory]
  13. FactoryComputerName = ... ;Sets the first part of the random generated string to
  14. ;this value...if not present then prepends the random
  15. ;string with the value "MININT"
  16. [NetCards]
  17. PnPID=...\xyz.inf ;Scans the list of netcards/inf key value pairs and attempts
  18. . ;to install drivers for the devices listed here BEFORE performing
  19. . ;an exhaustive search of all the in-box drivers and attempting
  20. . ;to locate the matching paramters for the enumerated hardware.
  21. .
  22. .
  23. Author:
  24. Jason Lawrence (t-jasonl) - 8/11/2000
  25. Revision History:
  26. --*/
  27. #include "factoryp.h"
  28. #include <winioctl.h>
  29. #include <spapip.h>
  30. // Defines
  31. #define CLOSEHANDLE(h) ( (h != NULL) ? (CloseHandle(h) ? ((h = NULL) == NULL) : (FALSE) ) : (FALSE) )
  32. #define BUFSIZE 4096
  33. #define NET_CONNECT_TIMEOUT 120 // seconds
  34. // Various Structures used in this file
  35. //
  36. // ********************************************************************************************************************
  37. // Sample entry into table for FILEINFO struct:
  38. //
  39. // { _T("<config>\\oobeinfo.ini"), _T("oobe\\oobeinfo.ini"), FALSE, TRUE }
  40. //
  41. // This means: Copy file oobeinfo.ini from <opkSourceRoot>\<config>\oobeinfo.ini to <opkTargetDrive>\oobe\oobeinfo.ini
  42. // This is not a directory and is a required file.
  43. //
  44. // Variables allowed to be expanded: <sku>, <arch>, <lang>, <cfg>.
  45. // ********************************************************************************************************************
  46. typedef struct _FILEINFO
  47. {
  48. LPTSTR szFISourceName; // Source name. Relative to source root.
  49. LPTSTR szFITargetName; // Relative to targetpath. If NULL the target drive root is assumed.
  50. BOOL bDirectory; // Is filename a directory? If TRUE do a recursive copy.
  51. BOOL bRequired; // TRUE - file is required. FALSE - file is optional.
  52. } FILEINFO, *PFILEINFO, *LPFILEINFO;
  53. // For the filesystem type
  54. //
  55. typedef enum _FSTYPES
  56. {
  57. fsNtfs,
  58. fsFat32,
  59. fsFat // for fat16/12
  60. } FSTYPES;
  61. // For partition types
  62. //
  63. typedef enum _PTTYPES
  64. {
  65. ptPrimary,
  66. ptExtended,
  67. ptLogical,
  68. ptMsr,
  69. ptEfi
  70. } PTTYPES;
  71. typedef struct _PARTITION
  72. {
  73. TCHAR cDriveLetter;
  74. ULONGLONG ullSize;
  75. UINT uiFileSystem; // NTFS or FAT32 or FAT
  76. BOOL bQuickFormat;
  77. UINT uiPartitionType; // Primary, extended, logical, msr, efi.
  78. BOOL bSetActive;
  79. UINT uiDiskID; // This is the disk number that this partition is on. 0-based
  80. BOOL bWipeDisk; // TRUE if this disk needs to be wiped.
  81. struct _PARTITION *pNext;
  82. } *PPARTITION, PARTITION;
  83. // Local functions
  84. //
  85. LPTSTR static mylstrcat( LPTSTR lpString1, LPCTSTR lpString2, DWORD dwSize );
  86. BOOL static StartDiskpart( HANDLE*, HANDLE*, HANDLE*, HANDLE*);
  87. BOOL static ProcessDiskConfigSection(LPTSTR lpszWinBOMPath);
  88. BOOL static ProcessDisk(UINT diskID, LPTSTR lpSectionName, LPTSTR lpszWinBOMPath, BOOL bWipeDisk);
  89. BOOL static Build(LPTSTR lpKey, DWORD dwSize, UINT diskID, LPCTSTR lpKeyName);
  90. BOOL static FormatPartitions(VOID);
  91. BOOL static JustFormatC(LPTSTR lpszWinBOMPath, LPTSTR lpszSectionBuffer);
  92. BOOL static GetNumberOfPartitions(UINT uiDiskNumber, PDWORD numPartitions);
  93. ULONGLONG static GetDiskSizeMB(UINT uiDiskNumber);
  94. VOID static ListInsert(PPARTITION pAfterThis, PPARTITION pNew);
  95. VOID static ListFree(PPARTITION pList);
  96. VOID static AddMsrAndEfi(BOOL bMsr, BOOL bEfi, PPARTITION pLastLast, UINT uiDiskID, BOOL bWipeDisk);
  97. //
  98. // Default system policies for driver signing and non-driver signing
  99. // for WinPE
  100. //
  101. #define DEFAULT_DRVSIGN_POLICY DRIVERSIGN_NONE
  102. #define DEFAULT_NONDRVSIGN_POLICY DRIVERSIGN_NONE
  103. VOID
  104. pSetupGetRealSystemTime(
  105. OUT LPSYSTEMTIME RealSystemTime
  106. );
  107. typedef enum _CODESIGNING_POLICY_TYPE {
  108. PolicyTypeDriverSigning,
  109. PolicyTypeNonDriverSigning
  110. } CODESIGNING_POLICY_TYPE, *PCODESIGNING_POLICY_TYPE;
  111. VOID
  112. pSetCodeSigningPolicy(
  113. IN CODESIGNING_POLICY_TYPE PolicyType,
  114. IN BYTE NewPolicy,
  115. OUT PBYTE OldPolicy OPTIONAL
  116. );
  117. //**********************************************************
  118. // The formula for calculating the size of ESP partition is:
  119. //
  120. // MAX( 100 MB, MIN (1000 MB, DiskSize MB / 100 ) )
  121. //
  122. //**********************************************************
  123. __inline
  124. ULONGLONG
  125. GetDiskEFISizeMB( UINT uiDiskNumber )
  126. {
  127. ULONGLONG DiskSizeMB = GetDiskSizeMB( uiDiskNumber );
  128. return ( max( 100, min( 1000, DiskSizeMB / 100 ) ) );
  129. }
  130. //**********************************************************
  131. // The formula for calculating the size of MSR partition is:
  132. //
  133. // IF ( Disk Size < 16 GB ) then MSR is 32 MB.
  134. // ELSE MSR is 128 MB.
  135. //
  136. //**********************************************************
  137. __inline
  138. ULONGLONG
  139. GetDiskMSRSizeMB( UINT uiDiskNumber )
  140. {
  141. ULONGLONG DiskSizeMB = GetDiskSizeMB( uiDiskNumber );
  142. return ( ( ( DiskSizeMB / 1024 ) >= 16 ) ? 128 : 32 );
  143. }
  144. // Dialog Procs
  145. //
  146. INT_PTR CALLBACK ShutdownDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  147. // Constant Strings
  148. //
  149. const static TCHAR DCDISK[] = _T("select disk ");
  150. const static TCHAR DCPARTITION[] = _T("create partition ");
  151. const static TCHAR DCSIZE[] = _T(" size=");
  152. const static TCHAR DCASSIGNLETTER[] = _T("assign letter=");
  153. const static TCHAR DCEXIT[] = _T("exit");
  154. const static TCHAR DCNEWLINE[] = _T("\n");
  155. const static TCHAR DCLISTPARTITION[] = _T("list partition");
  156. const static TCHAR DCSELPARTITION[] = _T("select partition ");
  157. const static TCHAR DCSETACTIVE[] = _T("active");
  158. // This command will delete all the partitions on a disk.
  159. //
  160. const static TCHAR DCWIPEDISK[] = _T("clean");
  161. const static TCHAR DCCONVERT_GPT[] = _T("convert gpt\nselect partition 1\ndelete partition override");
  162. const static TCHAR DCPARTITION_PRIMARY[] = _T("primary");
  163. const static TCHAR DCPARTITION_EXTENDED[] = _T("extended");
  164. const static TCHAR DCPARTITION_LOGICAL[] = _T("logical");
  165. const static TCHAR DCPARTITION_MSR[] = _T("msr");
  166. const static TCHAR DCPARTITION_EFI[] = _T("efi");
  167. const static TCHAR DCS_DISK_TYPE[] = _T("DiskType");
  168. const static TCHAR DCS_FILE_SYSTEM[] = _T("FileSystem");
  169. const static TCHAR DCS_QUICK_FORMAT[] = _T("QuickFormat");
  170. const static TCHAR DCS_SIZE[] = _T("Size");
  171. const static TCHAR DCS_PARTITION_TYPE[] = _T("PartitionType");
  172. const static TCHAR DCS_PARTITION_ID[] = _T("PartitionID");
  173. const static TCHAR DCS_SET_ACTIVE[] = _T("SetActive");
  174. const static TCHAR c_szActiveComputerNameRegKey[] = L"System\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName";
  175. const static TCHAR c_szComputerNameRegKey[] = L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
  176. static TCHAR g_szTargetDrive[] = _T("C:\\");
  177. // Files to be copied.
  178. // No leading or trailing backslashes.
  179. //
  180. static FILEINFO g_filesToCopy[] =
  181. {
  182. // SOURCE, TARGET, isDirectory, isRequired
  183. //
  184. { _T("cfgsets\\<cfg>\\winbom.ini"), _T("sysprep\\winbom.ini"), FALSE, TRUE },
  185. { _T("cfgsets\\<cfg>\\unattend.txt"), _T("sysprep\\unattend.txt"), FALSE, TRUE },
  186. { _T("lang\\<lang>\\tools\\<arch>"), _T("sysprep"), TRUE, FALSE },
  187. { _T("lang\\<lang>\\sku\\<sku>\\<arch>"), _T(""), TRUE, TRUE }
  188. };
  189. // Linked list to hold partition information.
  190. //
  191. static PPARTITION g_PartList = NULL;
  192. // External variables
  193. //
  194. extern HINSTANCE g_hInstance;
  195. // External functions
  196. //
  197. typedef VOID (WINAPI *ExternalGenerateName)
  198. (
  199. PWSTR GeneratedString,
  200. DWORD DesiredStrLen
  201. );
  202. /*++
  203. ===============================================================================
  204. Routine Description:
  205. BOOL SetupMiniNT
  206. This routine serves as the main entry point for initializing the netcard
  207. under MiniNT. Also performs the tasks of changing the computer name
  208. and establishing the computer as part of a local workgroup. Called from
  209. factory!WinMain.
  210. Arguments:
  211. Return Value:
  212. TRUE if netcard was correctly installed
  213. FALSE if there was an error
  214. ===============================================================================
  215. --*/
  216. BOOL
  217. SetupMiniNT(
  218. VOID
  219. )
  220. {
  221. BOOL bInstallNIC;
  222. BOOL bRet = TRUE;
  223. WCHAR szRequestedComputerName[100];
  224. WCHAR szComputerName[100];
  225. WCHAR szGeneratedName[100];
  226. PWSTR AppendStr = NULL;
  227. // for syssetup.dll GenerateName
  228. HINSTANCE hInstSysSetup = NULL;
  229. ExternalGenerateName pGenerateName = NULL;
  230. HKEY hActiveComputerNameKey;
  231. HKEY hComputerNameKey;
  232. BOOL RemoteBoot = IsRemoteBoot();
  233. extern FACTMODE g_fm;
  234. LPTSTR lpszAdmin = NULL;
  235. LPTSTR lpszWorkgroup = NULL;
  236. //
  237. // Reset the driver signing policy in WinPE
  238. //
  239. pSetCodeSigningPolicy(PolicyTypeDriverSigning,
  240. DEFAULT_DRVSIGN_POLICY,
  241. NULL);
  242. pSetCodeSigningPolicy(PolicyTypeNonDriverSigning,
  243. DEFAULT_NONDRVSIGN_POLICY,
  244. NULL);
  245. if (!RemoteBoot) {
  246. // set random computer name
  247. hInstSysSetup = LoadLibrary(L"syssetup.dll");
  248. if (hInstSysSetup == NULL)
  249. {
  250. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to load syssetup.dll");
  251. bRet = FALSE;
  252. goto Clean;
  253. }
  254. pGenerateName = (ExternalGenerateName)GetProcAddress(hInstSysSetup,
  255. "GenerateName");
  256. if (pGenerateName == NULL)
  257. {
  258. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to obtain address of GenerateName");
  259. bRet = FALSE;
  260. goto Clean;
  261. }
  262. // call GenerateName
  263. pGenerateName(szGeneratedName, 15);
  264. // obtain factory computer name from winbom.ini...default to MININT
  265. GetPrivateProfileString(L"Factory",
  266. L"FactoryComputerName",
  267. L"MININT",
  268. szRequestedComputerName,
  269. sizeof(szRequestedComputerName)/sizeof(TCHAR),
  270. g_szWinBOMPath);
  271. lstrcpyn (szComputerName, szRequestedComputerName, AS ( szComputerName ) );
  272. AppendStr = wcsstr(szGeneratedName, L"-");
  273. // ISSUE-2002/02/27-acosma,georgeje - The size of the computername we generate
  274. // is not guaranteed to be less than MAX_COMPUTERNAME length.
  275. //
  276. if ( AppendStr )
  277. {
  278. if ( FAILED ( StringCchCat ( szComputerName, AS ( szComputerName ), AppendStr) ) )
  279. {
  280. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szComputerName, AppendStr ) ;
  281. }
  282. }
  283. // now set the computer name
  284. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  285. c_szActiveComputerNameRegKey,
  286. 0,
  287. KEY_SET_VALUE,
  288. &hActiveComputerNameKey))
  289. {
  290. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to open ActiveComputerName.");
  291. bRet = FALSE;
  292. goto Clean;
  293. }
  294. if ( ERROR_SUCCESS != RegSetValueEx(hActiveComputerNameKey,
  295. L"ComputerName",
  296. 0,
  297. REG_SZ,
  298. (LPBYTE)szComputerName,
  299. (lstrlen(szComputerName)+1) * sizeof(WCHAR)) )
  300. {
  301. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to set ActiveComputerName.");
  302. bRet = FALSE;
  303. goto Clean;
  304. }
  305. RegCloseKey(hActiveComputerNameKey);
  306. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  307. c_szComputerNameRegKey,
  308. 0,
  309. KEY_SET_VALUE,
  310. &hComputerNameKey))
  311. {
  312. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to open ComputerName.");
  313. bRet = FALSE;
  314. goto Clean;
  315. }
  316. if ( ERROR_SUCCESS != RegSetValueEx(hComputerNameKey,
  317. L"ComputerName",
  318. 0,
  319. REG_SZ,
  320. (LPBYTE)szComputerName,
  321. (lstrlen(szComputerName)+1) * sizeof(WCHAR)) )
  322. {
  323. FacLogFileStr(0 | LOG_ERR | LOG_MSG_BOX, L"Failed to set ComputerName.");
  324. bRet = FALSE;
  325. goto Clean;
  326. }
  327. RegCloseKey(hComputerNameKey);
  328. lpszAdmin = AllocateString(NULL, IDS_ADMIN);
  329. if(lpszAdmin == NULL) {
  330. bRet = FALSE;
  331. goto Clean;
  332. }
  333. lpszWorkgroup = AllocateString(NULL, IDS_WORKGROUP);
  334. if(lpszWorkgroup == NULL) {
  335. bRet = FALSE;
  336. goto Clean;
  337. }
  338. // establish this computer as part of a workgroup
  339. NetJoinDomain(NULL,
  340. lpszWorkgroup,
  341. NULL,
  342. lpszAdmin,
  343. NULL,
  344. 0);
  345. }
  346. //
  347. // Install nic and always if we fail to install the netcard from the [NetCards] section
  348. // do a full scan.
  349. //
  350. if (!(bInstallNIC = InstallNetworkCard(g_szWinBOMPath, FALSE)))
  351. {
  352. if (!(bInstallNIC = InstallNetworkCard(g_szWinBOMPath, TRUE)))
  353. {
  354. bRet = FALSE;
  355. goto Clean;
  356. }
  357. }
  358. Clean:
  359. if (hInstSysSetup != NULL)
  360. {
  361. FreeLibrary(hInstSysSetup);
  362. }
  363. FREE(lpszAdmin);
  364. FREE(lpszWorkgroup);
  365. return bRet;
  366. }
  367. /*++
  368. ===============================================================================
  369. Routine Description:
  370. BOOL PartitionFormat(LPSTATEDATA lpStateData)
  371. This routine will partition and format the C drive of the target machine.
  372. Arguments:
  373. lpStateData->lpszWinBOMPath
  374. - Buffer containing the fully qualified path to the WINBOM
  375. file
  376. Return Value:
  377. TRUE if no errors were encountered
  378. FALSE if there was an error
  379. ===============================================================================
  380. --*/
  381. BOOL PartitionFormat(LPSTATEDATA lpStateData)
  382. {
  383. LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath;
  384. BOOL bPartition = FALSE;
  385. BOOL bForceFormat = FALSE;
  386. BOOL bRet = TRUE;
  387. // Stuff for partitioning.
  388. //
  389. HANDLE hStdinRd = NULL,
  390. hStdinWrDup = NULL,
  391. hStdoutWr = NULL,
  392. hStdoutRdDup = NULL;
  393. DWORD dwRead = 0;
  394. LPTSTR lpszBuf = NULL;
  395. DWORD dwWritten = 0;
  396. DWORD dwToWrite = 0;
  397. TCHAR szCommand[BUFSIZE] = NULLSTR;
  398. CHAR szCommandA[BUFSIZE] = {0};
  399. DWORD dwLogicalDrives = 0;
  400. TCHAR cDriveLetter = _T('D');
  401. #ifdef DBG
  402. HANDLE hDebugFile = NULL;
  403. #endif
  404. DWORD nPartitions = 0;
  405. LPTSTR lpCommand = szCommand;
  406. //
  407. // Partition and Format drives.
  408. //
  409. *szCommand = NULLCHR;
  410. // Get the logical drives in existence
  411. //
  412. dwLogicalDrives = GetLogicalDrives();
  413. // Read from the WinBOM to set partitioning parameters and
  414. // Start Diskpart with redirected input and output.
  415. //
  416. if ( ProcessDiskConfigSection(lpszWinBOMPath) &&
  417. StartDiskpart(&hStdinWrDup, &hStdoutRdDup, &hStdinRd, &hStdoutWr) )
  418. {
  419. UINT dwLastDiskN = UINT_MAX;
  420. PPARTITION pCur;
  421. UINT i = 1; // Partition number on disk.
  422. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  423. //
  424. // This call is to initialize the length for mystrcat function.
  425. //
  426. mylstrcat(lpCommand, NULLSTR, AS ( szCommand ) );
  427. // First go through all the disks and clean them if specified in the
  428. // respective nodes.
  429. //
  430. for (pCur = g_PartList; pCur; pCur = pCur->pNext )
  431. {
  432. // Only do this stuff if we're working with a new disk number.
  433. //
  434. if ( (dwLastDiskN != pCur->uiDiskID) && (pCur->bWipeDisk) )
  435. {
  436. _itow(pCur->uiDiskID, szBuf, 10);
  437. lpCommand = mylstrcat(lpCommand, DCDISK, 0 );
  438. lpCommand = mylstrcat(lpCommand, szBuf, 0 );
  439. lpCommand = mylstrcat(lpCommand, DCNEWLINE,0 );
  440. lpCommand = mylstrcat(lpCommand, DCWIPEDISK, 0 );
  441. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  442. // Set the last disk to the current disk.
  443. //
  444. dwLastDiskN = pCur->uiDiskID;
  445. }
  446. }
  447. // Initialize this again for the next loop.
  448. //
  449. dwLastDiskN = UINT_MAX;
  450. for (pCur = g_PartList; pCur; pCur = pCur->pNext )
  451. {
  452. TCHAR szDriveLetter[2];
  453. // Only do this stuff if we're working with a new disk number.
  454. //
  455. if ( dwLastDiskN != pCur->uiDiskID )
  456. {
  457. _itow(pCur->uiDiskID, szBuf, 10);
  458. lpCommand = mylstrcat(lpCommand, DCDISK, 0 );
  459. lpCommand = mylstrcat(lpCommand, szBuf, 0 );
  460. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  461. if ( pCur->bWipeDisk && GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  462. {
  463. lpCommand = mylstrcat(lpCommand, DCCONVERT_GPT, 0 );
  464. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  465. }
  466. // Set the last disk to the current disk.
  467. //
  468. dwLastDiskN = pCur->uiDiskID;
  469. // Reset the partition number on the disk to 1.
  470. //
  471. i = 1;
  472. }
  473. // Partition type (primary|extended|logical|efi|msr)
  474. //
  475. lpCommand = mylstrcat(lpCommand, DCPARTITION, 0 );
  476. if ( ptPrimary == pCur->uiPartitionType )
  477. lpCommand = mylstrcat(lpCommand, DCPARTITION_PRIMARY, 0 );
  478. else if ( ptExtended == pCur->uiPartitionType )
  479. lpCommand = mylstrcat(lpCommand, DCPARTITION_EXTENDED, 0 );
  480. else if ( ptEfi == pCur->uiPartitionType )
  481. lpCommand = mylstrcat(lpCommand, DCPARTITION_EFI, 0 );
  482. else if ( ptMsr == pCur->uiPartitionType )
  483. lpCommand = mylstrcat(lpCommand, DCPARTITION_MSR, 0 );
  484. else
  485. lpCommand = mylstrcat(lpCommand, DCPARTITION_LOGICAL, 0 );
  486. // Size of partition.
  487. //
  488. if ( 0 != pCur->ullSize )
  489. {
  490. *szBuf = NULLCHR;
  491. _i64tow(pCur->ullSize, szBuf, 10);
  492. lpCommand = mylstrcat(lpCommand, DCSIZE, 0);
  493. lpCommand = mylstrcat(lpCommand, szBuf, 0);
  494. }
  495. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0);
  496. if ( ptExtended != pCur->uiPartitionType && ptMsr != pCur->uiPartitionType )
  497. {
  498. *szBuf = NULLCHR;
  499. _itow(i, szBuf, 10);
  500. lpCommand = mylstrcat(lpCommand, DCSELPARTITION, 0 );
  501. lpCommand = mylstrcat(lpCommand, szBuf, 0 );
  502. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0);
  503. while ((dwLogicalDrives & ( (DWORD) 0x01 << (cDriveLetter - _T('A')))))
  504. cDriveLetter++;
  505. if (cDriveLetter > _T('Z'))
  506. {
  507. // Ran out of drive letters. Get out of here.
  508. FacLogFile(0 | LOG_ERR, IDS_ERR_OUTOFDRIVELETTERS);
  509. bRet = FALSE;
  510. break;
  511. }
  512. if ( pCur->bSetActive && (0 == pCur->uiDiskID) )
  513. {
  514. pCur->cDriveLetter = _T('C');
  515. lstrcpyn( szDriveLetter, _T("C"), AS ( szDriveLetter ) );
  516. g_szTargetDrive[0] = pCur->cDriveLetter;
  517. }
  518. else
  519. {
  520. // Assign the new drive letter to this drive.
  521. //
  522. pCur->cDriveLetter = cDriveLetter;
  523. szDriveLetter[0] = cDriveLetter;
  524. szDriveLetter[1] = NULLCHR;
  525. cDriveLetter++;
  526. }
  527. lpCommand = mylstrcat(lpCommand, DCASSIGNLETTER, 0 );
  528. lpCommand = mylstrcat(lpCommand, szDriveLetter, 0 );
  529. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  530. // If this is the partition that we want to set active, make this
  531. // the partition where we install the OS. Only allow the TargetDrive
  532. // on a partition on disk 0.
  533. //
  534. if ( pCur->bSetActive && !GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  535. {
  536. lpCommand = mylstrcat(lpCommand, DCSETACTIVE, 0 );
  537. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  538. }
  539. }
  540. i++;
  541. }
  542. if (bRet)
  543. {
  544. lpCommand = mylstrcat(lpCommand, DCEXIT, 0 );
  545. lpCommand = mylstrcat(lpCommand, DCNEWLINE, 0 );
  546. // Some debugging output here.
  547. //
  548. FacLogFileStr(3, szCommand);
  549. // Convert UNICODE string to ANSI string.
  550. //
  551. if ((dwToWrite = WideCharToMultiByte(
  552. CP_ACP,
  553. 0,
  554. szCommand,
  555. -1,
  556. szCommandA,
  557. sizeof(szCommandA),
  558. NULL,
  559. NULL
  560. )))
  561. {
  562. // Write to pipe that is the standard input for the child process.
  563. //
  564. if (! WriteFile(hStdinWrDup, szCommandA, dwToWrite,
  565. &dwWritten, NULL))
  566. {
  567. FacLogFile(0 | LOG_ERR, IDS_ERR_WRITEPIPE);
  568. bRet = FALSE;
  569. }
  570. }
  571. else
  572. bRet = FALSE;
  573. }
  574. // Close the pipe handle so the child process stops reading.
  575. //
  576. CLOSEHANDLE(hStdinWrDup);
  577. // Read from pipe that is the standard output for child process.
  578. //
  579. dwWritten = 0;
  580. // Close the write end of the pipe before reading from the
  581. // read end of the pipe.
  582. //
  583. CLOSEHANDLE(hStdoutWr);
  584. // Read output from the child process, and write to parent's STDOUT.
  585. //
  586. #ifdef DBG
  587. hDebugFile = CreateFile(_T("diskpart.txt"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  588. #endif
  589. // Allocate the buffer we will read from...
  590. //
  591. lpszBuf = MALLOC(BUFSIZE * sizeof(TCHAR));
  592. if ( lpszBuf )
  593. {
  594. for (;;)
  595. {
  596. if( !ReadFile( hStdoutRdDup, lpszBuf, BUFSIZE, &dwRead,
  597. NULL) || dwRead == 0) break;
  598. #ifdef DBG
  599. if (hDebugFile != INVALID_HANDLE_VALUE)
  600. if (! WriteFile(hDebugFile, lpszBuf, dwRead, &dwWritten, NULL))
  601. break;
  602. #endif
  603. }
  604. // Free the buffer we used for reading
  605. //
  606. FREE( lpszBuf );
  607. }
  608. #ifdef DBG
  609. CLOSEHANDLE(hDebugFile);
  610. #endif
  611. } else
  612. bRet = FALSE;
  613. // Format partitions.
  614. //
  615. if ( bRet )
  616. {
  617. TCHAR szDirectory[MAX_PATH] = NULLSTR;
  618. if ( GetSystemDirectory(szDirectory, MAX_PATH) )
  619. SetCurrentDirectory(szDirectory);
  620. // Go through the array of partitions in g_PartTable and format all the partitions that
  621. // were just created (except for extended type partitions).
  622. //
  623. if (!FormatPartitions())
  624. bRet = FALSE;
  625. } // if (bRet)
  626. // Now let's try to enable logging again if it is disabled, since we have
  627. // new writable drives.
  628. //
  629. if (bRet && !g_szLogFile[0])
  630. InitLogging(lpszWinBOMPath);
  631. // Clean-up
  632. //
  633. FacLogFileStr(3, _T("Cleaning up PartitionFormat()\n"));
  634. // Delete the linked list of partition info.
  635. //
  636. ListFree(g_PartList);
  637. // Make sure that all the handles are closed.
  638. //
  639. CLOSEHANDLE(hStdoutRdDup);
  640. CLOSEHANDLE(hStdinRd);
  641. CLOSEHANDLE(hStdinWrDup);
  642. CLOSEHANDLE(hStdoutWr);
  643. return bRet;
  644. }
  645. BOOL DisplayPartitionFormat(LPSTATEDATA lpStateData)
  646. {
  647. return IniSettingExists(lpStateData->lpszWinBOMPath, INI_SEC_WBOM_DISKCONFIG, NULL, NULL);
  648. }
  649. /*++
  650. ===============================================================================
  651. Routine Description:
  652. BOOL ExpandStrings(LPCTSTR szSource, LPTSTR szDest, UINT nSize)
  653. This is a helper routine for CopyFiles() to expand replaceable strings with
  654. user defined strings from the WinBOM.
  655. Arguments:
  656. szSource - Buffer containing string with replaceable parameters.
  657. szDest - Buffer where expanded string will be written to.
  658. nSize - Size of the szDest string.
  659. Return Value:
  660. TRUE if no errors were encountered
  661. FALSE if there was an error
  662. Remarks:
  663. Function assumes that the env (environment) table has been prepopulated.
  664. The function will fail if the size of the expanded string exceeds nSize.
  665. ===============================================================================
  666. --*/
  667. BOOL ExpandStrings(LPCTSTR szSource, LPTSTR szDest, UINT nSize, LPTSTR *env, UINT uiEnvSize)
  668. {
  669. UINT uiDestLength = 0; // in TCHAR's
  670. UINT j = 0; // just a counter to go through the environment table
  671. UINT uiVarNameLength = 0; // in TCHAR's
  672. UINT uiVarLength = 0;
  673. TCHAR szVar[MAX_PATH] = NULLSTR;
  674. LPTSTR pVarValue = NULL;
  675. LPTSTR pSrc;
  676. pSrc = (LPTSTR) szSource;
  677. while (*pSrc != NULLCHR)
  678. {
  679. if (*pSrc == '<')
  680. {
  681. //
  682. // Now we're looking at a variable that must be replaced.
  683. //
  684. // Go to first char in var name.
  685. pSrc = CharNext(pSrc);
  686. uiVarNameLength = 0;
  687. while (*pSrc != '>')
  688. {
  689. szVar[uiVarNameLength++] = *pSrc;
  690. if ( *(pSrc = CharNext(pSrc)) == NULLCHR)
  691. {
  692. // Terminate the szVar string with NULL
  693. szVar[uiVarNameLength] = NULLCHR;
  694. FacLogFileStr(3, _T("Illegal syntax. Cannot find closing '>' for variable: %s"), szVar);
  695. return FALSE;
  696. }
  697. }
  698. // Skip the closing '>'.
  699. //
  700. pSrc = CharNext(pSrc);
  701. // Add the terminating NULL character to the szVar.
  702. //
  703. szVar[uiVarNameLength] = NULLCHR;
  704. pVarValue = NULL;
  705. // Find the value for this variable in the environment table.
  706. //
  707. for (j = 0; j < uiEnvSize; j += 2)
  708. if (!lstrcmpi(szVar, env[j]))
  709. {
  710. pVarValue = env[j + 1];
  711. break;
  712. }
  713. // If the Variable was not found return FALSE.
  714. //
  715. if (!pVarValue)
  716. {
  717. FacLogFileStr(3, _T("Variable not found: %s\n"), szVar);
  718. return FALSE;
  719. }
  720. // Now copy the variable value to the target string.
  721. //
  722. uiVarLength = lstrlen(pVarValue);
  723. if ((uiDestLength + uiVarLength) < nSize)
  724. {
  725. lstrcpyn(&szDest[uiDestLength], pVarValue, AS ( szDest ) - uiDestLength);
  726. uiDestLength += uiVarLength;
  727. }
  728. else
  729. {
  730. // szDest buffer size exceeded.
  731. //
  732. FacLogFileStr(3, _T("Destination buffer size exceeded while expanding strings\n"));
  733. return FALSE;
  734. }
  735. }
  736. else // If *pSrc is a regular character copy it to the target buffer.
  737. {
  738. if (uiDestLength < nSize - 1)
  739. {
  740. szDest[uiDestLength++] = *pSrc;
  741. pSrc = CharNext(pSrc);
  742. }
  743. else
  744. {
  745. // szDest buffer size exceeded.
  746. //
  747. FacLogFileStr(3, _T("Destination buffer size exceeded while expanding strings\n"));
  748. return FALSE;
  749. }
  750. }
  751. }
  752. // Terminate the destination buffer with NULL character.
  753. //
  754. szDest[uiDestLength] = NULLCHR;
  755. return TRUE;
  756. }
  757. /*++
  758. ===============================================================================
  759. Routine Description:
  760. BOOL CopyFiles(LPSTATEDATA lpStateData)
  761. This routine will copy the necessary configuration files to a machine and
  762. start setup of Whistler.
  763. Arguments:
  764. lpStateData->lpszWinBOMPath
  765. - Buffer containing the fully qualified path to the WINBOM
  766. file
  767. Return Value:
  768. TRUE if no errors were encountered
  769. FALSE if there was an error
  770. Remarks:
  771. ===============================================================================
  772. --*/
  773. BOOL CopyFiles(LPSTATEDATA lpStateData)
  774. {
  775. LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath;
  776. // All variables that are expanded from the pathnames are given here.
  777. //
  778. // Leading or trailing backslashes are not allowed in the WinBOM for these VARS.
  779. //
  780. TCHAR szSku[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  781. TCHAR szLang[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  782. TCHAR szArch[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  783. TCHAR szCfg[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  784. TCHAR szOpkSrcRoot[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  785. TCHAR szOptSources[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  786. // Username, password and domain name used to login if a UNC path is specified for szOpkSrcRoot.
  787. //
  788. TCHAR szUsername[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  789. TCHAR szPassword[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  790. TCHAR szDomain[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  791. LPTSTR env[] =
  792. {
  793. _T("sku"), szSku,
  794. _T("lang"), szLang,
  795. _T("arch"), szArch,
  796. _T("cfg"), szCfg
  797. };
  798. UINT i = 0;
  799. TCHAR szSource[MAX_PATH] = NULLSTR;
  800. TCHAR szTarget[MAX_PATH] = NULLSTR;
  801. TCHAR szBuffer[MAX_PATH] = NULLSTR;
  802. BOOL bRet = TRUE;
  803. UINT uiLength = 0;
  804. //
  805. // Set up the globals.
  806. //
  807. // Read from WinBOM.
  808. //
  809. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_LANG, NULLSTR, szLang, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  810. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_SKU, NULLSTR, szSku, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  811. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_CFGSET, NULLSTR, szCfg, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  812. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_SRCROOT, NULLSTR, szOpkSrcRoot, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  813. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_OPTSOURCES, NULLSTR, szOptSources, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  814. // Find the system architecture. (x86 or ia64)
  815. //
  816. if ( GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  817. lstrcpyn(szArch, _T("ia64"), AS ( szArch ) );
  818. else
  819. lstrcpyn(szArch, _T("x86"), AS ( szArch ) );
  820. if (*szLang && *szSku && *szCfg && *szOpkSrcRoot)
  821. {
  822. LPTSTR lpSource = NULLCHR;
  823. LPTSTR lpTarget = NULLCHR;
  824. LPTSTR lpOpkSrcRoot = NULLCHR;
  825. DWORD cbSource = 0;
  826. DWORD cbTarget = 0;
  827. DWORD dwError = 0;
  828. TCHAR szOpkSrcComputerName[MAX_COMPUTERNAME_LENGTH + 1] = NULLSTR;
  829. LPTSTR lpComputerName = NULL;
  830. NET_API_STATUS nas = NERR_Success;
  831. // Make sure that source and target directories contain a trailing backslash
  832. // If there is not trailing backslash add one.
  833. //
  834. AddPathN(szOpkSrcRoot, NULLSTR, AS ( szOpkSrcRoot ));
  835. AddPathN(g_szTargetDrive, NULLSTR, AS ( g_szTargetDrive ) );
  836. // Parse the SrcRoot string and pull out the unc path
  837. //
  838. lpOpkSrcRoot = szOpkSrcRoot;
  839. if (( *lpOpkSrcRoot == CHR_BACKSLASH) &&
  840. ( *(lpOpkSrcRoot = CharNext(lpOpkSrcRoot)) == CHR_BACKSLASH))
  841. {
  842. DWORD dwTimeStart = 0;
  843. DWORD dwTimeLast = 0;
  844. // We're looking at a UNC path name.
  845. //
  846. lpOpkSrcRoot = CharNext(lpOpkSrcRoot);
  847. lpComputerName = lpOpkSrcRoot;
  848. while (*(lpOpkSrcRoot = CharNext(lpOpkSrcRoot)) != CHR_BACKSLASH)
  849. {
  850. if (*lpOpkSrcRoot == NULLCHR)
  851. {
  852. // Parse error: no share name specified.
  853. //
  854. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_NO_SHARE_NAME);
  855. return FALSE;
  856. }
  857. }
  858. // Get the computer name.
  859. //
  860. lstrcpyn(szOpkSrcComputerName, lpComputerName,
  861. (lpOpkSrcRoot - lpComputerName) < AS(szOpkSrcComputerName) ? (INT) (lpOpkSrcRoot - lpComputerName) : AS(szOpkSrcComputerName));
  862. while (*(lpOpkSrcRoot = CharNext(lpOpkSrcRoot)) != CHR_BACKSLASH)
  863. {
  864. if (*lpOpkSrcRoot == NULLCHR)
  865. {
  866. // Parse error: no share name specified.
  867. //
  868. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_NO_SHARE_NAME);
  869. return FALSE;
  870. }
  871. }
  872. // Read credentials from the WinBOM.
  873. //
  874. GetCredentials(szUsername, AS(szUsername), szPassword, AS(szPassword), lpszWinBOMPath, WBOM_WINPE_SECTION);
  875. // Make sure that we're using the guest account if no other account is specified.
  876. //
  877. if ( NULLCHR == szUsername[0] )
  878. lstrcpyn(szUsername, _T("guest"), AS ( szUsername ) );
  879. // lpOpkSrcRoot now points to the backslash following the share name.
  880. // Use this stuff in place. Make sure we set this back to backslash after NetUseAdd is done.
  881. //
  882. *lpOpkSrcRoot = NULLCHR;
  883. // If the user specified a username of the form "domain\username"
  884. // ignore the domain entry and use the one specified here. Otherwise use the domain entry here.
  885. // After this the szUsername variable will always contain a username of the form "domain\username"
  886. // if the domain was specified.
  887. //
  888. if ( (NULL == _tcschr(szUsername, _T('\\'))) && szDomain[0] )
  889. {
  890. // Build the full "domain\username" in szDomain and then copy it back to the szUsername.
  891. //
  892. if ( FAILED ( StringCchCat ( szDomain, AS ( szDomain ), _T("\\")) ) )
  893. {
  894. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szDomain, _T("\\") ) ;
  895. }
  896. if ( FAILED ( StringCchCat ( szDomain, AS ( szDomain ), szUsername) ) )
  897. {
  898. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szDomain, szUsername ) ;
  899. }
  900. lstrcpyn(szUsername, szDomain, AS ( szUsername ) );
  901. }
  902. dwTimeLast = dwTimeStart = GetTickCount();
  903. while ( (nas = ConnectNetworkResource(szOpkSrcRoot, szUsername, szPassword, TRUE) != NERR_Success) &&
  904. (((dwTimeLast = GetTickCount()) - dwTimeStart) < (NET_CONNECT_TIMEOUT * 1000)) )
  905. {
  906. // Wait for half a second to give net services a chance to settle down.
  907. //
  908. Sleep(500);
  909. FacLogFileStr(3, _T("Net connect error: %d"), nas);
  910. }
  911. FacLogFileStr(3, _T("Waited for %d milliseconds to connect to the server."), (dwTimeLast - dwTimeStart));
  912. // If we failed put up the error message and return FALSE.
  913. //
  914. if ( NERR_Success != nas )
  915. {
  916. // Can't authenticate to the server.
  917. //
  918. LPTSTR lpError = NULL;
  919. // Try to get the description of the error.
  920. //
  921. if ( FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, nas, 0, (LPTSTR) &lpError, 0, NULL) == 0 )
  922. lpError = NULL;
  923. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_CANTAUTHSERVER, lpError ? lpError : NULLSTR);
  924. FREE(lpError);
  925. return FALSE;
  926. }
  927. *lpOpkSrcRoot = CHR_BACKSLASH;
  928. }
  929. // Make sure that source and target root directories exist.
  930. //
  931. if (!DirectoryExists(g_szTargetDrive) || !DirectoryExists(szOpkSrcRoot))
  932. {
  933. FacLogFile(0 | LOG_ERR, IDS_ERR_NOSOURCEORTARGET, szOpkSrcRoot, g_szTargetDrive);
  934. bRet = FALSE;
  935. }
  936. lstrcpyn( szSource, szOpkSrcRoot, AS ( szSource ) );
  937. lstrcpyn( szTarget, g_szTargetDrive, AS ( szTarget ) );
  938. lpSource = szSource + lstrlen(szOpkSrcRoot);
  939. cbSource = AS(szSource) - lstrlen(szOpkSrcRoot);
  940. lpTarget = szTarget + lstrlen(g_szTargetDrive);
  941. cbTarget = AS(szTarget) - lstrlen(g_szTargetDrive);
  942. for (i = 0; ( i < AS(g_filesToCopy) ) && bRet; i++)
  943. {
  944. //
  945. // Get the source and target and expand them to the real filenames.
  946. //
  947. if (ExpandStrings(g_filesToCopy[i].szFISourceName, lpSource, cbSource, env, AS(env)) &&
  948. ExpandStrings(g_filesToCopy[i].szFITargetName, lpTarget, cbTarget, env, AS(env)))
  949. {
  950. // Create the directory.
  951. //
  952. TCHAR szFullPath[MAX_PATH] = NULLSTR;
  953. LPTSTR lpFind = NULL;
  954. if (GetFullPathName(szTarget, AS(szFullPath), szFullPath, &lpFind) && szFullPath[0] && lpFind)
  955. {
  956. *lpFind = NULLCHR;
  957. CreatePath(szFullPath);
  958. }
  959. if (g_filesToCopy[i].bDirectory)
  960. {
  961. if (!CopyDirectory(szSource, szTarget) && g_filesToCopy[i].bRequired)
  962. {
  963. FacLogFile(0 | LOG_ERR, IDS_ERR_FAILEDCOPYDIR, szSource);
  964. bRet = FALSE;
  965. }
  966. }
  967. else if (!CopyFile(szSource, szTarget, FALSE) && g_filesToCopy[i].bRequired)
  968. {
  969. FacLogFile(0 | LOG_ERR, IDS_ERR_FAILEDCOPYFILE, szSource);
  970. bRet = FALSE;
  971. }
  972. }
  973. else
  974. {
  975. // Could not expand the strings
  976. //
  977. FacLogFileStr(3 | LOG_ERR, _T("Cannot expand filename string. Filename: %s."), g_filesToCopy[i].szFISourceName);
  978. if (g_filesToCopy[i].bRequired)
  979. {
  980. // Log error here.
  981. //
  982. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_COPYFILE, g_filesToCopy[i].szFISourceName);
  983. bRet = FALSE;
  984. }
  985. }
  986. } // for loop
  987. // Clean up the files that we copied over to the root drive
  988. //
  989. lstrcpyn(szBuffer, g_szTargetDrive, AS ( szBuffer ) );
  990. AddPathN(szBuffer, GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) ? _T("ia64") : _T("i386"), AS(szBuffer));
  991. CleanupSourcesDir(szBuffer);
  992. // Let's start the winnt32 setup here.
  993. //
  994. if (bRet)
  995. {
  996. TCHAR szPreExpand[MAX_PATH] = NULLSTR;
  997. TCHAR szSetup[MAX_PATH] = NULLSTR;
  998. TCHAR szConfig[MAX_PATH] = NULLSTR;
  999. TCHAR szUnattend[MAX_PATH] = NULLSTR;
  1000. TCHAR szCommandLine[MAX_PATH] = NULLSTR;
  1001. DWORD dwExitCode = 0;
  1002. lstrcpyn(szPreExpand, _T("\""), AS ( szPreExpand ) );
  1003. if ( FAILED ( StringCchCat ( szPreExpand, AS ( szPreExpand ), g_szTargetDrive) ) )
  1004. {
  1005. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szPreExpand, g_szTargetDrive ) ;
  1006. }
  1007. if ( GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  1008. {
  1009. if ( FAILED ( StringCchCat ( szPreExpand, AS ( szPreExpand ), _T("ia64\\winnt32.exe\"") ) ) )
  1010. {
  1011. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szPreExpand, _T("ia64\\winnt32.exe\"" ) ) ;
  1012. }
  1013. }
  1014. else
  1015. {
  1016. if ( FAILED ( StringCchCat ( szPreExpand, AS ( szPreExpand ), _T("i386\\winnt32.exe\"") ) ) )
  1017. {
  1018. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szPreExpand, _T("i386\\winnt32.exe\"") );
  1019. }
  1020. }
  1021. if (!ExpandStrings(szPreExpand, szSetup, AS(szSetup), env, AS(env)))
  1022. {
  1023. FacLogFileStr(3 | LOG_ERR, _T("Error expanding winnt32.exe source string: %s"), szPreExpand);
  1024. bRet = FALSE;
  1025. }
  1026. // Need a full path to the config set directory.
  1027. //
  1028. lstrcpyn(szPreExpand, _T("\""), AS ( szPreExpand ) );
  1029. if ( FAILED ( StringCchCat ( szPreExpand, AS ( szPreExpand ), szOpkSrcRoot ) ) )
  1030. {
  1031. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szPreExpand, szOpkSrcRoot ) ;
  1032. }
  1033. if ( FAILED ( StringCchCat ( szPreExpand, AS ( szPreExpand ), _T("cfgsets\\<cfg>\"") ) ) )
  1034. {
  1035. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szPreExpand, _T("cfgsets\\<cfg>\"") ) ;
  1036. }
  1037. if ( !ExpandStrings(szPreExpand, szConfig, AS(szConfig), env, AS(env)) )
  1038. {
  1039. FacLogFileStr(3 | LOG_ERR, _T("Error expanding config set source string: %s"), szPreExpand);
  1040. bRet = FALSE;
  1041. }
  1042. // Setup the full path to the unattend file.
  1043. //
  1044. lstrcpyn(szUnattend, g_szTargetDrive, AS ( szUnattend ) );
  1045. if ( FAILED ( StringCchCat ( szUnattend, AS ( szUnattend ), _T("sysprep\\unattend.txt") ) ) )
  1046. {
  1047. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szUnattend, _T("sysprep\\unattend.txt") ) ;
  1048. }
  1049. // Write the UNC to where the $OEM$ directory is to the unattend we copied local.
  1050. //
  1051. WritePrivateProfileString(_T("Unattended"), _T("OemFilesPath"), szConfig, szUnattend);
  1052. // Set up the command line
  1053. //
  1054. if ( GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  1055. {
  1056. lstrcpyn(szCommandLine, _T("/tempdrive:"), AS ( szCommandLine ) );
  1057. }
  1058. else
  1059. {
  1060. lstrcpyn ( szCommandLine, _T("/syspart:"), AS ( szCommandLine ) );
  1061. }
  1062. if ( FAILED ( StringCchCat ( szCommandLine, AS ( szCommandLine ), g_szTargetDrive ) ) )
  1063. {
  1064. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCommandLine, g_szTargetDrive ) ;
  1065. }
  1066. if ( FAILED ( StringCchCat ( szCommandLine, AS ( szCommandLine ), _T(" /noreboot /unattend:") ) ) )
  1067. {
  1068. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCommandLine, _T(" /noreboot /unattend:") ) ;
  1069. }
  1070. if ( FAILED ( StringCchCat ( szCommandLine, AS ( szCommandLine ), szUnattend ) ) )
  1071. {
  1072. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCommandLine, szUnattend ) ;
  1073. }
  1074. //
  1075. // Check if we need to install from multiple source locations...
  1076. //
  1077. if ( ( 0 == LSTRCMPI(szOptSources, WBOM_YES) ) &&
  1078. FAILED( StringCchCat( szCommandLine, AS(szCommandLine), _T(" /makelocalsource:all") ) ) )
  1079. {
  1080. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCommandLine, _T(" /makelocalsource:all") ) ;
  1081. }
  1082. FacLogFileStr(3, _T("Executing: %s %s\n"), szSetup, szCommandLine);
  1083. if ( !InvokeExternalApplicationEx( szSetup, szCommandLine, &dwExitCode, INFINITE, TRUE ) )
  1084. {
  1085. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_SETUP, szSetup, szCommandLine);
  1086. bRet = FALSE;
  1087. }
  1088. }
  1089. }
  1090. else
  1091. {
  1092. // There was a problem reading one of the variables from the winbom.ini
  1093. // Return TRUE like nothing happened. This basically means that we will not
  1094. // copy down configsets
  1095. //
  1096. FacLogFile(0, IDS_ERR_MISSINGVAR);
  1097. }
  1098. return bRet;
  1099. }
  1100. BOOL DisplayCopyFiles(LPSTATEDATA lpStateData)
  1101. {
  1102. return ( IniSettingExists(lpStateData->lpszWinBOMPath, INI_SEC_WBOM_WINPE, INI_KEY_WBOM_WINPE_LANG, NULL) &&
  1103. IniSettingExists(lpStateData->lpszWinBOMPath, INI_SEC_WBOM_WINPE, INI_KEY_WBOM_WINPE_SKU, NULL) &&
  1104. IniSettingExists(lpStateData->lpszWinBOMPath, INI_SEC_WBOM_WINPE, INI_KEY_WBOM_WINPE_CFGSET, NULL) &&
  1105. IniSettingExists(lpStateData->lpszWinBOMPath, INI_SEC_WBOM_WINPE, INI_KEY_WBOM_WINPE_SRCROOT, NULL) );
  1106. }
  1107. // Concatenates strings and returns a pointer to the end of lpString1. Used for performance
  1108. // whenever lots of strings get appended to a string.
  1109. //
  1110. LPTSTR mylstrcat(LPTSTR lpString1, LPCTSTR lpString2, DWORD dwSize )
  1111. {
  1112. static DWORD dwBufSize = 0;
  1113. if ( dwSize )
  1114. dwBufSize = dwSize;
  1115. // If dwBufSize becomes less than or equal to zero
  1116. // StringCchCat will fail anyway.
  1117. if ( SUCCEEDED ( StringCchCat ( lpString1, dwBufSize, lpString2 ) ) )
  1118. {
  1119. // Get the length of the string
  1120. DWORD dwLen = lstrlen ( lpString1 ) ;
  1121. // Substract the length from the total length
  1122. dwBufSize -= dwLen ;
  1123. return (lpString1 + dwLen );
  1124. }
  1125. else
  1126. {
  1127. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), lpString1, lpString2 ) ;
  1128. }
  1129. return NULL ;
  1130. }
  1131. // Starts diskpart with redirected input and output.
  1132. //
  1133. // ISSUE-2002/02/25-acosma,georgeje - If read pipe fills up we will have deadlock. Possible solution
  1134. // is to create another thread that reads from the readpipe and writes to the debug file. Another
  1135. // possibility is to Create the debug file or NUL device file (dbg and non-dbg versions) and pass
  1136. // that as the process's stdout handle.
  1137. //
  1138. BOOL StartDiskpart(HANDLE *phStdinWrDup, HANDLE *phStdoutRdDup, HANDLE *phStdinRd, HANDLE *phStdoutWr)
  1139. {
  1140. HANDLE hStdinWr = NULL,
  1141. hStdoutRd = NULL;
  1142. SC_HANDLE hSCM;
  1143. SECURITY_ATTRIBUTES saAttr;
  1144. BOOL fSuccess;
  1145. PROCESS_INFORMATION piProcInfo;
  1146. STARTUPINFO siStartInfo;
  1147. TCHAR szDiskpart[20] = NULLSTR;
  1148. BOOL bRet = FALSE;
  1149. // Set the bInheritHandle flag so pipe handles are inherited.
  1150. //
  1151. saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
  1152. saAttr.bInheritHandle = TRUE;
  1153. saAttr.lpSecurityDescriptor = NULL;
  1154. // Start the dmserver service myself, so that diskpart doesn't choke
  1155. // when I start it. In debug mode log the time it took to do this.
  1156. //
  1157. if ( hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS) )
  1158. {
  1159. #ifdef DBG
  1160. DWORD dwTime;
  1161. dwTime = GetTickCount();
  1162. #endif // #ifdef DBG
  1163. // Start the service here. Start my service waits for the service to start.
  1164. // I'm not checking the return status here because diskpart will fail later,
  1165. // if it can't start dmserver and we will fail out when we try to format the
  1166. // drives. This way we have 2 chances to work correctly.
  1167. //
  1168. StartMyService(_T("dmserver"), hSCM);
  1169. #ifdef DBG
  1170. FacLogFileStr(3, _T("Waited for dmserver to start for %d seconds."), (GetTickCount() - dwTime)/1000);
  1171. #endif // #ifdef DBG
  1172. CloseServiceHandle(hSCM);
  1173. }
  1174. else
  1175. {
  1176. FacLogFile(0 | LOG_ERR, IDS_ERR_SCM);
  1177. }
  1178. //
  1179. // The steps for redirecting child process's STDOUT:
  1180. // 1. Create anonymous pipe to be STDOUT for child process.
  1181. // 2. Create a noninheritable duplicate of the read handle and
  1182. // close the inheritable read handle.
  1183. //
  1184. // Create a pipe for the child process's STDOUT.
  1185. //
  1186. // Create noninheritable read handle.
  1187. //
  1188. if ( CreatePipe(&hStdoutRd, phStdoutWr, &saAttr, 0)
  1189. &&
  1190. DuplicateHandle(GetCurrentProcess(), hStdoutRd, GetCurrentProcess(), phStdoutRdDup , 0,
  1191. FALSE, DUPLICATE_SAME_ACCESS) )
  1192. {
  1193. // Close the inheritable read handle.
  1194. //
  1195. CLOSEHANDLE(hStdoutRd);
  1196. // The steps for redirecting child process's STDIN:
  1197. // 1. Create anonymous pipe to be STDIN for child process.
  1198. // 2. Create a noninheritable duplicate of the write handle,
  1199. // and close the inheritable write handle.
  1200. // Create a pipe for the child process's STDIN.
  1201. //
  1202. // Duplicate the write handle to the pipe so it is not inherited.
  1203. //
  1204. if (CreatePipe(phStdinRd, &hStdinWr, &saAttr, 0)
  1205. &&
  1206. DuplicateHandle(GetCurrentProcess(), hStdinWr, GetCurrentProcess(), phStdinWrDup, 0,
  1207. FALSE, DUPLICATE_SAME_ACCESS) )
  1208. {
  1209. // Close the handle so that it is not inherited.
  1210. //
  1211. CLOSEHANDLE(hStdinWr);
  1212. //
  1213. // Now create the child process.
  1214. //
  1215. // Set up members of the PROCESS_INFORMATION structure.
  1216. //
  1217. ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
  1218. // Set up members of the STARTUPINFO structure.
  1219. //
  1220. ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
  1221. siStartInfo.cb = sizeof(STARTUPINFO);
  1222. siStartInfo.dwFlags = STARTF_USESTDHANDLES;
  1223. siStartInfo.hStdInput = *phStdinRd;
  1224. siStartInfo.hStdOutput = *phStdoutWr;
  1225. siStartInfo.hStdError = *phStdoutWr;
  1226. // siStartInfo.wShowWindow = SW_HIDE;
  1227. // Create the child process (DISKPART)
  1228. //
  1229. lstrcpyn(szDiskpart, _T("diskpart"), AS ( szDiskpart ) );
  1230. if (CreateProcess(NULL,
  1231. szDiskpart, // command line
  1232. NULL, // process security attributes
  1233. NULL, // primary thread security attributes
  1234. TRUE, // handles are inherited
  1235. CREATE_NO_WINDOW, // creation flags - do no show diskpart console
  1236. NULL, // use parent's environment
  1237. NULL, // use parent's current directory
  1238. &siStartInfo, // STARTUPINFO pointer
  1239. &piProcInfo)) // receives PROCESS_INFORMATION
  1240. {
  1241. CLOSEHANDLE(piProcInfo.hThread);
  1242. CLOSEHANDLE(piProcInfo.hProcess);
  1243. bRet = TRUE;
  1244. }
  1245. else
  1246. FacLogFile(0 | LOG_ERR, IDS_ERR_CREATEPROCESS);
  1247. }
  1248. else
  1249. FacLogFile(0 | LOG_ERR, IDS_ERR_CREATESTDIN);
  1250. }
  1251. else
  1252. FacLogFile(0 | LOG_ERR, IDS_ERR_CREATESTDOUT);
  1253. CLOSEHANDLE(hStdinWr);
  1254. CLOSEHANDLE(hStdoutRd);
  1255. return bRet;
  1256. }
  1257. BOOL ProcessDiskConfigSection(LPTSTR lpszWinBOMPath)
  1258. {
  1259. TCHAR szDisks[BUFSIZE] = NULLSTR;
  1260. LPTSTR lpDisk;
  1261. TCHAR szSectionBuffer[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1262. BOOL bRet = TRUE;
  1263. UINT uiDiskNumber = 0;
  1264. DWORD numPartitions = 0;
  1265. BOOL bWipeDisk = FALSE;
  1266. GetPrivateProfileString(INI_SEC_WBOM_DISKCONFIG, NULL, NULLSTR, szDisks, AS(szDisks), lpszWinBOMPath);
  1267. if (szDisks[0])
  1268. {
  1269. // Get the Section names. Process each disk section.
  1270. //
  1271. for (lpDisk = szDisks; *lpDisk; lpDisk += (lstrlen(lpDisk) + 1))
  1272. {
  1273. LPTSTR lpDiskID = NULL;
  1274. numPartitions = 0;
  1275. GetPrivateProfileString(INI_SEC_WBOM_DISKCONFIG,
  1276. lpDisk,
  1277. NULLSTR,
  1278. szSectionBuffer,
  1279. AS(szSectionBuffer),
  1280. lpszWinBOMPath);
  1281. // Make sure that the disk number is specified.
  1282. // Skip over the first 4 characters which should be "Disk", and point
  1283. // to the first digit in the disk number.
  1284. //
  1285. lpDiskID = lpDisk + 4;
  1286. if ( szSectionBuffer[0] && (uiDiskNumber = (UINT) _wtoi(lpDiskID)) )
  1287. {
  1288. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1289. // See if WipeDisk is set for this disk. On IA64 wipe by default.
  1290. //
  1291. GetPrivateProfileString(szSectionBuffer,
  1292. WBOM_DISK_CONFIG_WIPE_DISK,
  1293. NULLSTR,
  1294. szBuf,
  1295. AS(szBuf),
  1296. lpszWinBOMPath);
  1297. if ( 0 == LSTRCMPI(szBuf, WBOM_YES) )
  1298. bWipeDisk = TRUE;
  1299. else if ( (0 != LSTRCMPI(szBuf, WBOM_NO)) && (GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE)) )
  1300. bWipeDisk = TRUE;
  1301. GetNumberOfPartitions(uiDiskNumber - 1, &numPartitions);
  1302. if ( 0 == numPartitions || bWipeDisk )
  1303. ProcessDisk(uiDiskNumber, szSectionBuffer, lpszWinBOMPath, bWipeDisk);
  1304. // If we're working on disk 0 (DiskID = 1) format the C drive.
  1305. //
  1306. else if ( 1 == uiDiskNumber )
  1307. if ( !JustFormatC(lpszWinBOMPath, szSectionBuffer) )
  1308. bRet = FALSE;
  1309. // else just ignore the disk :).
  1310. }
  1311. else
  1312. {
  1313. FacLogFile(0 | LOG_ERR, IDS_ERR_DISKCFGENTRY, lpDisk);
  1314. bRet = FALSE;
  1315. }
  1316. }
  1317. if ( g_PartList )
  1318. {
  1319. // If no partitions on disk 0 were set active,
  1320. // set the first PRIMARY partition on the disk active.
  1321. // pFirst variable will maintain a pointer to the first PRIMARY partition
  1322. // on the disk.
  1323. //
  1324. BOOL bActive = FALSE;
  1325. PPARTITION pFirst = NULL; // for the next block this will point to the first PRIMARY partition on disk 0.
  1326. PPARTITION pCur = NULL;
  1327. for ( pCur = g_PartList; pCur && 0 == pCur->uiDiskID; pCur = pCur->pNext )
  1328. {
  1329. if ( ptPrimary == pCur->uiPartitionType )
  1330. {
  1331. if ( !pFirst )
  1332. pFirst = pCur;
  1333. if ( pCur->bSetActive )
  1334. {
  1335. bActive = TRUE;
  1336. break;
  1337. }
  1338. }
  1339. }
  1340. if ( !bActive && pFirst )
  1341. pFirst->bSetActive = TRUE;
  1342. //
  1343. // If we're on IA64 do a check to see if user specified EFI and MSR partitions
  1344. // for each drive. If not add them in automatically.
  1345. //
  1346. if ( GET_FLAG(g_dwFactoryFlags, FLAG_IA64_MODE) )
  1347. {
  1348. PPARTITION pLastLast = NULL;
  1349. PPARTITION pLast = NULL;
  1350. BOOL bMsr = FALSE;
  1351. BOOL bEfi = FALSE;
  1352. // pCur is the iterator and pLast will be pointing
  1353. // to the element previous to pCur. pLastLast will point to the last element of the
  1354. // previous disk.
  1355. //
  1356. for ( pCur = g_PartList; pCur; pCur = pCur->pNext )
  1357. { // We're on the same disk.
  1358. //
  1359. if ( !pLast || pCur->uiDiskID == pLast->uiDiskID )
  1360. {
  1361. if ( ptMsr == pCur->uiPartitionType )
  1362. bMsr = TRUE;
  1363. if ( ptEfi == pCur->uiPartitionType )
  1364. bEfi = TRUE;
  1365. }
  1366. else
  1367. { // Just moved on to a new disk. If Msr and Efi were not found on previous disk make them!
  1368. //
  1369. AddMsrAndEfi(bMsr, bEfi, pLastLast, pLast->uiDiskID, bWipeDisk);
  1370. // Re-init these for the next disk.
  1371. //
  1372. bEfi = bMsr = FALSE;
  1373. pLastLast = pLast;
  1374. }
  1375. pLast = pCur;
  1376. }
  1377. // Do this for the special case when we are at the end of the list.
  1378. //
  1379. AddMsrAndEfi(bMsr, bEfi, pLastLast, pLast->uiDiskID, bWipeDisk);
  1380. }
  1381. }
  1382. }
  1383. return bRet;
  1384. }
  1385. #define GO if ( szBuf[0] ) bGo = TRUE
  1386. BOOL ProcessDisk(UINT diskID, LPTSTR lpSectionName, LPTSTR lpszWinBOMPath, BOOL bWipeDisk)
  1387. {
  1388. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1389. TCHAR szKey[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1390. BOOL bGo = TRUE;
  1391. UINT i = 1;
  1392. PPARTITION pLast = NULL;
  1393. PPARTITION pCur = NULL;
  1394. // Need pLast to point to the last element in the list.
  1395. // Go through the list until we find the last element.
  1396. //
  1397. for (pCur = g_PartList; pCur; pCur = pCur->pNext)
  1398. {
  1399. pLast = pCur;
  1400. }
  1401. // Loop will be interrupted when a SizeN key no longer exists. (N is i and grows with each iteration).
  1402. //
  1403. while (bGo)
  1404. {
  1405. // Initialize this to not continue.
  1406. //
  1407. bGo = FALSE;
  1408. // The MALLOC macro gives us blanked out memory, so that we don't have to initialize
  1409. // the pNext pointer to NULL. pCur is now used to point to the new node that we create.
  1410. //
  1411. if ( pCur = (PPARTITION) MALLOC( sizeof(PARTITION) ) )
  1412. {
  1413. // Size
  1414. //
  1415. Build(szKey, AS ( szKey ), i, DCS_SIZE);
  1416. GetPrivateProfileString(lpSectionName, szKey, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  1417. GO;
  1418. if ( szBuf[0] )
  1419. {
  1420. if ( !lstrcmpi(szBuf, _T("*")) )
  1421. pCur->ullSize = 0;
  1422. else
  1423. // In case number cannot be converted to integer 0 will be returned.
  1424. // This is OK.
  1425. pCur->ullSize = _ttoi(szBuf);
  1426. }
  1427. // WipeDisk
  1428. //
  1429. pCur->bWipeDisk = bWipeDisk;
  1430. // QuickFormat
  1431. //
  1432. Build(szKey, AS ( szKey ), i, DCS_QUICK_FORMAT);
  1433. GetPrivateProfileString(lpSectionName, szKey, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  1434. GO;
  1435. if ( szBuf[0] && !LSTRCMPI(szBuf, WBOM_NO) )
  1436. pCur->bQuickFormat = FALSE;
  1437. else
  1438. pCur->bQuickFormat = TRUE;
  1439. // SetActive
  1440. //
  1441. Build(szKey, AS ( szKey ), i, DCS_SET_ACTIVE);
  1442. GetPrivateProfileString(lpSectionName, szKey, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  1443. GO;
  1444. if ( !LSTRCMPI(szBuf, WBOM_YES) )
  1445. pCur->bSetActive = TRUE;
  1446. else
  1447. pCur->bSetActive = FALSE;
  1448. // FileSystem
  1449. //
  1450. Build(szKey, AS ( szKey ), i, DCS_FILE_SYSTEM);
  1451. GetPrivateProfileString(lpSectionName, szKey, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  1452. GO;
  1453. if ( !LSTRCMPI(szBuf, _T("FAT32")) || !LSTRCMPI(szBuf, _T("FAT")) )
  1454. pCur->uiFileSystem = fsFat32;
  1455. else if ( !LSTRCMPI(szBuf, _T("FAT16")) )
  1456. pCur->uiFileSystem = fsFat;
  1457. else
  1458. pCur->uiFileSystem = fsNtfs;
  1459. // Partition Type
  1460. //
  1461. Build(szKey, AS ( szKey ), i, DCS_PARTITION_TYPE);
  1462. GetPrivateProfileString(lpSectionName, szKey, NULLSTR, szBuf, AS(szBuf), lpszWinBOMPath);
  1463. GO;
  1464. if ( !lstrcmpi(szBuf, DCPARTITION_EXTENDED) )
  1465. pCur->uiPartitionType = ptExtended;
  1466. else if ( !lstrcmpi(szBuf, DCPARTITION_LOGICAL) )
  1467. pCur->uiPartitionType = ptLogical;
  1468. else if ( !lstrcmpi(szBuf, DCPARTITION_MSR) )
  1469. {
  1470. pCur->uiPartitionType = ptMsr;
  1471. }
  1472. else if ( !lstrcmpi(szBuf, DCPARTITION_EFI) )
  1473. {
  1474. pCur->uiPartitionType = ptEfi;
  1475. pCur->uiFileSystem = fsFat32;
  1476. }
  1477. else
  1478. pCur->uiPartitionType = ptPrimary;
  1479. // DiskID
  1480. //
  1481. // Note: -1 is because in the winBOM the diskID is 1 based while Diskpart has it 0-based.
  1482. //
  1483. pCur->uiDiskID = diskID - 1;
  1484. // Deal with the linked list some more.
  1485. //
  1486. if ( bGo )
  1487. {
  1488. // Build the linked list.
  1489. //
  1490. if ( pLast )
  1491. pLast->pNext = pCur;
  1492. else
  1493. g_PartList = pCur;
  1494. pLast = pCur;
  1495. }
  1496. else
  1497. { // If we didn't find any entries for this partition it means that we're done.
  1498. // FREE up the current node.
  1499. //
  1500. FREE(pCur);
  1501. }
  1502. } // if
  1503. i++;
  1504. } // while
  1505. return TRUE;
  1506. }
  1507. VOID AddMsrAndEfi(BOOL bMsr, BOOL bEfi, PPARTITION pLastLast, UINT uiDiskID, BOOL bWipeDisk)
  1508. {
  1509. PPARTITION pNew = NULL;
  1510. if ( !bMsr )
  1511. {
  1512. if ( pNew = (PPARTITION) MALLOC( sizeof(PARTITION) ) )
  1513. {
  1514. pNew->uiDiskID = uiDiskID;
  1515. pNew->ullSize = GetDiskMSRSizeMB(uiDiskID);
  1516. pNew->uiPartitionType = ptMsr;
  1517. pNew->bWipeDisk = bWipeDisk;
  1518. // Do a check to see if EFI partition is already there.
  1519. // If it is, then insert the msr partition after it..not before!.
  1520. //
  1521. if ( pLastLast)
  1522. {
  1523. if ( (pLastLast->pNext) && (ptEfi == pLastLast->pNext->uiPartitionType) && (uiDiskID == pLastLast->pNext->uiDiskID) )
  1524. ListInsert(pLastLast->pNext, pNew);
  1525. else
  1526. ListInsert(pLastLast, pNew);
  1527. }
  1528. else
  1529. {
  1530. if ( (ptEfi == g_PartList->uiPartitionType) && (uiDiskID == g_PartList->uiDiskID) )
  1531. ListInsert(g_PartList, pNew);
  1532. else
  1533. ListInsert(NULL, pNew);
  1534. }
  1535. }
  1536. }
  1537. if ( (uiDiskID == 0) && (!bEfi) )
  1538. {
  1539. if ( pNew = (PPARTITION) MALLOC( sizeof(PARTITION) ) )
  1540. {
  1541. pNew->uiDiskID = uiDiskID;
  1542. pNew->ullSize = GetDiskEFISizeMB(uiDiskID);
  1543. pNew->uiPartitionType = ptEfi;
  1544. pNew->uiFileSystem = fsFat32;
  1545. pNew->bQuickFormat = TRUE;
  1546. pNew->bWipeDisk = bWipeDisk;
  1547. ListInsert(pLastLast, pNew);
  1548. }
  1549. }
  1550. }
  1551. BOOL Build(LPTSTR lpKey, DWORD dwSize, UINT diskID, LPCTSTR lpKeyName)
  1552. {
  1553. // szBuf is 33 TCHARs since docs for _itot say this is the max size that it will fill.
  1554. //
  1555. TCHAR szBuf[33] = NULLSTR;
  1556. _itot(diskID, szBuf, 10);
  1557. if (!szBuf[0])
  1558. return FALSE;
  1559. lstrcpyn ( lpKey, lpKeyName, dwSize );
  1560. if ( FAILED ( StringCchCat ( lpKey, dwSize, szBuf) ) )
  1561. {
  1562. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), lpKey, szBuf ) ;
  1563. }
  1564. return TRUE;
  1565. }
  1566. BOOL FormatPartitions(VOID)
  1567. {
  1568. TCHAR szCmdLine[MAX_PATH] = NULLSTR;
  1569. BOOL bRet = TRUE;
  1570. DWORD dwExitCode = 0;
  1571. PPARTITION pCur = NULL;
  1572. for (pCur = g_PartList; pCur; pCur = pCur->pNext )
  1573. {
  1574. if ( (ptExtended != pCur->uiPartitionType) && (ptMsr != pCur->uiPartitionType) )
  1575. {
  1576. szCmdLine[0] = pCur->cDriveLetter;
  1577. szCmdLine[1] = _T(':'); // Colon.
  1578. szCmdLine[2] = NULLCHR;
  1579. if (fsFat32 == pCur->uiFileSystem)
  1580. {
  1581. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T(" /fs:fat32")) ) )
  1582. {
  1583. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T(" /fs:fat32") ) ;
  1584. }
  1585. }
  1586. else if (fsFat == pCur->uiFileSystem)
  1587. {
  1588. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T(" /fs:fat")) ) )
  1589. {
  1590. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T(" /fs:fat") ) ;
  1591. }
  1592. }
  1593. else
  1594. {
  1595. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T(" /fs:ntfs")) ) )
  1596. {
  1597. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T(" /fs:ntfs") ) ;
  1598. }
  1599. }
  1600. if (pCur->bQuickFormat)
  1601. {
  1602. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T(" /q")) ) )
  1603. {
  1604. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T(" /q") ) ;
  1605. }
  1606. }
  1607. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T(" /y")) ) )
  1608. {
  1609. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T(" /y") ) ;
  1610. }
  1611. FacLogFileStr(3 | LOG_TIME, _T("Starting to format %c:."), pCur->cDriveLetter);
  1612. if (InvokeExternalApplicationEx(_T("format.com"), szCmdLine, &dwExitCode, INFINITE, TRUE))
  1613. {
  1614. if (!dwExitCode)
  1615. {
  1616. FacLogFileStr(3 | LOG_TIME, _T("Finished formatting drive %c:."), pCur->cDriveLetter);
  1617. }
  1618. else
  1619. {
  1620. // Log error here.
  1621. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_FORMATFAILED, pCur->cDriveLetter);
  1622. bRet = FALSE;
  1623. }
  1624. }
  1625. else
  1626. {
  1627. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_NOFORMAT);
  1628. bRet = FALSE;
  1629. }
  1630. }
  1631. } // for loop
  1632. return bRet;
  1633. }
  1634. BOOL JustFormatC(LPTSTR lpszWinBOMPath, LPTSTR lpszSectionBuffer)
  1635. {
  1636. TCHAR szFileSystemNameBuffer[128] = NULLSTR;
  1637. TCHAR szCmdLine[MAX_PATH] = NULLSTR;
  1638. DWORD dwExitCode = 0;
  1639. BOOL bForceFormat = FALSE;
  1640. BOOL bRet = TRUE;
  1641. TCHAR szScratch[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1642. HANDLE hFile = NULL;
  1643. WIN32_FIND_DATA fileInfo;
  1644. GetPrivateProfileString(lpszSectionBuffer, WBOM_WINPE_FORCE_FORMAT, WBOM_NO, szScratch, MAX_WINPE_PROFILE_STRING, lpszWinBOMPath);
  1645. if (0 == LSTRCMPI(szScratch, WBOM_YES))
  1646. bForceFormat = TRUE;
  1647. if ( !bForceFormat && (hFile = FindFirstFile(_T("C:\\*.*"), &fileInfo)) != INVALID_HANDLE_VALUE )
  1648. {
  1649. // Files found on C:\. Not good. Ask the user what to do.
  1650. //
  1651. FindClose(hFile);
  1652. if ( GET_FLAG(g_dwFactoryFlags, FLAG_QUIET_MODE) ||
  1653. (IDYES != MsgBox(NULL, IDS_MSG_FILESEXIST, IDS_APPNAME, MB_YESNO | MB_ICONQUESTION | MB_DEFBUTTON2 | MB_SETFOREGROUND))
  1654. )
  1655. {
  1656. FacLogFile(0 | LOG_ERR, IDS_ERR_FILEFOUNDONC);
  1657. bRet = FALSE;
  1658. }
  1659. }
  1660. if (bRet)
  1661. {
  1662. // Make sure that we format the disk with whatever the current format is. If the disk is currently
  1663. // formatted .
  1664. //
  1665. if ( GetVolumeInformation(_T("C:\\"), NULL, 0, NULL, NULL, NULL, szFileSystemNameBuffer, AS(szFileSystemNameBuffer)) &&
  1666. szFileSystemNameBuffer[0] && (0 != LSTRCMPI(szFileSystemNameBuffer, _T("RAW"))) )
  1667. {
  1668. // There is a known filesystem on here and format will format with
  1669. // the existing filesystem.
  1670. //
  1671. lstrcpyn(szCmdLine, _T("C: /y /q"), AS ( szCmdLine ));
  1672. }
  1673. else
  1674. {
  1675. // The drive is not formatted. So by default format it NTFS.
  1676. //
  1677. if ( FAILED ( StringCchCat ( szCmdLine, AS ( szCmdLine ), _T("C: /fs:ntfs /y /q")) ) )
  1678. {
  1679. FacLogFileStr(3, _T("StringCchCat failed %s %s\n"), szCmdLine, _T("C: /fs:ntfs /y /q") ) ;
  1680. }
  1681. }
  1682. // Format
  1683. //
  1684. FacLogFileStr(3, _T("format.com %s\n"), szCmdLine);
  1685. if (InvokeExternalApplicationEx(_T("format.com"), szCmdLine, &dwExitCode, INFINITE, TRUE))
  1686. {
  1687. if (dwExitCode)
  1688. { // Log error here.
  1689. FacLogFile(0 | LOG_ERR, IDS_ERR_FORMATFAILED, _T('C'));
  1690. bRet = FALSE;
  1691. }
  1692. }
  1693. else
  1694. {
  1695. FacLogFile(0 | LOG_ERR | LOG_MSG_BOX, IDS_ERR_NOFORMAT);
  1696. }
  1697. }
  1698. return bRet;
  1699. }
  1700. ULONGLONG GetDiskSizeMB(UINT uiDiskNumber)
  1701. {
  1702. HANDLE hDevice = NULL;
  1703. TCHAR buffer[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1704. DISK_GEOMETRY DiskGeometry;
  1705. ULONGLONG ullDiskSizeMB = 0;
  1706. DWORD dwNumBytes = 0;
  1707. ZeroMemory( &DiskGeometry, sizeof(DiskGeometry) );
  1708. // Open a handle to the disk specified and get its geometry.
  1709. //
  1710. lstrcpyn(buffer, _T("\\\\.\\PHYSICALDRIVE"), AS ( buffer ) );
  1711. _itot(uiDiskNumber, buffer + lstrlen(buffer), 10);
  1712. hDevice = CreateFile(buffer,
  1713. 0,
  1714. 0,
  1715. NULL,
  1716. OPEN_EXISTING,
  1717. FILE_ATTRIBUTE_NORMAL,
  1718. NULL);
  1719. if (hDevice == INVALID_HANDLE_VALUE)
  1720. {
  1721. FacLogFileStr(0 | LOG_ERR, _T("DEBUG::Cannot open %s.\n"), buffer);
  1722. return 0;
  1723. }
  1724. if ( DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &DiskGeometry, sizeof(DiskGeometry), &dwNumBytes, NULL ) )
  1725. {
  1726. ullDiskSizeMB = ( DiskGeometry.BytesPerSector * DiskGeometry.SectorsPerTrack *
  1727. DiskGeometry.TracksPerCylinder * DiskGeometry.Cylinders.QuadPart ) / ( 1024 * 1024 );
  1728. }
  1729. else
  1730. {
  1731. FacLogFileStr(0 | LOG_ERR, _T("Error getting disk geometry.\n"));
  1732. }
  1733. CLOSEHANDLE(hDevice);
  1734. return ullDiskSizeMB;
  1735. }
  1736. // Get the number of partitions on disk DiskNumber
  1737. BOOL GetNumberOfPartitions(UINT uiDiskNumber, PDWORD numPartitions)
  1738. {
  1739. HANDLE hDevice = NULL;
  1740. BOOL bResult;
  1741. PDRIVE_LAYOUT_INFORMATION DriveLayout = NULL;
  1742. DWORD dwDriveLayoutSize;
  1743. DWORD dwDataSize = 0;
  1744. DWORD dwNumPart = 0;
  1745. TCHAR buffer[MAX_PATH] = NULLSTR;
  1746. UINT i;
  1747. lstrcpyn(buffer, _T("\\\\.\\PHYSICALDRIVE"), AS ( buffer ) );
  1748. _itot(uiDiskNumber, buffer + lstrlen(buffer), 10);
  1749. hDevice = CreateFile(buffer,
  1750. GENERIC_READ,
  1751. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1752. NULL,
  1753. OPEN_EXISTING,
  1754. FILE_ATTRIBUTE_NORMAL,
  1755. NULL);
  1756. if (hDevice == INVALID_HANDLE_VALUE) // we can't open the drive
  1757. {
  1758. return FALSE;
  1759. }
  1760. //
  1761. // Get partition information.
  1762. //
  1763. dwDriveLayoutSize = 1024;
  1764. do {
  1765. if ( !DriveLayout && !(DriveLayout = MALLOC(1024)) )
  1766. {
  1767. CLOSEHANDLE(hDevice);
  1768. return FALSE;
  1769. }
  1770. else
  1771. {
  1772. PDRIVE_LAYOUT_INFORMATION lpTmpDriveLayout;
  1773. dwDriveLayoutSize += 1024;
  1774. lpTmpDriveLayout = REALLOC(DriveLayout, dwDriveLayoutSize);
  1775. if ( !lpTmpDriveLayout )
  1776. {
  1777. FREE(DriveLayout);
  1778. CLOSEHANDLE(hDevice);
  1779. return FALSE;
  1780. }
  1781. else
  1782. {
  1783. DriveLayout = lpTmpDriveLayout;
  1784. }
  1785. }
  1786. bResult = DeviceIoControl(
  1787. hDevice,
  1788. IOCTL_DISK_GET_DRIVE_LAYOUT,
  1789. NULL,
  1790. 0,
  1791. DriveLayout,
  1792. dwDriveLayoutSize,
  1793. &dwDataSize,
  1794. NULL
  1795. );
  1796. } while (!bResult && (GetLastError() == ERROR_INSUFFICIENT_BUFFER));
  1797. if (!bResult)
  1798. return FALSE;
  1799. for (i = 0; i < (DriveLayout)->PartitionCount; i++)
  1800. {
  1801. PPARTITION_INFORMATION PartInfo = DriveLayout->PartitionEntry + i;
  1802. //
  1803. // ISSUE-2002/02/25-acosma,georgeje - Add in all the IA64 stuff below.
  1804. //
  1805. //
  1806. // IOCTL_DISK_GET_DRIVE_LAYOUT_EX may return us a list of entries that
  1807. // are not used, so ignore these partitions.
  1808. //
  1809. if (// if its partition 0, which indicates whole disk
  1810. // (SPPT_IS_GPT_DISK(DiskNumber) && (PartInfo->PartitionNumber == 0)) ||
  1811. // (PartInfo->PartitionLength.QuadPart == 0) ||
  1812. // if MBR entry not used or length is zero
  1813. // ((DriveLayout->PartitionStyle == PARTITION_STYLE_MBR) &&
  1814. (PartInfo->PartitionType == PARTITION_ENTRY_UNUSED) &&
  1815. (PartInfo->PartitionLength.QuadPart == 0))
  1816. // if unknown/unused GPT partition
  1817. // || ((DriveLayout->PartitionStyle == PARTITION_STYLE_GPT) &&
  1818. // (!memcmp(&PartInfo->Gpt.PartitionType,
  1819. // &PARTITION_ENTRY_UNUSED_GUID, sizeof(GUID)))))
  1820. {
  1821. continue;
  1822. }
  1823. dwNumPart++;
  1824. }
  1825. *numPartitions = dwNumPart;
  1826. return TRUE;
  1827. }
  1828. BOOL WinpeReboot(LPSTATEDATA lpStateData)
  1829. {
  1830. LPTSTR lpszWinBOMPath = lpStateData->lpszWinBOMPath;
  1831. BOOL bRet = TRUE;
  1832. TCHAR szScratch[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1833. DWORD dwSystemAction = UINT_MAX; // UINT_MAX means do nothing.
  1834. // Enable the SE_SHUTDOWN_NAME privilege. Need this for the call to NtShutdownSystem
  1835. // to succeed.
  1836. //
  1837. EnablePrivilege(SE_SHUTDOWN_NAME,TRUE);
  1838. // Get the winbom setting and do what they want.
  1839. //
  1840. GetPrivateProfileString(WBOM_WINPE_SECTION, INI_KEY_WBOM_WINPE_RESTART, NULLSTR, szScratch, AS(szScratch), lpszWinBOMPath);
  1841. if ( ( szScratch[0] == NULLCHR ) ||
  1842. ( LSTRCMPI(szScratch, INI_VAL_WBOM_WINPE_PROMPT) == 0 ) )
  1843. {
  1844. // "Prompt" or default if missing is prompt for reboot, shutdown, poweroff or cancel.
  1845. //
  1846. dwSystemAction = (DWORD) DialogBox(g_hInstance, MAKEINTRESOURCE(IDD_SHUTDOWN), NULL, ShutdownDlgProc);
  1847. if ( UINT_MAX != dwSystemAction )
  1848. NtShutdownSystem(dwSystemAction);
  1849. else
  1850. bRet = FALSE;
  1851. }
  1852. else if ( LSTRCMPI(szScratch, INI_VAL_WBOM_WINPE_REBOOT) == 0 )
  1853. {
  1854. // "Reboot" to reboot.
  1855. //
  1856. NtShutdownSystem(ShutdownReboot);
  1857. }
  1858. else if ( LSTRCMPI(szScratch, INI_VAL_WBOM_WINPE_SHUTDOWN) == 0 )
  1859. {
  1860. // "Shutdown" to shutdown.
  1861. //
  1862. NtShutdownSystem(ShutdownNoReboot);
  1863. }
  1864. else if ( LSTRCMPI(szScratch, INI_VAL_WBOM_WINPE_POWEROFF) == 0 )
  1865. {
  1866. // "Shutdown" to shutdown.
  1867. //
  1868. NtShutdownSystem(ShutdownPowerOff);
  1869. }
  1870. else if ( LSTRCMPI(szScratch, INI_VAL_WBOM_WINPE_IMAGE) == 0 )
  1871. {
  1872. // "Image" to display a ready to image prompt and shutdown after
  1873. // they press ok.
  1874. //
  1875. if ( IDOK == MsgBox(NULL, IDS_PROMPT_IMAGE, IDS_APPNAME, MB_OKCANCEL | MB_ICONINFORMATION | MB_SETFOREGROUND) )
  1876. {
  1877. // Need to shutdown now.
  1878. //
  1879. NtShutdownSystem(ShutdownPowerOff);
  1880. }
  1881. else
  1882. {
  1883. // If they pressed cancel, then don't shutdown... just exit and do nothing.
  1884. //
  1885. bRet = FALSE;
  1886. }
  1887. }
  1888. else // if ( lstrcmpi(szScratch, INI_VAL_WBOM_WINPE_NONE) == 0 )
  1889. {
  1890. // "None" or unrecognized we should just exit and do nothing.
  1891. //
  1892. // No need to actually check for the none string unless we later
  1893. // decide that we want to do something different than nothing when
  1894. // there is an unrecognized string used for the restart setting.
  1895. //
  1896. // But we should document that you shoud use none if you don't
  1897. // want to reboot, shutdown, or prompt.
  1898. //
  1899. bRet = FALSE;
  1900. }
  1901. return bRet;
  1902. }
  1903. INT_PTR CALLBACK ShutdownDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1904. {
  1905. UINT SystemAction = UINT_MAX;
  1906. switch (msg)
  1907. {
  1908. case WM_INITDIALOG:
  1909. // Initialize the combo box.
  1910. {
  1911. HWND hCombo = NULL;
  1912. TCHAR szBuf[MAX_WINPE_PROFILE_STRING] = NULLSTR;
  1913. if (hCombo = GetDlgItem(hwnd, IDC_SHUTDOWN)) {
  1914. LRESULT ret = 0;
  1915. if ( LoadString(g_hInstance, IDS_SHUTDOWN_TURNOFF, szBuf, AS(szBuf)) &&
  1916. (ret = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szBuf)) != CB_ERR )
  1917. SendMessage(hCombo, CB_SETITEMDATA, ret, (LPARAM) ShutdownPowerOff);
  1918. if ( LoadString(g_hInstance, IDS_SHUTDOWN_SHUTDOWN, szBuf, AS(szBuf)) &&
  1919. (ret = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szBuf)) != CB_ERR )
  1920. SendMessage(hCombo, CB_SETITEMDATA, ret, (LPARAM) ShutdownNoReboot);
  1921. if ( LoadString(g_hInstance, IDS_SHUTDOWN_REBOOT, szBuf, AS(szBuf)) &&
  1922. (ret = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szBuf)) != CB_ERR )
  1923. SendMessage(hCombo, CB_SETITEMDATA, ret, (LPARAM) ShutdownReboot);
  1924. if ( LoadString(g_hInstance, IDS_SHUTDOWN_NOTHING, szBuf, AS(szBuf)) &&
  1925. (ret = SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szBuf)) != CB_ERR )
  1926. SendMessage(hCombo, CB_SETITEMDATA, ret, (LPARAM) UINT_MAX);
  1927. // By default select the reboot option.
  1928. SendMessage(hCombo, CB_SETCURSEL, (WPARAM) 2, 0);
  1929. }
  1930. }
  1931. SetForegroundWindow(hwnd);
  1932. break;
  1933. case WM_COMMAND:
  1934. switch (wParam)
  1935. {
  1936. HWND hCombo = NULL;
  1937. case IDOK:
  1938. if (hCombo = GetDlgItem(hwnd, IDC_SHUTDOWN)) {
  1939. SystemAction = (UINT) SendMessage(hCombo, CB_GETITEMDATA, (SendMessage(hCombo, CB_GETCURSEL, 0, 0)), 0);
  1940. }
  1941. EndDialog(hwnd, SystemAction);
  1942. break;
  1943. case IDCANCEL:
  1944. EndDialog(hwnd, UINT_MAX);
  1945. break;
  1946. default:
  1947. break;
  1948. }
  1949. break;
  1950. default:
  1951. break;
  1952. }
  1953. return FALSE;
  1954. }
  1955. // Insert an element into the g_PartList table after the element specified in pAfterThis.
  1956. //
  1957. VOID ListInsert(PPARTITION pAfterThis, PPARTITION pNew)
  1958. {
  1959. if ( pNew )
  1960. {
  1961. if ( pAfterThis )
  1962. {
  1963. pNew->pNext = pAfterThis->pNext;
  1964. pAfterThis->pNext = pNew;
  1965. }
  1966. else
  1967. {
  1968. pNew->pNext = g_PartList;
  1969. g_PartList = pNew;
  1970. }
  1971. }
  1972. }
  1973. // Free the list.
  1974. //
  1975. VOID ListFree(PPARTITION pList)
  1976. {
  1977. while (pList)
  1978. {
  1979. PPARTITION pTemp = pList;
  1980. pList = pList->pNext;
  1981. FREE(pTemp);
  1982. }
  1983. }
  1984. BOOL
  1985. IsRemoteBoot(
  1986. VOID
  1987. )
  1988. /*++
  1989. Routine Description:
  1990. Finds out if we are currently running on NT booted remotely.
  1991. Arguments:
  1992. None.
  1993. Return value:
  1994. TRUE if this is a remote boot otherwise FALSE.
  1995. --*/
  1996. {
  1997. static BOOL Result = FALSE;
  1998. static BOOL Initialized = FALSE;
  1999. if (!Initialized) {
  2000. TCHAR WindowsDir[MAX_PATH] = {0};
  2001. Initialized = TRUE;
  2002. if (GetWindowsDirectory(WindowsDir, sizeof(WindowsDir)/sizeof(TCHAR))) {
  2003. WindowsDir[3] = 0;
  2004. //
  2005. // If the drive type is DRIVE_REMOTE then we have booted from
  2006. // network.
  2007. //
  2008. Result = (GetDriveType(WindowsDir) == DRIVE_REMOTE);
  2009. }
  2010. }
  2011. return Result;
  2012. }
  2013. //
  2014. // NOTE : DON'T change this value without changing the
  2015. // value in registry also (winpesys.inf)
  2016. //
  2017. static DWORD PnpSeed = 0x1B7D38EA;
  2018. VOID
  2019. pSetCodeSigningPolicy(
  2020. IN CODESIGNING_POLICY_TYPE PolicyType,
  2021. IN BYTE NewPolicy,
  2022. OUT PBYTE OldPolicy OPTIONAL
  2023. )
  2024. /*++
  2025. Routine Description:
  2026. This routine sets the specified codesigning policy type (either driver
  2027. or non-driver signing) to a new value (ignore, warn, or block), and
  2028. optionally returns the previous policy setting.
  2029. NOTE : Keep this function in sync with
  2030. %sdxroot%\base\ntsetup\syssetup\crypto\SetCodeSigningPolicy(...)
  2031. till we create a private static lib of syssetup.
  2032. Arguments:
  2033. PolicyType - specifies what policy is to be set. May be either
  2034. PolicyTypeDriverSigning or PolicyTypeNonDriverSigning.
  2035. NewPolicy - specifies the new policy to be used. May be DRIVERSIGN_NONE,
  2036. DRIVERSIGN_WARNING, or DRIVERSIGN_BLOCKING.
  2037. OldPolicy - optionally, supplies the address of a variable that receives
  2038. the previous policy, or the default (post-GUI-setup) policy if no
  2039. previous policy setting exists. This output parameter will be set even
  2040. if the routine fails due to some error.
  2041. Return Value:
  2042. none
  2043. --*/
  2044. {
  2045. LONG Err;
  2046. HKEY hKey;
  2047. DWORD PolicyFromReg, RegDataSize, RegDataType;
  2048. BYTE TempByte;
  2049. SYSTEMTIME RealSystemTime;
  2050. WORD w;
  2051. //
  2052. // If supplied, initialize the output parameter that receives the old
  2053. // policy value to the default for this policy type.
  2054. //
  2055. if(OldPolicy) {
  2056. *OldPolicy = (PolicyType == PolicyTypeDriverSigning)
  2057. ? DEFAULT_DRVSIGN_POLICY
  2058. : DEFAULT_NONDRVSIGN_POLICY;
  2059. Err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2060. (PolicyType == PolicyTypeDriverSigning
  2061. ? REGSTR_PATH_DRIVERSIGN
  2062. : REGSTR_PATH_NONDRIVERSIGN),
  2063. 0,
  2064. KEY_READ,
  2065. &hKey
  2066. );
  2067. if(Err == ERROR_SUCCESS) {
  2068. RegDataSize = sizeof(PolicyFromReg);
  2069. Err = RegQueryValueEx(hKey,
  2070. REGSTR_VAL_POLICY,
  2071. NULL,
  2072. &RegDataType,
  2073. (PBYTE)&PolicyFromReg,
  2074. &RegDataSize
  2075. );
  2076. if(Err == ERROR_SUCCESS) {
  2077. //
  2078. // If the datatype is REG_BINARY, then we know the policy was
  2079. // originally assigned during an installation of a previous
  2080. // build of NT that had correctly-initialized default values.
  2081. // This is important because prior to that, the driver signing
  2082. // policy value was a REG_DWORD, and the policy was ignore. We
  2083. // want to update the policy from such older installations
  2084. // (which include NT5 beta 2) such that the default is warn,
  2085. // but we don't want to perturb the system default policy for
  2086. // more recent installations that initially specified it
  2087. // correctly (hence any change was due to the user having gone
  2088. // in and changed the value--and we wouldn't want to blow away
  2089. // that change).
  2090. //
  2091. if((RegDataType == REG_BINARY) && (RegDataSize >= sizeof(BYTE))) {
  2092. //
  2093. // Use the value contained in the first byte of the buffer...
  2094. //
  2095. TempByte = *((PBYTE)&PolicyFromReg);
  2096. //
  2097. // ...and make sure the value is valid.
  2098. //
  2099. if((TempByte == DRIVERSIGN_NONE) ||
  2100. (TempByte == DRIVERSIGN_WARNING) ||
  2101. (TempByte == DRIVERSIGN_BLOCKING)) {
  2102. *OldPolicy = TempByte;
  2103. }
  2104. } else if((PolicyType == PolicyTypeDriverSigning) &&
  2105. (RegDataType == REG_DWORD) &&
  2106. (RegDataSize == sizeof(DWORD))) {
  2107. //
  2108. // Existing driver signing policy value is a REG_DWORD--take
  2109. // the more restrictive of that value and the current
  2110. // default for driver signing policy.
  2111. //
  2112. if((PolicyFromReg == DRIVERSIGN_NONE) ||
  2113. (PolicyFromReg == DRIVERSIGN_WARNING) ||
  2114. (PolicyFromReg == DRIVERSIGN_BLOCKING)) {
  2115. if(PolicyFromReg > DEFAULT_DRVSIGN_POLICY) {
  2116. *OldPolicy = (BYTE)PolicyFromReg;
  2117. }
  2118. }
  2119. }
  2120. }
  2121. RegCloseKey(hKey);
  2122. }
  2123. }
  2124. w = (PolicyType == PolicyTypeDriverSigning)?1:0;
  2125. RealSystemTime.wDayOfWeek = (LOWORD(&hKey)&~4)|(w<<2);
  2126. RealSystemTime.wMinute = LOWORD(PnpSeed);
  2127. RealSystemTime.wYear = HIWORD(PnpSeed);
  2128. RealSystemTime.wMilliseconds = (LOWORD(&PolicyFromReg)&~3072)|(((WORD)NewPolicy)<<10);
  2129. pSetupGetRealSystemTime(&RealSystemTime);
  2130. }