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.

721 lines
18 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation. All rights reserved.
  3. Module Name:
  4. sif.c
  5. Abstract:
  6. This module contains the following routines for manipulating the sif file in
  7. which Plug and Play migration data will be stored:
  8. AsrCreatePnpStateFileW
  9. AsrCreatePnpStateFileA
  10. Author:
  11. Jim Cavalaris (jamesca) 07-Mar-2000
  12. Environment:
  13. User-mode only.
  14. Revision History:
  15. 07-March-2000 jamesca
  16. Creation and initial implementation.
  17. --*/
  18. //
  19. // includes
  20. //
  21. #include "precomp.h"
  22. #include "debug.h"
  23. #include "pnpsif.h"
  24. #include <pnpmgr.h>
  25. #include <setupbat.h>
  26. //
  27. // definitions
  28. //
  29. // Maximum length of a line in the sif file
  30. #define MAX_SIF_LINE 4096
  31. //
  32. // private prototypes
  33. //
  34. BOOL
  35. CreateSifFileW(
  36. IN PCWSTR FilePath,
  37. IN BOOL CreateNew,
  38. OUT LPHANDLE SifHandle
  39. );
  40. BOOL
  41. WriteSifSection(
  42. IN CONST HANDLE SifHandle,
  43. IN PCTSTR SectionName,
  44. IN PCTSTR SectionData,
  45. IN BOOL Ansi
  46. );
  47. //
  48. // routines
  49. //
  50. BOOL
  51. AsrCreatePnpStateFileW(
  52. IN PCWSTR lpFilePath
  53. )
  54. /*++
  55. Routine Description:
  56. Creates the ASR PNP state file (asrpnp.sif) at the specified file-path
  57. during an ASR backup operation. This sif file is retrieved from the ASR
  58. floppy disk during the setupldr phase of a clean install, and in used during
  59. text mode setup.
  60. Arguments:
  61. lpFilePath - Specifies the path to the file where the state file is to be
  62. created.
  63. Return Value:
  64. TRUE if successful, FALSE otherwise. Upon failure, additional information
  65. can be retrieved by calling GetLastError().
  66. --*/
  67. {
  68. BOOL result = TRUE;
  69. BOOL bAnsiSif = TRUE; // always write ANSI sif files.
  70. LPTSTR buffer = NULL;
  71. HANDLE sifHandle = NULL;
  72. //
  73. // Create an empty sif file using the supplied path name.
  74. //
  75. result = CreateSifFileW(lpFilePath,
  76. TRUE, // create a new asrpnp.sif file
  77. &sifHandle);
  78. if (!result) {
  79. //
  80. // LastError already set by CreateSifFile.
  81. //
  82. DBGTRACE((DBGF_ERRORS,
  83. TEXT("AsrCreatePnpStateFile: CreateSifFileW failed for file %s, ")
  84. TEXT("error=0x%08lx\n"),
  85. lpFilePath, GetLastError()));
  86. return FALSE;
  87. }
  88. //
  89. // Do the device instance migration stuff...
  90. //
  91. if (MigrateDeviceInstanceData(&buffer)) {
  92. //
  93. // Write the device instance section to the sif file.
  94. //
  95. result = WriteSifSection(sifHandle,
  96. WINNT_DEVICEINSTANCES,
  97. buffer,
  98. bAnsiSif); // Write sif section as ANSI
  99. if (!result) {
  100. DBGTRACE((DBGF_ERRORS,
  101. TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], ")
  102. TEXT("error=0x%08lx\n"),
  103. WINNT_DEVICEINSTANCES, GetLastError()));
  104. }
  105. //
  106. // Free the allocated buffer.
  107. //
  108. LocalFree(buffer);
  109. buffer = NULL;
  110. } else {
  111. DBGTRACE((DBGF_ERRORS,
  112. TEXT("AsrCreatePnpStateFile: MigrateDeviceInstanceData failed, ")
  113. TEXT("error=0x%08lx\n"),
  114. GetLastError()));
  115. }
  116. //
  117. // Do the class key migration stuff...
  118. //
  119. if (MigrateClassKeys(&buffer)) {
  120. //
  121. // Write the class key section to the sif file.
  122. //
  123. result = WriteSifSection(sifHandle,
  124. WINNT_CLASSKEYS,
  125. buffer,
  126. bAnsiSif); // Write sif section as ANSI
  127. if (!result) {
  128. DBGTRACE((DBGF_ERRORS,
  129. TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], ")
  130. TEXT("error=0x%08lx\n"),
  131. WINNT_CLASSKEYS, GetLastError()));
  132. }
  133. //
  134. // Free the allocated buffer.
  135. //
  136. LocalFree(buffer);
  137. buffer = NULL;
  138. } else {
  139. DBGTRACE((DBGF_ERRORS,
  140. TEXT("AsrCreatePnpStateFile: MigrateClassKeys failed, ")
  141. TEXT("error=0x%08lx\n"),
  142. GetLastError()));
  143. }
  144. //
  145. // Do the hash value migration stuff...
  146. //
  147. if (MigrateHashValues(&buffer)) {
  148. //
  149. // Write the hash value section to the sif file.
  150. //
  151. result = WriteSifSection(sifHandle,
  152. WINNT_DEVICEHASHVALUES,
  153. buffer,
  154. bAnsiSif); // Write sif section as ANSI?
  155. if (!result) {
  156. DBGTRACE((DBGF_ERRORS,
  157. TEXT("AsrCreatePnpStateFile: WriteSifSection failed for [%s], ")
  158. TEXT("error=0x%08lx\n"),
  159. WINNT_DEVICEHASHVALUES, GetLastError()));
  160. }
  161. //
  162. // Free the allocated buffer.
  163. //
  164. LocalFree(buffer);
  165. buffer = NULL;
  166. } else {
  167. DBGTRACE((DBGF_ERRORS,
  168. TEXT("AsrCreatePnpStateFile: MigrateHashValues failed, ")
  169. TEXT("error=0x%08lx\n"),
  170. GetLastError()));
  171. }
  172. //
  173. // Close the sif file.
  174. //
  175. if (sifHandle) {
  176. CloseHandle(sifHandle);
  177. }
  178. //
  179. // Reset the last error as successful in case we encountered a non-fatal
  180. // error along the way.
  181. //
  182. SetLastError(ERROR_SUCCESS);
  183. return TRUE;
  184. } // AsrCreatePnpStateFile()
  185. BOOL
  186. AsrCreatePnpStateFileA(
  187. IN PCSTR lpFilePath
  188. )
  189. /*++
  190. Routine Description:
  191. None.
  192. Arguments:
  193. None.
  194. Return Value:
  195. None.
  196. --*/
  197. {
  198. WCHAR wszFilePath[MAX_PATH + 1];
  199. //
  200. // Validate arguments.
  201. //
  202. if (!ARGUMENT_PRESENT(lpFilePath) ||
  203. strlen(lpFilePath) > MAX_PATH) {
  204. SetLastError(ERROR_INVALID_PARAMETER);
  205. return FALSE;
  206. }
  207. //
  208. // Convert the file path to a wide string.
  209. //
  210. memset(wszFilePath, 0, MAX_PATH + 1);
  211. if (!(MultiByteToWideChar(CP_ACP,
  212. 0,
  213. lpFilePath,
  214. -1,
  215. wszFilePath,
  216. MAX_PATH + 1))) {
  217. SetLastError(ERROR_INVALID_PARAMETER);
  218. return FALSE;
  219. }
  220. //
  221. // Return the result of calling the wide char version
  222. //
  223. return AsrCreatePnpStateFileW(wszFilePath);
  224. } // AsrCreatePnpStateFileA()
  225. BOOL
  226. CreateSifFileW(
  227. IN PCWSTR lpFilePath,
  228. IN BOOL bCreateNew,
  229. OUT LPHANDLE lpSifHandle
  230. )
  231. /*++
  232. Routine Description:
  233. None.
  234. Arguments:
  235. None.
  236. Return Value:
  237. None.
  238. --*/
  239. {
  240. DWORD Err = NO_ERROR;
  241. SID_IDENTIFIER_AUTHORITY sidNtAuthority = SECURITY_NT_AUTHORITY;
  242. PSID psidAdministrators = NULL;
  243. PSID psidBackupOperators = NULL;
  244. PSID psidLocalSystem = NULL;
  245. PACL pDacl = NULL;
  246. ULONG ulAclSize;
  247. SECURITY_ATTRIBUTES sa;
  248. SECURITY_DESCRIPTOR sd;
  249. HANDLE sifhandle = NULL;
  250. //
  251. // Validate arguments.
  252. //
  253. if (!ARGUMENT_PRESENT(lpFilePath) ||
  254. (wcslen(lpFilePath) > MAX_PATH) ||
  255. !ARGUMENT_PRESENT(lpSifHandle)) {
  256. Err = ERROR_INVALID_PARAMETER;
  257. goto Clean0;
  258. }
  259. //
  260. // Initialize output paramaters.
  261. //
  262. *lpSifHandle = NULL;
  263. //
  264. // Construct the security attributes for the sif file.
  265. // Allow access for Administrators, BackupOperators, and LocalSystem.
  266. //
  267. if (!AllocateAndInitializeSid(
  268. &sidNtAuthority,
  269. 2,
  270. SECURITY_BUILTIN_DOMAIN_RID,
  271. DOMAIN_ALIAS_RID_ADMINS,
  272. 0, 0, 0, 0, 0, 0,
  273. &psidAdministrators)) {
  274. Err = GetLastError();
  275. goto Clean0;
  276. }
  277. ASSERT(IsValidSid(psidAdministrators));
  278. if (!AllocateAndInitializeSid(
  279. &sidNtAuthority,
  280. 2,
  281. SECURITY_BUILTIN_DOMAIN_RID,
  282. DOMAIN_ALIAS_RID_BACKUP_OPS,
  283. 0, 0, 0, 0, 0, 0,
  284. &psidBackupOperators)) {
  285. Err = GetLastError();
  286. goto Clean0;
  287. }
  288. ASSERT(IsValidSid(psidBackupOperators));
  289. if (!AllocateAndInitializeSid(
  290. &sidNtAuthority,
  291. 1,
  292. SECURITY_LOCAL_SYSTEM_RID,
  293. 0, 0, 0, 0, 0, 0, 0,
  294. &psidLocalSystem)) {
  295. Err = GetLastError();
  296. goto Clean0;
  297. }
  298. ASSERT(IsValidSid(psidLocalSystem));
  299. //
  300. // Determine the size required for the DACL
  301. //
  302. ulAclSize = sizeof(ACL);
  303. ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidAdministrators) - sizeof(DWORD);
  304. ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidBackupOperators) - sizeof(DWORD);
  305. ulAclSize += sizeof(ACCESS_ALLOWED_ACE) + GetLengthSid(psidLocalSystem) - sizeof(DWORD);
  306. //
  307. // Allocate and initialize the DACL
  308. //
  309. pDacl =(PACL)LocalAlloc(0, ulAclSize);
  310. if (pDacl == NULL) {
  311. Err = ERROR_NOT_ENOUGH_MEMORY;
  312. goto Clean0;
  313. }
  314. if (!InitializeAcl(pDacl, ulAclSize, ACL_REVISION)) {
  315. Err = GetLastError();
  316. goto Clean0;
  317. }
  318. //
  319. // Add an ACE to the DACL for Administrators FILE_ALL_ACCESS
  320. //
  321. if (!AddAccessAllowedAceEx(
  322. pDacl,
  323. ACL_REVISION,
  324. 0,
  325. FILE_ALL_ACCESS,
  326. psidAdministrators)) {
  327. Err = GetLastError();
  328. goto Clean0;
  329. }
  330. //
  331. // Add an ACE to the DACL for BackupOperators FILE_ALL_ACCESS
  332. //
  333. if (!AddAccessAllowedAceEx(
  334. pDacl,
  335. ACL_REVISION,
  336. 0,
  337. FILE_ALL_ACCESS,
  338. psidBackupOperators)) {
  339. Err = GetLastError();
  340. goto Clean0;
  341. }
  342. //
  343. // Add an ACE to the DACL for LocalSystem FILE_ALL_ACCESS
  344. //
  345. if (!AddAccessAllowedAceEx(
  346. pDacl,
  347. ACL_REVISION,
  348. 0,
  349. FILE_ALL_ACCESS,
  350. psidLocalSystem)) {
  351. Err = GetLastError();
  352. goto Clean0;
  353. }
  354. ASSERT(IsValidAcl(pDacl));
  355. //
  356. // Initialize the security descriptor
  357. //
  358. if (!InitializeSecurityDescriptor(
  359. &sd, SECURITY_DESCRIPTOR_REVISION)) {
  360. Err = GetLastError();
  361. goto Clean0;
  362. }
  363. //
  364. // Set the new DACL in the security descriptor
  365. //
  366. if (!SetSecurityDescriptorDacl(
  367. &sd, TRUE, pDacl, FALSE)) {
  368. Err = GetLastError();
  369. goto Clean0;
  370. }
  371. ASSERT(IsValidSecurityDescriptor(&sd));
  372. //
  373. // Add the security descriptor to the security attributes
  374. //
  375. ZeroMemory(&sa, sizeof(SECURITY_ATTRIBUTES));
  376. sa.nLength = sizeof(sa);
  377. sa.lpSecurityDescriptor = &sd;
  378. sa.bInheritHandle = TRUE;
  379. //
  380. // Create the file. The handle will be closed by the caller, once they are
  381. // finished with it.
  382. //
  383. sifhandle = CreateFileW(lpFilePath,
  384. GENERIC_WRITE | GENERIC_READ,
  385. FILE_SHARE_READ,
  386. &sa,
  387. bCreateNew ? CREATE_ALWAYS : OPEN_EXISTING,
  388. FILE_FLAG_BACKUP_SEMANTICS,
  389. NULL);
  390. if (sifhandle == INVALID_HANDLE_VALUE) {
  391. Err = GetLastError();
  392. goto Clean0;
  393. }
  394. ASSERT(sifhandle != NULL);
  395. //
  396. // Return the sif handle to the caller only if successful.
  397. //
  398. *lpSifHandle = sifhandle;
  399. Clean0:
  400. if (pDacl != NULL) {
  401. LocalFree(pDacl);
  402. }
  403. if (psidLocalSystem != NULL) {
  404. FreeSid(psidLocalSystem);
  405. }
  406. if (psidBackupOperators != NULL) {
  407. FreeSid(psidBackupOperators);
  408. }
  409. if (psidAdministrators != NULL) {
  410. FreeSid(psidAdministrators);
  411. }
  412. SetLastError(Err);
  413. return(Err == NO_ERROR);
  414. } // CreateSifFileW()
  415. BOOL
  416. WriteSifSection(
  417. IN CONST HANDLE SifHandle,
  418. IN PCTSTR SectionName,
  419. IN PCTSTR SectionData,
  420. IN BOOL Ansi
  421. )
  422. /*++
  423. Routine Description:
  424. None.
  425. Arguments:
  426. None.
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. BYTE buffer[(MAX_SIF_LINE+1)*sizeof(WCHAR)];
  432. DWORD dwSize, dwTempSize;
  433. PCTSTR p;
  434. HRESULT hr;
  435. //
  436. // Validate the arguments
  437. //
  438. if (!ARGUMENT_PRESENT(SifHandle) ||
  439. !ARGUMENT_PRESENT(SectionName) ||
  440. !ARGUMENT_PRESENT(SectionData)) {
  441. SetLastError(ERROR_INVALID_PARAMETER);
  442. return FALSE;
  443. }
  444. //
  445. // Write the section name to the sif file.
  446. //
  447. if (Ansi) {
  448. //
  449. // Write ANSI strings to the sif file
  450. //
  451. #if UNICODE
  452. hr = StringCbPrintfExA((LPSTR)buffer,
  453. sizeof(buffer),
  454. NULL, NULL,
  455. STRSAFE_NULL_ON_FAILURE,
  456. (LPCSTR)"[%ls]\r\n",
  457. SectionName);
  458. #else // ANSI
  459. hr = StringCbPrintfExA((LPSTR)buffer,
  460. sizeof(buffer),
  461. NULL, NULL,
  462. STRSAFE_NULL_ON_FAILURE,
  463. (LPCSTR)"[%s]\r\n",
  464. SectionName);
  465. #endif // UNICODE/ANSI
  466. //
  467. // If unable to write the section name to the sif file, we can't write
  468. // the section at all.
  469. //
  470. if (FAILED(hr)) {
  471. SetLastError(ERROR_INVALID_DATA);
  472. return FALSE;
  473. }
  474. dwSize = (DWORD)strlen((PSTR)buffer);
  475. } else {
  476. //
  477. // Write Unicode strings to the sif file
  478. //
  479. #if UNICODE
  480. hr = StringCbPrintfExW((LPWSTR)buffer,
  481. sizeof(buffer),
  482. NULL, NULL,
  483. STRSAFE_NULL_ON_FAILURE,
  484. (LPCWSTR)L"[%ws]\r\n",
  485. SectionName);
  486. #else // ANSI
  487. hr = StringCbPrintfExW((LPWSTR)buffer,
  488. sizeof(buffer),
  489. NULL, NULL,
  490. STRSAFE_NULL_ON_FAILURE,
  491. (LPCWSTR)L"[%S]\r\n",
  492. SectionName);
  493. #endif // UNICODE/ANSI
  494. //
  495. // If unable to write the section name to the sif file, we can't write
  496. // the section at all.
  497. //
  498. if (FAILED(hr)) {
  499. SetLastError(ERROR_INVALID_DATA);
  500. return FALSE;
  501. }
  502. dwSize = (DWORD)wcslen((PWSTR)buffer) * sizeof(WCHAR);
  503. }
  504. if (!WriteFile(SifHandle, buffer, dwSize, &dwTempSize, NULL)) {
  505. //
  506. // LastError already set by WriteFile
  507. //
  508. return FALSE;
  509. }
  510. DBGTRACE((DBGF_INFO, TEXT("[%s]\n"), SectionName));
  511. //
  512. // Write the multi-sz section data to the file.
  513. //
  514. for (p = SectionData; *p != TEXT('\0'); p += lstrlen(p) + 1) {
  515. if (Ansi) {
  516. //
  517. // Write ANSI strings to the sif file
  518. //
  519. #if UNICODE
  520. hr = StringCbPrintfExA((LPSTR)buffer,
  521. sizeof(buffer),
  522. NULL, NULL,
  523. STRSAFE_NULL_ON_FAILURE,
  524. (LPCSTR)"%ls\r\n",
  525. p);
  526. #else // ANSI
  527. hr = StringCbPrintfExA((LPSTR)buffer,
  528. sizeof(buffer),
  529. NULL, NULL,
  530. STRSAFE_NULL_ON_FAILURE,
  531. (LPCSTR)"%s\r\n",
  532. p);
  533. #endif // UNICODE/ANSI
  534. //
  535. // If unable to write this string to the sif file, skip to the next.
  536. //
  537. if (FAILED(hr)) {
  538. continue;
  539. }
  540. dwSize = (DWORD)strlen((PSTR)buffer);
  541. } else {
  542. //
  543. // Write Unicode strings to the sif file
  544. //
  545. #if UNICODE
  546. hr = StringCbPrintfExW((LPWSTR)buffer,
  547. sizeof(buffer),
  548. NULL, NULL,
  549. STRSAFE_NULL_ON_FAILURE,
  550. (LPCWSTR)L"%ws\r\n",
  551. p);
  552. #else // ANSI
  553. hr = StringCbPrintfExW((LPWSTR)buffer,
  554. sizeof(buffer),
  555. NULL, NULL,
  556. STRSAFE_NULL_ON_FAILURE,
  557. (LPCWSTR)L"%S\r\n",
  558. p);
  559. #endif // UNICODE/ANSI
  560. //
  561. // If unable to write this string to the sif file, skip to the next.
  562. //
  563. if (FAILED(hr)) {
  564. continue;
  565. }
  566. dwSize = (DWORD)wcslen((PWSTR)buffer) * sizeof(WCHAR);
  567. }
  568. if (!WriteFile(SifHandle, buffer, dwSize, &dwTempSize, NULL)) {
  569. //
  570. // LastError already set by WriteFile
  571. //
  572. return FALSE;
  573. }
  574. DBGTRACE((DBGF_INFO, TEXT("%s\n"), p));
  575. }
  576. return TRUE;
  577. } // WriteSifSection()
  578.