Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2485 lines
74 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. inftojet.c
  5. Abstract:
  6. Routines to convert security profiles in INF format to JET format.
  7. Author:
  8. Jin Huang (jinhuang) 23-Jan-1997
  9. Revision History:
  10. --*/
  11. #include "serverp.h"
  12. #include "infp.h"
  13. #include "pfp.h"
  14. #include "regvalue.h"
  15. #pragma hdrstop
  16. //#define SCE_DBG 1
  17. #define SCE_PRIV_ADD TEXT("Add:")
  18. #define SCE_PRIV_REMOVE TEXT("Remove:")
  19. #define SCE_OBJECT_FLAG_OBJECTS 1
  20. #define SCE_OBJECT_FLAG_OLDSDDL 2
  21. #define SCE_OBJECT_FLAG_UNKNOWN_VERSION 4
  22. //
  23. // Forward references
  24. //
  25. SCEINF_STATUS
  26. SceInfpGetOneObject(
  27. IN PINFCONTEXT pInfLine,
  28. IN DWORD ObjectFlag,
  29. OUT PWSTR *Name,
  30. OUT PWSTR *Value,
  31. OUT PDWORD ValueLen
  32. );
  33. #define SCE_CONVERT_INF_MULTISZ 0x01
  34. #define SCE_CONVERT_INF_PRIV 0x02
  35. #define SCE_CONVERT_INF_GROUP 0x04
  36. #define SCE_CONVERT_INF_NEWVERSION 0x08
  37. #define SCE_CONVERT_INF_REGVALUE 0x10
  38. SCESTATUS
  39. SceConvertpInfKeyValue(
  40. IN PCWSTR InfSectionName,
  41. IN HINF hInf,
  42. IN PSCECONTEXT hProfile,
  43. IN DWORD dwTableOption,
  44. IN DWORD dwConvertOption,
  45. IN LONG GpoID,
  46. OUT PSCE_NAME_LIST *pKeyList
  47. );
  48. SCESTATUS
  49. SceConvertpInfObject(
  50. IN PCWSTR InfSectionName,
  51. IN UINT ObjectType,
  52. IN DWORD ObjectFlag,
  53. IN HINF hInf,
  54. IN PSCECONTEXT hProfile,
  55. IN DWORD dwTableOption,
  56. IN LONG GpoID
  57. );
  58. SCESTATUS
  59. SceConvertpInfDescription(
  60. IN HINF hInf,
  61. IN PSCECONTEXT hProfile
  62. );
  63. SCESTATUS
  64. SceConvertpAttachmentSections(
  65. IN HINF hInf,
  66. IN PSCECONTEXT hProfile,
  67. IN DWORD dwTableOption,
  68. IN LONG GpoID,
  69. IN SCE_ATTACHMENT_TYPE aType
  70. );
  71. SCESTATUS
  72. SceConvertpWMIAttachmentSections(
  73. IN HINF hInf,
  74. IN PSCECONTEXT hProfile,
  75. IN DWORD dwTableOption,
  76. IN LONG GpoID
  77. );
  78. SCESTATUS
  79. SceConvertpOneAttachmentSection(
  80. IN HINF hInf,
  81. IN PSCECONTEXT hProfile,
  82. IN PWSTR SectionName,
  83. IN DWORD dwTableOption,
  84. IN LONG GpoID
  85. );
  86. SCESTATUS
  87. ScepBuildNewPrivilegeList(
  88. IN LSA_HANDLE *pPolicyHandle,
  89. IN PWSTR PrivName,
  90. IN PWSTR mszUsers,
  91. IN ULONG dwBuildOption,
  92. OUT PWSTR *pmszNewUsers,
  93. OUT DWORD *pNewLen
  94. );
  95. SCESTATUS
  96. ScepAddToPrivilegeList(
  97. OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
  98. IN PWSTR Name,
  99. IN DWORD Len,
  100. IN DWORD PrivValue
  101. );
  102. //
  103. // Function definitions
  104. //
  105. SCESTATUS
  106. SceJetConvertInfToJet(
  107. IN PCWSTR InfFile,
  108. IN LPSTR JetDbName,
  109. IN SCEJET_CREATE_TYPE Flags,
  110. IN DWORD Options,
  111. IN AREA_INFORMATION Area
  112. )
  113. /**++
  114. Function Description:
  115. This function converts a SCP profile in INF format to a Jet database format
  116. for the area provided. The SCP profile information is converted into the
  117. local policy table (SMP) in the Jet database.
  118. If the Jet database already exists, Flags is used to decide either overwrite,
  119. reuse, or just error out. All possible errors occur inside the routine are
  120. saved in the optional Errlog if Errlog is not NULL
  121. Arguments:
  122. InfFile - The Inf file name to convert from
  123. JetDbName - the SCP profile in Jet format to convert into
  124. Flags - Used when there is a duplicated Jet database
  125. SCEJET_OVERWRITE
  126. SCEJET_OPEN
  127. 0
  128. Options - the conversion options
  129. Area - the area to convert
  130. Return Value:
  131. -- **/
  132. {
  133. PSCECONTEXT hProfile=NULL;
  134. SCESTATUS rc;
  135. PSCE_NAME_LIST pProfileList=NULL,
  136. pProfile=NULL;
  137. DWORD Count;
  138. PSECURITY_DESCRIPTOR pSD=NULL;
  139. SECURITY_INFORMATION SeInfo;
  140. HINF hInf=NULL;
  141. RPC_STATUS RpcStatus=RPC_S_OK;
  142. INT Revision = 0;
  143. DWORD ObjectFlag=0;
  144. INFCONTEXT InfLine;
  145. DWORD dwConvertOption=0;
  146. if ( InfFile == NULL ||
  147. JetDbName == NULL ) {
  148. return(SCESTATUS_INVALID_PARAMETER);
  149. }
  150. //
  151. // open the inf profile
  152. //
  153. rc = SceInfpOpenProfile(
  154. InfFile,
  155. &hInf
  156. );
  157. if ( rc != SCESTATUS_SUCCESS ) {
  158. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  159. SCEDLL_ERROR_OPEN,
  160. (PWSTR)InfFile);
  161. return(rc);
  162. }
  163. LONG GpoID=0;
  164. //
  165. // create/open the Jet database
  166. //
  167. DWORD dwNewOption = 0;
  168. // MREGE_POLICY option allows opening the temp merge policy table to build new policy
  169. // TATTOO option allows creating/opening the tattoo table into SAP context
  170. if ( Options & SCE_POLICY_TEMPLATE )
  171. dwNewOption |= SCE_TABLE_OPTION_MERGE_POLICY | SCE_TABLE_OPTION_TATTOO;
  172. // this check handles setup case (to create/open tattoo table)
  173. else {
  174. if ( (Options & SCE_SYSTEM_DB) )
  175. dwNewOption |= SCE_TABLE_OPTION_TATTOO;
  176. // dc demote should reset account policy and user rights at reboot (from tattoo table)
  177. if ( Options & SCE_DC_DEMOTE )
  178. dwNewOption |= SCE_TABLE_OPTION_DEMOTE_TATTOO;
  179. }
  180. rc = SceJetCreateFile(JetDbName,
  181. Flags,
  182. dwNewOption,
  183. &hProfile);
  184. if ( rc != SCESTATUS_SUCCESS ) {
  185. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  186. SCEDLL_ERROR_CREATE, L"database");
  187. goto CleanUp;
  188. }
  189. if ( Options & SCE_SYSTEM_DB ) {
  190. //
  191. // set Admin F, CO F to the database (protected)
  192. //
  193. rc = ConvertTextSecurityDescriptor (
  194. L"D:P(A;;GA;;;CO)(A;;GR;;;WD)(A;;GA;;;BA)(A;;GA;;;SY)",
  195. &pSD,
  196. &Count, // temp var for SDsize
  197. &SeInfo
  198. );
  199. if ( rc == NO_ERROR ) {
  200. ScepChangeAclRevision(pSD, ACL_REVISION);
  201. //
  202. // use current token as the owner (because this database is
  203. // to be created
  204. //
  205. HANDLE Token=NULL;
  206. if (!OpenThreadToken( GetCurrentThread(),
  207. TOKEN_QUERY,
  208. FALSE,
  209. &Token)) {
  210. if (!OpenProcessToken( GetCurrentProcess(),
  211. TOKEN_QUERY,
  212. &Token)) {
  213. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  214. }
  215. }
  216. if ( Token ) {
  217. PSECURITY_DESCRIPTOR pNewSD=NULL;
  218. //
  219. // RtlNewSecurityObjectEx must be called on the process context (system)
  220. // because it will try to get process information inside the api.
  221. //
  222. RpcRevertToSelf();
  223. rc = RtlNtStatusToDosError(
  224. RtlNewSecurityObjectEx(
  225. NULL,
  226. pSD,
  227. &pNewSD,
  228. NULL, // GUID
  229. FALSE,
  230. SEF_DACL_AUTO_INHERIT |
  231. SEF_AVOID_OWNER_CHECK |
  232. SEF_AVOID_PRIVILEGE_CHECK,
  233. Token,
  234. &FileGenericMapping
  235. ));
  236. RpcStatus = RpcImpersonateClient( NULL );
  237. if ( RpcStatus == RPC_S_OK ) {
  238. if ( rc == NO_ERROR ) {
  239. if ( !SetFileSecurityA (
  240. JetDbName,
  241. SeInfo,
  242. pNewSD
  243. ) ) {
  244. rc = GetLastError();
  245. ScepLogOutput3(1, rc,
  246. SCEDLL_ERROR_SET_SECURITY, L"database");
  247. }
  248. ScepFree(pNewSD);
  249. } else {
  250. ScepLogOutput3(1, rc,
  251. SCEDLL_ERROR_BUILD_SD, L"database");
  252. }
  253. } else {
  254. if ( rc == NO_ERROR ) {
  255. ScepFree(pNewSD);
  256. }
  257. ScepLogOutput3(1, I_RpcMapWin32Status(RpcStatus),
  258. SCEDLL_ERROR_BUILD_SD, L"database");
  259. }
  260. CloseHandle(Token);
  261. }
  262. ScepFree(pSD);
  263. } else
  264. ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, L"database");
  265. }
  266. if ( RpcStatus != RPC_S_OK ) {
  267. goto CleanUp;
  268. }
  269. if ( !(Options & SCE_POLICY_TEMPLATE) ) {
  270. //
  271. // if not in the middle of policy propagation, use Jet transaction
  272. // otherwise, use the temp table concept.
  273. //
  274. SceJetStartTransaction( hProfile );
  275. //
  276. //If it is in demote or snapshot mode delete local policy.
  277. //
  278. if ( (Options & SCE_DC_DEMOTE) &&
  279. (Options & SCE_SYSTEM_DB) ) {
  280. ScepDeleteInfoForAreas(
  281. hProfile,
  282. SCE_ENGINE_SMP,
  283. AREA_ALL
  284. );
  285. ScepDeleteInfoForAreas(
  286. hProfile,
  287. SCE_ENGINE_SAP, // tattoo
  288. AREA_ALL
  289. );
  290. } else if ( Options & SCE_GENERATE_ROLLBACK ) {
  291. ScepDeleteInfoForAreas(
  292. hProfile,
  293. SCE_ENGINE_SMP,
  294. AREA_ALL
  295. );
  296. }
  297. } else if ( Options & SCE_POLICY_FIRST ) {
  298. //
  299. // The ENGINE_SCP table points to the new merge table
  300. // instead of the existing one.
  301. //
  302. // delete everything in SCP then
  303. // copy Tattoo to SCP
  304. //
  305. rc = ScepDeleteInfoForAreas(
  306. hProfile,
  307. SCE_ENGINE_SCP,
  308. AREA_ALL
  309. );
  310. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND ) {
  311. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  312. SCEDLL_ERROR_DELETE, L"SCP");
  313. goto CleanUp;
  314. }
  315. //
  316. // delete GPO table to start over
  317. //
  318. SceJetDeleteAll( hProfile,
  319. "SmTblGpo",
  320. SCEJET_TABLE_GPO
  321. );
  322. PSCE_ERROR_LOG_INFO Errlog=NULL;
  323. ScepLogOutput3(2, rc, SCEDLL_COPY_LOCAL);
  324. // copy from tattoo table to effective policy table
  325. rc = ScepCopyLocalToMergeTable( hProfile,
  326. Options,
  327. (ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0,
  328. &Errlog );
  329. ScepLogWriteError( Errlog,1 );
  330. ScepFreeErrorLog( Errlog );
  331. Errlog = NULL;
  332. if ( rc != SCESTATUS_SUCCESS ) {
  333. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  334. SCEDLL_ERROR_COPY);
  335. goto CleanUp;
  336. }
  337. //
  338. // now, migrate database if tattoo table doesn't exist (in existing database)
  339. // this could happen if someone manually copied a database to the system
  340. // database location, or if the database failed to be migrated in setup
  341. //
  342. if ( hProfile->JetSapID == JET_tableidNil ) {
  343. SceJetCreateTable(
  344. hProfile,
  345. "SmTblTattoo",
  346. SCEJET_TABLE_TATTOO,
  347. SCEJET_CREATE_IN_BUFFER,
  348. NULL,
  349. NULL
  350. );
  351. }
  352. }
  353. TCHAR szGpoName[MAX_PATH];
  354. szGpoName[0] = L'\0';
  355. szGpoName[1] = L'\0';
  356. szGpoName[2] = L'\0';
  357. if ( Options & SCE_POLICY_TEMPLATE ) {
  358. //
  359. // get the GPO path and GPOID
  360. //
  361. GetPrivateProfileString(TEXT("Version"),
  362. TEXT("GPOPath"),
  363. TEXT(""),
  364. szGpoName,
  365. MAX_PATH,
  366. InfFile
  367. );
  368. if ( szGpoName[0] != L'\0' ) {
  369. PWSTR pTemp = wcschr(szGpoName, L'\\');
  370. if ( pTemp ) {
  371. *pTemp = L'\0';
  372. }
  373. GpoID = SceJetGetGpoIDByName(hProfile,
  374. szGpoName,
  375. TRUE // add if it's not there
  376. );
  377. //
  378. // if GpoID is -1, an error occurred
  379. //
  380. if ( GpoID < 0 ) {
  381. rc = GetLastError();
  382. if ( rc != SCESTATUS_SUCCESS ) {
  383. ScepLogOutput3( 1, ScepDosErrorToSceStatus(rc),
  384. SCEDLL_ERROR_CONVERT, (PWSTR)szGpoName);
  385. goto CleanUp;
  386. }
  387. }
  388. }
  389. }
  390. //
  391. // query the version # to determine if the SDDL string should be migrated
  392. //
  393. if ( SetupFindFirstLine(hInf,L"Version",L"Revision",&InfLine) ) {
  394. if ( !SetupGetIntField(&InfLine, 1, (INT *)&Revision) ) {
  395. Revision = 0;
  396. }
  397. }
  398. if ( Revision == 0 ) ObjectFlag = SCE_OBJECT_FLAG_OLDSDDL;
  399. if ( Revision > SCE_TEMPLATE_MAX_SUPPORTED_VERSION ) {
  400. dwConvertOption = SCE_CONVERT_INF_NEWVERSION;
  401. ObjectFlag |= SCE_OBJECT_FLAG_UNKNOWN_VERSION;
  402. }
  403. //
  404. // process each area
  405. //
  406. if ( Area & AREA_SECURITY_POLICY ) {
  407. if ( !( Options & SCE_NO_DOMAIN_POLICY) ) {
  408. // System Access section
  409. rc = SceConvertpInfKeyValue(
  410. szSystemAccess,
  411. hInf,
  412. hProfile,
  413. dwNewOption,
  414. dwConvertOption,
  415. GpoID,
  416. NULL
  417. );
  418. if ( rc != SCESTATUS_SUCCESS ) {
  419. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  420. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szSystemAccess);
  421. goto CleanUp;
  422. }
  423. }
  424. //
  425. // configure event log settings in setup too
  426. // since local policy table is not used in policy prop anymore
  427. //
  428. // if ( !(Options & SCE_SYSTEM_DB) ||
  429. // (Options & SCE_POLICY_TEMPLATE) ) {
  430. // System Log section
  431. rc = SceConvertpInfKeyValue(
  432. szAuditSystemLog,
  433. hInf,
  434. hProfile,
  435. dwNewOption,
  436. dwConvertOption,
  437. GpoID,
  438. NULL
  439. );
  440. if ( rc != SCESTATUS_SUCCESS ) {
  441. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  442. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSystemLog);
  443. goto CleanUp;
  444. }
  445. // Security Log section
  446. rc = SceConvertpInfKeyValue(
  447. szAuditSecurityLog,
  448. hInf,
  449. hProfile,
  450. dwNewOption,
  451. dwConvertOption,
  452. GpoID,
  453. NULL
  454. );
  455. if ( rc != SCESTATUS_SUCCESS ) {
  456. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  457. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSecurityLog);
  458. goto CleanUp;
  459. }
  460. // Application Log section
  461. rc = SceConvertpInfKeyValue(
  462. szAuditApplicationLog,
  463. hInf,
  464. hProfile,
  465. dwNewOption,
  466. dwConvertOption,
  467. GpoID,
  468. NULL
  469. );
  470. if ( rc != SCESTATUS_SUCCESS ) {
  471. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  472. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditApplicationLog);
  473. goto CleanUp;
  474. }
  475. // }
  476. // Audit Event section
  477. rc = SceConvertpInfKeyValue(
  478. szAuditEvent,
  479. hInf,
  480. hProfile,
  481. dwNewOption,
  482. dwConvertOption,
  483. GpoID,
  484. NULL
  485. );
  486. if ( rc != SCESTATUS_SUCCESS ) {
  487. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  488. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditEvent);
  489. goto CleanUp;
  490. }
  491. if ( !( Options & SCE_NO_DOMAIN_POLICY) &&
  492. (ProductType == NtProductLanManNt) &&
  493. !( Options & SCE_DC_DEMOTE) ) {
  494. // Kerberos section
  495. rc = SceConvertpInfKeyValue(
  496. szKerberosPolicy,
  497. hInf,
  498. hProfile,
  499. dwNewOption,
  500. dwConvertOption,
  501. GpoID,
  502. NULL
  503. );
  504. if ( rc != SCESTATUS_SUCCESS ) {
  505. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  506. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szKerberosPolicy);
  507. goto CleanUp;
  508. }
  509. }
  510. // registry values
  511. rc = SceConvertpInfKeyValue(
  512. szRegistryValues,
  513. hInf,
  514. hProfile,
  515. dwNewOption,
  516. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_REGVALUE,
  517. GpoID,
  518. NULL
  519. );
  520. if ( rc != SCESTATUS_SUCCESS ) {
  521. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  522. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryValues);
  523. goto CleanUp;
  524. }
  525. rc = SceConvertpAttachmentSections(hInf,
  526. hProfile,
  527. (Options & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
  528. GpoID,
  529. SCE_ATTACHMENT_POLICY);
  530. if ( rc != SCESTATUS_SUCCESS ) {
  531. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  532. SCEDLL_SAP_ERROR_ENUMERATE, L"policy attachments.");
  533. goto CleanUp;
  534. }
  535. }
  536. if ( Area & AREA_REGISTRY_SECURITY ) {
  537. //
  538. // Object type - Registry
  539. //
  540. rc = SceConvertpInfObject(
  541. szRegistryKeys,
  542. 1,
  543. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  544. hInf,
  545. hProfile,
  546. dwNewOption,
  547. GpoID
  548. );
  549. if ( rc != SCESTATUS_SUCCESS ) {
  550. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  551. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryKeys);
  552. goto CleanUp;
  553. }
  554. }
  555. if ( Area & AREA_FILE_SECURITY ) {
  556. // File security
  557. rc = SceConvertpInfObject(
  558. szFileSecurity,
  559. 2,
  560. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  561. hInf,
  562. hProfile,
  563. dwNewOption,
  564. GpoID
  565. );
  566. if ( rc != SCESTATUS_SUCCESS ) {
  567. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  568. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szFileSecurity);
  569. goto CleanUp;
  570. }
  571. }
  572. #if 0
  573. //
  574. // DS object security
  575. //
  576. rc = SceConvertpInfObject(
  577. szDSSecurity,
  578. 3,
  579. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  580. hInf,
  581. hProfile,
  582. dwNewOption,
  583. GpoID
  584. );
  585. if ( rc != SCESTATUS_SUCCESS ) {
  586. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  587. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szDSSecurity);
  588. goto CleanUp;
  589. }
  590. #endif
  591. if ( Area & AREA_SYSTEM_SERVICE ) {
  592. //
  593. // Service General Settings
  594. //
  595. rc = SceConvertpInfObject(
  596. szServiceGeneral,
  597. 0,
  598. ObjectFlag,
  599. hInf,
  600. hProfile,
  601. dwNewOption,
  602. GpoID
  603. );
  604. if ( rc != SCESTATUS_SUCCESS ) {
  605. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  606. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szServiceGeneral);
  607. goto CleanUp;
  608. }
  609. //
  610. // each service's specific settings
  611. //
  612. rc = SceConvertpAttachmentSections(hInf,
  613. hProfile,
  614. dwNewOption,
  615. GpoID,
  616. SCE_ATTACHMENT_SERVICE);
  617. if ( rc != SCESTATUS_SUCCESS ) {
  618. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  619. SCEDLL_SAP_ERROR_ENUMERATE, L"service attachments.");
  620. goto CleanUp;
  621. }
  622. }
  623. if ( (Area & AREA_ATTACHMENTS) ) {
  624. //
  625. // each service's specific settings
  626. //
  627. rc = SceConvertpWMIAttachmentSections(hInf,
  628. hProfile,
  629. dwNewOption,
  630. GpoID
  631. );
  632. if ( rc != SCESTATUS_SUCCESS ) {
  633. goto CleanUp;
  634. }
  635. }
  636. if ( Area & AREA_PRIVILEGES ) {
  637. //
  638. // Multi-Sz type - privilege/rights
  639. //
  640. rc = SceConvertpInfKeyValue(
  641. szPrivilegeRights,
  642. hInf,
  643. hProfile,
  644. dwNewOption,
  645. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_PRIV,
  646. GpoID,
  647. NULL
  648. );
  649. if ( rc != SCESTATUS_SUCCESS ) {
  650. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  651. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szPrivilegeRights);
  652. goto CleanUp;
  653. }
  654. }
  655. if ( Area & AREA_GROUP_MEMBERSHIP ) {
  656. // group membership
  657. rc = SceConvertpInfKeyValue(
  658. szGroupMembership,
  659. hInf,
  660. hProfile,
  661. dwNewOption,
  662. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_GROUP,
  663. GpoID,
  664. NULL
  665. );
  666. if ( rc != SCESTATUS_SUCCESS ) {
  667. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  668. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szGroupMembership);
  669. goto CleanUp;
  670. }
  671. }
  672. //
  673. // if there is a description, convert it.
  674. //
  675. SceConvertpInfDescription(
  676. hInf,
  677. hProfile);
  678. if ( !(Options & SCE_POLICY_TEMPLATE) ) {
  679. //
  680. // Commit changes
  681. //
  682. SceJetCommitTransaction( hProfile, 0 );
  683. } else if ( Options & SCE_POLICY_LAST ) {
  684. //
  685. // update the LastUsedMergeTable field
  686. //
  687. DWORD dwThisTable = hProfile->Type & 0xF0L;
  688. if ( SCEJET_MERGE_TABLE_1 == dwThisTable ||
  689. SCEJET_MERGE_TABLE_2 == dwThisTable ) {
  690. rc = SceJetSetValueInVersion(
  691. hProfile,
  692. "SmTblVersion",
  693. "LastUsedMergeTable",
  694. (PWSTR)&dwThisTable,
  695. 4,
  696. JET_prepReplace
  697. );
  698. }
  699. }
  700. CleanUp:
  701. //
  702. // close the inf profile
  703. //
  704. SceInfpCloseProfile(hInf);
  705. if ( pProfileList != NULL ) {
  706. ScepFreeNameList(pProfileList);
  707. }
  708. //
  709. // Rollback
  710. //
  711. if ( !(Options & SCE_POLICY_TEMPLATE) &&
  712. (RpcStatus == RPC_S_OK) &&
  713. (rc != SCESTATUS_SUCCESS) ) {
  714. SceJetRollback( hProfile, 0 );
  715. }
  716. //
  717. // Close the JET database
  718. //
  719. SceJetCloseFile( hProfile, TRUE, FALSE );
  720. if ( RpcStatus != RPC_S_OK ) {
  721. rc = I_RpcMapWin32Status(RpcStatus);
  722. }
  723. return(rc);
  724. }
  725. SCESTATUS
  726. SceConvertpAttachmentSections(
  727. IN HINF hInf,
  728. IN PSCECONTEXT hProfile,
  729. IN DWORD dwTableOption,
  730. IN LONG GpoID,
  731. IN SCE_ATTACHMENT_TYPE aType
  732. )
  733. {
  734. SCESTATUS rc;
  735. PSCE_SERVICES pServiceList=NULL, pNode;
  736. rc = ScepEnumServiceEngines( &pServiceList, aType );
  737. if ( rc == SCESTATUS_SUCCESS ) {
  738. for ( pNode=pServiceList; pNode != NULL; pNode=pNode->Next) {
  739. rc = SceConvertpOneAttachmentSection(hInf,
  740. hProfile,
  741. pNode->ServiceName,
  742. dwTableOption,
  743. GpoID
  744. );
  745. if ( rc != SCESTATUS_SUCCESS ) {
  746. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  747. SCEDLL_ERROR_CONVERT_SECTION, pNode->ServiceName );
  748. break;
  749. }
  750. }
  751. SceFreePSCE_SERVICES(pServiceList);
  752. } else if ( rc == SCESTATUS_PROFILE_NOT_FOUND ||
  753. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  754. // if no service exist, just ignore
  755. rc = SCESTATUS_SUCCESS;
  756. }
  757. return(rc);
  758. }
  759. SCESTATUS
  760. SceConvertpWMIAttachmentSections(
  761. IN HINF hInf,
  762. IN PSCECONTEXT hProfile,
  763. IN DWORD dwTableOption,
  764. IN LONG GpoID
  765. )
  766. {
  767. SCESTATUS rc=SCESTATUS_SUCCESS;
  768. INFCONTEXT InfLine;
  769. WCHAR SectionName[513];
  770. DWORD DataSize=0;
  771. if ( SetupFindFirstLine(hInf, szAttachments,NULL,&InfLine) ) {
  772. do {
  773. memset(SectionName, '\0', 513*sizeof(WCHAR));
  774. // get each attachment section name
  775. if(SetupGetStringField(&InfLine, 0, SectionName, 512, &DataSize) ) {
  776. rc = SceConvertpOneAttachmentSection(hInf,
  777. hProfile,
  778. SectionName,
  779. dwTableOption,
  780. GpoID
  781. );
  782. if ( rc != SCESTATUS_SUCCESS ) {
  783. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  784. SCEDLL_ERROR_CONVERT_SECTION, SectionName );
  785. break;
  786. }
  787. } else {
  788. rc = ScepDosErrorToSceStatus(GetLastError());
  789. }
  790. } while ( rc == SCESTATUS_SUCCESS &&
  791. SetupFindNextLine(&InfLine, &InfLine));
  792. }
  793. return(rc);
  794. }
  795. SCESTATUS
  796. SceConvertpOneAttachmentSection(
  797. IN HINF hInf,
  798. IN PSCECONTEXT hProfile,
  799. IN PWSTR SectionName,
  800. IN DWORD dwTableOption,
  801. IN LONG GpoID
  802. )
  803. {
  804. SCESTATUS rc;
  805. PSCESVC_CONFIGURATION_INFO pServiceInfo=NULL;
  806. //
  807. // read inf info for the service
  808. //
  809. rc = SceSvcpGetInformationTemplate(
  810. hInf,
  811. SectionName,
  812. NULL, // not a single key
  813. &pServiceInfo
  814. );
  815. if ( rc == SCESTATUS_SUCCESS && pServiceInfo != NULL ) {
  816. //
  817. // write the information to SCP or SMP table
  818. //
  819. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  820. rc = SceSvcpSetInfo(
  821. hProfile,
  822. SceSvcInternalUse,
  823. SectionName,
  824. NULL,
  825. TRUE, // to support incremental template, DO NOT overwrite the whole section
  826. GpoID,
  827. pServiceInfo
  828. );
  829. } else {
  830. rc = SceSvcpSetInfo(
  831. hProfile,
  832. SceSvcConfigurationInfo,
  833. SectionName,
  834. NULL,
  835. TRUE, // to support incremental template, DO NOT overwrite the whole section
  836. 0,
  837. pServiceInfo
  838. );
  839. }
  840. //
  841. // free buffer
  842. //
  843. SceSvcpFreeMemory(pServiceInfo);
  844. pServiceInfo = NULL;
  845. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  846. rc = SCESTATUS_SUCCESS;
  847. }
  848. return(rc);
  849. }
  850. SCESTATUS
  851. SceConvertpInfKeyValue(
  852. IN PCWSTR InfSectionName,
  853. IN HINF hInf,
  854. IN PSCECONTEXT hProfile,
  855. IN DWORD dwTableOption,
  856. IN DWORD dwConvertOption,
  857. IN LONG GpoID,
  858. OUT PSCE_NAME_LIST *pKeyList OPTIONAL
  859. )
  860. /* ++
  861. Routine Description:
  862. This routine converts INF sections which are in a key=value format. Value
  863. could be in MultiSz format (dwConvertOption & SCE_CONVERT_INF_MULTISZ).
  864. The optional pKeyList is a list of all keys in the section. This option
  865. is used when dynamic sections are converted.
  866. Arguments:
  867. InfSectionName - the INF section name to convert
  868. hInf - the Inf file handle
  869. hprofile - the Jet database context
  870. dwTableOption - SCE_TABLE_OPTION_MERGE_POLICY = within policy propagation
  871. SCE_TABLE_OPTION_TATTOO - system db (in setup)
  872. dwConvertOption - SCE_CONVERT_INF_MULTISZ - MultiSz type value
  873. SCE_CONVERT_INF_PRIV - user right section
  874. SCE_CONVERT_INF_GROUP - group membership section
  875. GpoID - the group policy ID for this item
  876. pKeyList - a list of all keys in the section.
  877. Return Value:
  878. -- */
  879. {
  880. SCESTATUS rc;
  881. DOUBLE SectionID;
  882. PSCESECTION hSection=NULL;
  883. PSCESECTION hSectionTattoo=NULL;
  884. INFCONTEXT InfLine;
  885. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  886. PWSTR pSidStr=NULL;
  887. PWSTR pKeyStr=NULL;
  888. PWSTR StrValue=NULL;
  889. DWORD ValueLen=0;
  890. LSA_HANDLE LsaPolicy=NULL;
  891. DWORD Len=0;
  892. if ( InfSectionName == NULL ||
  893. hInf == INVALID_HANDLE_VALUE ||
  894. hProfile == NULL ) {
  895. return(SCESTATUS_INVALID_PARAMETER);
  896. }
  897. //
  898. // get section's ID. if the section does not exist, add it to the section table
  899. //
  900. rc = SceJetGetSectionIDByName(
  901. hProfile,
  902. InfSectionName,
  903. &SectionID
  904. );
  905. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  906. rc = SceJetAddSection(
  907. hProfile,
  908. InfSectionName,
  909. &SectionID
  910. );
  911. }
  912. if ( rc != SCESTATUS_SUCCESS ) {
  913. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  914. SCEDLL_ERROR_QUERY_INFO, (PWSTR)InfSectionName );
  915. return(rc);
  916. }
  917. if ( SetupFindFirstLine(hInf,InfSectionName,NULL,&InfLine) ) {
  918. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  919. //
  920. // open the SCP section
  921. //
  922. rc = SceJetOpenSection(
  923. hProfile,
  924. SectionID,
  925. SCEJET_TABLE_SCP,
  926. &hSection
  927. );
  928. } else {
  929. //
  930. // open SMP table
  931. //
  932. rc = SceJetOpenSection(
  933. hProfile,
  934. SectionID,
  935. SCEJET_TABLE_SMP,
  936. &hSection
  937. );
  938. //
  939. // open the tattoo (in order to update tattoo value in setup)
  940. // do not care error
  941. //
  942. if ( dwTableOption & SCE_TABLE_OPTION_TATTOO )
  943. SceJetOpenSection(hProfile, SectionID,
  944. SCEJET_TABLE_TATTOO,
  945. &hSectionTattoo);
  946. }
  947. if ( rc != SCESTATUS_SUCCESS ) {
  948. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  949. SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
  950. if (hSection != NULL )
  951. SceJetCloseSection( &hSection, TRUE);
  952. if (hSectionTattoo != NULL )
  953. SceJetCloseSection( &hSectionTattoo, TRUE);
  954. return(rc);
  955. }
  956. //
  957. // Open LSA policy handle for group name lookup, if any
  958. // if policy handle can't be opened, import name format
  959. //
  960. if ( dwConvertOption & SCE_CONVERT_INF_GROUP ) {
  961. ScepOpenLsaPolicy(
  962. MAXIMUM_ALLOWED,
  963. &LsaPolicy,
  964. TRUE
  965. );
  966. }
  967. //
  968. // process each line in the section and save to the scp table.
  969. // Each INF line has a key and a value.
  970. //
  971. do {
  972. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(TCHAR));
  973. rc = SCESTATUS_BAD_FORMAT;
  974. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  975. //
  976. // check if newer version (keys) are passed
  977. //
  978. if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
  979. if ( dwConvertOption & SCE_CONVERT_INF_PRIV ) {
  980. //
  981. // user rights from new version
  982. // filter out all unknown rights
  983. //
  984. if ( -1 == ScepLookupPrivByName(Keyname) ) {
  985. rc = SCESTATUS_SUCCESS;
  986. goto NextLine;
  987. }
  988. } else if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
  989. //
  990. // convert registry values, should check number of fields
  991. //
  992. if ( SetupGetFieldCount( &InfLine ) < 2 ) {
  993. rc = SCESTATUS_SUCCESS;
  994. goto NextLine;
  995. }
  996. }
  997. }
  998. if ( (dwConvertOption & SCE_CONVERT_INF_GROUP) &&
  999. ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ||
  1000. (Keyname[0] != L'*') ) ) {
  1001. //
  1002. // this is a group in name format
  1003. //
  1004. PWSTR pTemp = (PWSTR)Keyname;
  1005. //
  1006. // search for the suffix (szMembers or szMemberof or szPrivileges)
  1007. //
  1008. while ( pTemp = wcsstr(pTemp, szMembers) ) {
  1009. if ( *(pTemp+wcslen(szMembers)) != L'\0') {
  1010. pTemp++;
  1011. ValueLen = 0;
  1012. } else {
  1013. break;
  1014. }
  1015. }
  1016. if ( pTemp == NULL ) {
  1017. pTemp = (PWSTR)Keyname;
  1018. while ( pTemp = wcsstr(pTemp, szMemberof) ) {
  1019. if ( *(pTemp+wcslen(szMemberof)) != L'\0') {
  1020. pTemp++;
  1021. ValueLen = 1;
  1022. } else {
  1023. break;
  1024. }
  1025. }
  1026. if ( pTemp == NULL ) {
  1027. pTemp = (PWSTR)Keyname;
  1028. while ( pTemp = wcsstr(pTemp, szPrivileges) ) {
  1029. if ( *(pTemp+wcslen(szPrivileges)) != L'\0') {
  1030. pTemp++;
  1031. ValueLen = 2;
  1032. } else {
  1033. break;
  1034. }
  1035. }
  1036. }
  1037. }
  1038. if ( pTemp == NULL ) {
  1039. //
  1040. // this is an unknown group format, just import the keyname
  1041. // for supported version; for new version template, ignore
  1042. // this line
  1043. //
  1044. if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
  1045. rc = SCESTATUS_SUCCESS;
  1046. goto NextLine;
  1047. }
  1048. } else if ( Keyname[0] != L'*' ) {
  1049. *pTemp = L'\0';
  1050. PWSTR pTemp1 = wcschr(Keyname, L'\\');
  1051. Len=0;
  1052. if ( pTemp1 && LsaPolicy ) {
  1053. //
  1054. // convert group name (domain\account) into *SID format
  1055. //
  1056. ScepConvertNameToSidString(
  1057. LsaPolicy,
  1058. Keyname,
  1059. FALSE,
  1060. &pSidStr,
  1061. &Len
  1062. );
  1063. } else if ( !pTemp1 ) {
  1064. if ( !ScepLookupNameTable( Keyname, &pSidStr ) ) {
  1065. //
  1066. // check in the constant SID table first
  1067. //
  1068. pSidStr = NULL;
  1069. if ( LsaPolicy) {
  1070. //
  1071. // free text group name, resolve it
  1072. //
  1073. ScepConvertNameToSidString(
  1074. LsaPolicy,
  1075. Keyname,
  1076. FALSE,
  1077. &pSidStr,
  1078. &Len
  1079. );
  1080. }
  1081. } else {
  1082. Len = wcslen(pSidStr);
  1083. }
  1084. }
  1085. //
  1086. // restore the "_"
  1087. //
  1088. *pTemp = L'_';
  1089. if ( pSidStr ) {
  1090. //
  1091. // add the suffix
  1092. //
  1093. pKeyStr = (PWSTR)ScepAlloc(0, (Len+wcslen(pTemp)+1)*sizeof(WCHAR));
  1094. if ( pKeyStr ) {
  1095. wcscpy(pKeyStr, pSidStr);
  1096. wcscat(pKeyStr, pTemp);
  1097. } else {
  1098. //
  1099. // use the name instead - out of memory will be caught later
  1100. //
  1101. }
  1102. ScepFree(pSidStr);
  1103. pSidStr = NULL;
  1104. }
  1105. }
  1106. }
  1107. if ( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1108. SetupGetMultiSzField(&InfLine, 1, NULL, 0, &ValueLen)) ||
  1109. (!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1110. SetupGetStringField(&InfLine, 1, NULL, 0, &ValueLen)) ) {
  1111. if ( ValueLen > 1 ) {
  1112. StrValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1113. (ValueLen+1)*sizeof(TCHAR));
  1114. if( StrValue == NULL ) {
  1115. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1116. } else if( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1117. SetupGetMultiSzField(&InfLine, 1, StrValue, ValueLen, NULL)) ||
  1118. (!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1119. SetupGetStringField(&InfLine,1,StrValue,ValueLen,NULL)) ) {
  1120. //
  1121. // if dealing with registry values only, do the following:
  1122. // compress regtype into one CHAR instead of many WCHARS
  1123. // (can canonicalize REG_QWORD value later by arithmetic padding etc.- doesn't
  1124. // make sense now since registry api's treat REG_QWORD as a string anyway)
  1125. //
  1126. if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
  1127. DWORD LenStrValue = wcslen(StrValue);
  1128. if (LenStrValue > 1) {
  1129. *((CHAR *)StrValue) = (CHAR) (_wtol(StrValue) + '0');
  1130. memmove( StrValue+1,
  1131. StrValue + LenStrValue,
  1132. sizeof(WCHAR) * (ValueLen - LenStrValue));
  1133. ValueLen -= (LenStrValue - 1);
  1134. }
  1135. }
  1136. rc = SCESTATUS_SUCCESS;
  1137. } else {
  1138. ScepFree(StrValue);
  1139. StrValue = NULL;
  1140. }
  1141. } else {
  1142. rc = SCESTATUS_SUCCESS;
  1143. ValueLen = 0;
  1144. }
  1145. PWSTR NewValue=NULL;
  1146. DWORD NewLen=0;
  1147. if ( rc == SCESTATUS_SUCCESS ) {
  1148. if ( (dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1149. StrValue != NULL &&
  1150. (dwConvertOption & SCE_CONVERT_INF_PRIV) &&
  1151. ( _wcsicmp(SCE_PRIV_ADD, StrValue) == 0 ||
  1152. _wcsicmp(SCE_PRIV_REMOVE, StrValue) == 0) ) {
  1153. //
  1154. // another format for user rights (ADD: REMOVE:...)
  1155. //
  1156. rc = ScepBuildNewPrivilegeList(&LsaPolicy,
  1157. Keyname,
  1158. StrValue,
  1159. SCE_BUILD_ENUMERATE_PRIV,
  1160. &NewValue,
  1161. &NewLen);
  1162. if ( rc == SCESTATUS_SUCCESS ) {
  1163. ScepFree(StrValue);
  1164. StrValue = NewValue;
  1165. ValueLen = NewLen;
  1166. }
  1167. }
  1168. }
  1169. if ( ( rc == SCESTATUS_SUCCESS) &&
  1170. !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  1171. StrValue &&
  1172. ( (dwConvertOption & SCE_CONVERT_INF_PRIV) ||
  1173. (dwConvertOption & SCE_CONVERT_INF_GROUP)) ) {
  1174. //
  1175. // convert any free text format accounts from account domain
  1176. // to sid format if it's resolvable.
  1177. //
  1178. NewValue = NULL;
  1179. NewLen = 0;
  1180. rc = ScepConvertFreeTextAccountToSid(&LsaPolicy,
  1181. StrValue,
  1182. ValueLen,
  1183. &NewValue,
  1184. &NewLen);
  1185. if ( ( rc == SCESTATUS_SUCCESS) &&
  1186. NewValue ) {
  1187. ScepFree(StrValue);
  1188. StrValue = NewValue;
  1189. ValueLen = NewLen;
  1190. }
  1191. }
  1192. if ( rc == SCESTATUS_SUCCESS ) {
  1193. //
  1194. // write this line to JET database
  1195. // within policy propagation, write the GPOID too
  1196. //
  1197. rc = SceJetSetLine(
  1198. hSection,
  1199. pKeyStr ? pKeyStr : Keyname,
  1200. FALSE,
  1201. StrValue,
  1202. ValueLen*sizeof(TCHAR),
  1203. (dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
  1204. );
  1205. if ( rc != SCESTATUS_SUCCESS ) {
  1206. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1207. SCEDLL_ERROR_WRITE_INFO, Keyname);
  1208. }
  1209. //
  1210. // if this is not policy propagation and it's the system db,
  1211. // check if the tattoo value exists and if so, update it
  1212. // but if this is in dc demotion, always import them into the
  1213. // tattoo table so at reboot when policy propagates, it would
  1214. // reset the system settings to a standalone server
  1215. //
  1216. if ( !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  1217. (dwTableOption & SCE_TABLE_OPTION_TATTOO) &&
  1218. hSectionTattoo ) {
  1219. if ( pKeyStr )
  1220. Len = wcslen(pKeyStr);
  1221. else
  1222. Len = wcslen(Keyname);
  1223. if ( (dwTableOption & SCE_TABLE_OPTION_DEMOTE_TATTOO) ||
  1224. (SCESTATUS_SUCCESS == SceJetSeek(
  1225. hSectionTattoo,
  1226. pKeyStr ? pKeyStr : Keyname,
  1227. Len*sizeof(WCHAR),
  1228. SCEJET_SEEK_EQ_NO_CASE)) ) {
  1229. SceJetSetLine(
  1230. hSectionTattoo,
  1231. pKeyStr ? pKeyStr : Keyname,
  1232. FALSE,
  1233. StrValue,
  1234. ValueLen*sizeof(TCHAR),
  1235. 0
  1236. );
  1237. }
  1238. }
  1239. ScepFree(StrValue);
  1240. StrValue = NULL;
  1241. if (pKeyList != NULL) {
  1242. if ( (rc=ScepAddToNameList(pKeyList, Keyname,0)) != NO_ERROR ) {
  1243. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_ADD, Keyname);
  1244. rc = ScepDosErrorToSceStatus(rc);
  1245. ScepFreeNameList(*pKeyList);
  1246. }
  1247. }
  1248. }
  1249. }
  1250. if ( pKeyStr ) {
  1251. ScepFree(pKeyStr);
  1252. pKeyStr = NULL;
  1253. }
  1254. NextLine:
  1255. if (rc != SCESTATUS_SUCCESS)
  1256. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  1257. SCEDLL_ERROR_CONVERT, Keyname);
  1258. }
  1259. } while( rc == SCESTATUS_SUCCESS && SetupFindNextLine(&InfLine, &InfLine));
  1260. SceJetCloseSection( &hSection, TRUE);
  1261. if ( hSectionTattoo )
  1262. SceJetCloseSection( &hSectionTattoo, TRUE);
  1263. }
  1264. if ( LsaPolicy ) {
  1265. LsaClose(LsaPolicy);
  1266. }
  1267. return(rc);
  1268. }
  1269. SCESTATUS
  1270. ScepBuildNewPrivilegeList(
  1271. IN OUT LSA_HANDLE *pPolicyHandle,
  1272. IN PWSTR PrivName,
  1273. IN PWSTR mszUsers,
  1274. IN ULONG dwBuildOption,
  1275. OUT PWSTR *pmszNewUsers,
  1276. OUT DWORD *pNewLen
  1277. )
  1278. {
  1279. if ( pPolicyHandle == NULL ||
  1280. PrivName == NULL || mszUsers == NULL ||
  1281. pmszNewUsers == NULL || pNewLen == NULL ) {
  1282. return(SCESTATUS_INVALID_PARAMETER);
  1283. }
  1284. *pNewLen = 0;
  1285. *pmszNewUsers = NULL;
  1286. //
  1287. // lookup the priv first
  1288. //
  1289. DWORD PrivValue = ScepLookupPrivByName(PrivName);
  1290. if ( PrivValue == -1 || PrivValue >= 64 ) {
  1291. return(SCESTATUS_INVALID_DATA);
  1292. }
  1293. NTSTATUS NtStatus=STATUS_SUCCESS;
  1294. if ( *pPolicyHandle == NULL ) {
  1295. NtStatus = ScepOpenLsaPolicy(
  1296. MAXIMUM_ALLOWED, //GENERIC_ALL,
  1297. pPolicyHandle,
  1298. TRUE
  1299. );
  1300. if ( !NT_SUCCESS(NtStatus) ) {
  1301. return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
  1302. }
  1303. }
  1304. PSCE_PRIVILEGE_VALUE_LIST pAccountList=NULL;
  1305. if ( dwBuildOption & SCE_BUILD_ENUMERATE_PRIV ) {
  1306. NtStatus = ScepBuildAccountsToRemove(
  1307. *pPolicyHandle,
  1308. (PrivValue < 32) ? (1 << PrivValue) : 0,
  1309. (PrivValue >= 32) ? (1 << (PrivValue-32)) : 0,
  1310. SCE_BUILD_IGNORE_UNKNOWN | SCE_BUILD_ACCOUNT_SID_STRING,
  1311. NULL,
  1312. 0,
  1313. NULL,
  1314. &pAccountList
  1315. );
  1316. }
  1317. SCESTATUS rc=SCESTATUS_SUCCESS;
  1318. if ( NT_SUCCESS(NtStatus) ) {
  1319. //
  1320. // pAccountList can be NULL (no users are assigned of this privilege)
  1321. //
  1322. PWSTR pCurr = mszUsers;
  1323. BOOL bMode = FALSE; // add
  1324. DWORD Len;
  1325. DWORD SidStrLen;
  1326. PWSTR CurrSidString=NULL;
  1327. PSCE_PRIVILEGE_VALUE_LIST pTemp, pParent;
  1328. BOOL bFreeCurrSidString = FALSE;
  1329. while ( pCurr && *pCurr != L'\0' ) {
  1330. Len = wcslen(pCurr);
  1331. if ( _wcsicmp(SCE_PRIV_ADD, pCurr) == 0 ) {
  1332. bMode = FALSE; // add
  1333. } else if ( _wcsicmp(SCE_PRIV_REMOVE, pCurr) == 0 ) {
  1334. bMode = TRUE; // remove
  1335. } else {
  1336. //
  1337. // get SID string for the account if it's a name
  1338. //
  1339. if (*pCurr == L'*') {
  1340. CurrSidString = pCurr;
  1341. SidStrLen = Len;
  1342. }
  1343. else if (SCESTATUS_SUCCESS == ScepConvertNameToSidString(
  1344. *pPolicyHandle,
  1345. pCurr,
  1346. FALSE,
  1347. &CurrSidString,
  1348. &SidStrLen
  1349. )) {
  1350. bFreeCurrSidString = TRUE;
  1351. }
  1352. else {
  1353. CurrSidString = pCurr;
  1354. SidStrLen = Len;
  1355. }
  1356. for ( pTemp=pAccountList, pParent=NULL; pTemp != NULL;
  1357. pParent=pTemp, pTemp = pTemp->Next ) {
  1358. if ( _wcsicmp(pTemp->Name, CurrSidString) == 0 ) {
  1359. break;
  1360. }
  1361. }
  1362. if ( bMode == FALSE ) {
  1363. if ( pTemp == NULL ) {
  1364. // add this one in
  1365. rc = ScepAddToPrivilegeList(&pAccountList, CurrSidString, SidStrLen, 0);
  1366. }
  1367. } else {
  1368. if ( pTemp ) {
  1369. // remove this one out
  1370. if ( pParent ) {
  1371. pParent->Next = pTemp->Next;
  1372. } else {
  1373. pAccountList = pTemp->Next;
  1374. }
  1375. // free this one
  1376. pTemp->Next = NULL;
  1377. ScepFreePrivilegeValueList(pTemp);
  1378. pTemp = NULL;
  1379. }
  1380. }
  1381. }
  1382. //
  1383. // free CurrSidString if it's allocated
  1384. // (BVT: have to be careful here - MULTI_SZ potentially being freed many times)
  1385. //
  1386. if ( bFreeCurrSidString ) {
  1387. LocalFree(CurrSidString);
  1388. CurrSidString = NULL;
  1389. bFreeCurrSidString = FALSE;
  1390. }
  1391. SidStrLen = 0;
  1392. if ( SCESTATUS_SUCCESS != rc ) {
  1393. break;
  1394. }
  1395. // move to next element
  1396. pCurr += Len + 1;
  1397. }
  1398. if ( SCESTATUS_SUCCESS == rc ) {
  1399. DWORD TotalLen = 0;
  1400. for ( pTemp=pAccountList; pTemp != NULL; pTemp = pTemp->Next ) {
  1401. pTemp->PrivLowPart = wcslen(pTemp->Name);
  1402. TotalLen += pTemp->PrivLowPart+1;
  1403. }
  1404. *pmszNewUsers = (PWSTR)ScepAlloc(0, (TotalLen+1)*sizeof(WCHAR));
  1405. if (*pmszNewUsers ) {
  1406. *pNewLen = TotalLen;
  1407. TotalLen = 0;
  1408. for ( pTemp=pAccountList; pTemp != NULL && TotalLen <= *pNewLen;
  1409. pTemp = pTemp->Next ) {
  1410. wcscpy(*pmszNewUsers+TotalLen, pTemp->Name);
  1411. TotalLen += pTemp->PrivLowPart;
  1412. *(*pmszNewUsers+TotalLen) = L'\0';
  1413. TotalLen++;
  1414. }
  1415. *(*pmszNewUsers+TotalLen) = L'\0';
  1416. } else {
  1417. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1418. }
  1419. }
  1420. } else {
  1421. rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus));
  1422. }
  1423. return(rc);
  1424. }
  1425. SCESTATUS
  1426. SceConvertpInfObject(
  1427. IN PCWSTR InfSectionName,
  1428. IN UINT ObjectType,
  1429. IN DWORD ObjectFlag,
  1430. IN HINF hInf,
  1431. IN PSCECONTEXT hProfile,
  1432. IN DWORD dwTableOption,
  1433. IN LONG GpoID
  1434. )
  1435. /* ++
  1436. Routine Description:
  1437. This routine converts INF sections which are in object-security format,
  1438. for example, Registry Keys and File Security sections. These sections
  1439. must have 3 fields on each line. The first field is the object's name,
  1440. the second field is a status flag, and the third field is the security
  1441. descriptor text. The infomration saved in the Jet database for each
  1442. object is the object's name as the key, and the text format security
  1443. descriptor plus 1 byte status flag as the value.
  1444. Arguments:
  1445. InfSectionName - the INF section name to convert
  1446. ObjectType - The object's type
  1447. 1 = Registry
  1448. 2 = File
  1449. 3 = DS object
  1450. hInf - the Inf file handle
  1451. hprofile - the Jet database context
  1452. Return Value:
  1453. -- */
  1454. {
  1455. SCESTATUS rc;
  1456. DOUBLE SectionID;
  1457. PSCESECTION hSection=NULL;
  1458. PSCESECTION hSectionTattoo=NULL;
  1459. INFCONTEXT InfLine;
  1460. PWSTR TempName=NULL;
  1461. PWSTR Name=NULL;
  1462. PWSTR Value=NULL;
  1463. DWORD ValueLen;
  1464. SCEINF_STATUS InfErr;
  1465. TCHAR ObjName[MAX_PATH];
  1466. if ( InfSectionName == NULL ||
  1467. hInf == INVALID_HANDLE_VALUE ||
  1468. hProfile == NULL ) {
  1469. return(SCESTATUS_INVALID_PARAMETER);
  1470. }
  1471. //
  1472. // get section's ID. if the section does not exist, add it to the section table
  1473. //
  1474. rc = SceJetGetSectionIDByName(
  1475. hProfile,
  1476. InfSectionName,
  1477. &SectionID
  1478. );
  1479. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  1480. rc = SceJetAddSection(
  1481. hProfile,
  1482. InfSectionName,
  1483. &SectionID
  1484. );
  1485. }
  1486. if ( rc != SCESTATUS_SUCCESS ) {
  1487. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1488. SCEDLL_SCP_ERROR_ADD, (PWSTR)InfSectionName);
  1489. return(rc);
  1490. }
  1491. if ( SetupFindFirstLine(hInf,InfSectionName,NULL,&InfLine) ) {
  1492. //
  1493. // open the section
  1494. //
  1495. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  1496. rc = SceJetOpenSection(
  1497. hProfile,
  1498. SectionID,
  1499. SCEJET_TABLE_SCP,
  1500. &hSection
  1501. );
  1502. } else {
  1503. //
  1504. // SMP exists, also open the SMP section
  1505. //
  1506. rc = SceJetOpenSection(
  1507. hProfile,
  1508. SectionID,
  1509. SCEJET_TABLE_SMP,
  1510. &hSection
  1511. );
  1512. if ( dwTableOption & SCE_TABLE_OPTION_TATTOO ) {
  1513. //
  1514. // if it's in setup, should check if tattoo table needs to be updated
  1515. // do not care error
  1516. //
  1517. SceJetOpenSection(
  1518. hProfile,
  1519. SectionID,
  1520. SCEJET_TABLE_TATTOO,
  1521. &hSectionTattoo
  1522. );
  1523. }
  1524. }
  1525. if ( rc != SCESTATUS_SUCCESS ) {
  1526. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1527. SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
  1528. if ( hSection )
  1529. SceJetCloseSection( &hSection, TRUE);
  1530. if ( hSectionTattoo )
  1531. SceJetCloseSection( &hSectionTattoo, TRUE);
  1532. return(rc);
  1533. }
  1534. //
  1535. // process each line in the section and save to the scp table.
  1536. //
  1537. BOOL bIgnore;
  1538. do {
  1539. //
  1540. // Get string fields. Don't care the key name or if it exist.
  1541. // Must have at least 3 fields each line.
  1542. //
  1543. bIgnore = FALSE;
  1544. InfErr = SceInfpGetOneObject(&InfLine,
  1545. ObjectFlag,
  1546. &TempName,
  1547. &Value,
  1548. &ValueLen
  1549. );
  1550. rc = ScepDosErrorToSceStatus(InfErr);
  1551. if ( rc == SCESTATUS_SUCCESS && TempName != NULL ) {
  1552. //
  1553. // check to see if the object name needs translated
  1554. //
  1555. if ( ObjectType == 3 ) {
  1556. //
  1557. // DS object
  1558. //
  1559. rc = ScepConvertLdapToJetIndexName(TempName, &Name);
  1560. } else if ( ObjectType == 2 && TempName[0] == L'\\' ) {
  1561. //
  1562. // do not support UNC name format
  1563. //
  1564. rc = SCESTATUS_INVALID_DATA;
  1565. } else if ( ObjectType == 2 && wcschr(TempName, L'%') != NULL ) {
  1566. //
  1567. // translate the name
  1568. //
  1569. rc = ScepTranslateFileDirName( TempName, &Name);
  1570. if ( rc == ERROR_PATH_NOT_FOUND ) {
  1571. if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION )
  1572. bIgnore = TRUE;
  1573. rc = SCESTATUS_INVALID_DATA;
  1574. } else if ( rc != NO_ERROR )
  1575. rc = ScepDosErrorToSceStatus(rc);
  1576. } else {
  1577. Name = TempName;
  1578. TempName = NULL;
  1579. }
  1580. //
  1581. // write this line to JET database
  1582. //
  1583. if ( rc == SCESTATUS_SUCCESS ) {
  1584. //
  1585. // convert to lowercase
  1586. //
  1587. Name = _wcslwr(Name);
  1588. //
  1589. // within policy propagation, write the GPOID too
  1590. //
  1591. rc = SceJetSetLine(
  1592. hSection,
  1593. Name,
  1594. TRUE,
  1595. Value,
  1596. ValueLen*sizeof(TCHAR),
  1597. (dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
  1598. );
  1599. if ( hSectionTattoo &&
  1600. !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  1601. (dwTableOption & SCE_TABLE_OPTION_TATTOO ) ) {
  1602. //
  1603. // if it's in setup (not policy prop) and tattoo table exists
  1604. // check if tattoo value exists for this one and if so, update it
  1605. // do not care error
  1606. //
  1607. if ( SCESTATUS_SUCCESS == SceJetSeek(
  1608. hSectionTattoo,
  1609. Name,
  1610. wcslen(Name)*sizeof(WCHAR),
  1611. SCEJET_SEEK_EQ_NO_CASE) ) {
  1612. SceJetSetLine(
  1613. hSectionTattoo,
  1614. Name,
  1615. TRUE,
  1616. Value,
  1617. ValueLen*sizeof(TCHAR),
  1618. 0
  1619. );
  1620. }
  1621. }
  1622. }
  1623. if ( rc != SCESTATUS_SUCCESS) {
  1624. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1625. SCEDLL_ERROR_CONVERT, TempName );
  1626. }
  1627. ScepFree(Value);
  1628. Value = NULL;
  1629. ScepFree(TempName);
  1630. TempName = NULL;
  1631. ScepFree(Name);
  1632. Name = NULL;
  1633. } else if ( (ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION) &&
  1634. rc == SCESTATUS_SUCCESS && TempName == NULL ) {
  1635. //
  1636. // this one is ignored because it came from a newer version
  1637. // of template.
  1638. //
  1639. } else {
  1640. ObjName[0] = L'\0';
  1641. SetupGetStringField(&InfLine,1,ObjName,MAX_PATH,&ValueLen);
  1642. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1643. SCEDLL_ERROR_CONVERT, ObjName );
  1644. }
  1645. //
  1646. // for a newer version template, if a env variable can't be resolved
  1647. // it will be ignored.
  1648. //
  1649. if ( bIgnore ) rc = SCESTATUS_SUCCESS;
  1650. if ( SCESTATUS_INVALID_DATA == rc ) {
  1651. //
  1652. // if a environment variable or other invalid data is found
  1653. // in the template, will continue to process other areas/items
  1654. // but the error will be eventually returned to the caller
  1655. //
  1656. gbInvalidData = TRUE;
  1657. rc = SCESTATUS_SUCCESS;
  1658. }
  1659. if ( rc != SCESTATUS_SUCCESS )
  1660. break; // do..while loop
  1661. } while( SetupFindNextLine(&InfLine,&InfLine) );
  1662. SceJetCloseSection( &hSection, TRUE);
  1663. if ( hSectionTattoo ) SceJetCloseSection( &hSectionTattoo, TRUE);
  1664. }
  1665. return(rc);
  1666. }
  1667. SCEINF_STATUS
  1668. SceInfpGetOneObject(
  1669. IN PINFCONTEXT pInfLine,
  1670. IN DWORD ObjectFlag,
  1671. OUT PWSTR *Name,
  1672. OUT PWSTR *Value,
  1673. OUT PDWORD ValueLen
  1674. )
  1675. /* ++
  1676. Routine Description:
  1677. This routine retrieves security setting for one object (a registry key,
  1678. or a file) from the INF file (SCP type). Each object in these sections
  1679. is represented by one line. Each object has 3 fields, a name, status flag,
  1680. and a security setting.
  1681. Arguments:
  1682. pInfLine - Current line context from the INF file for one object
  1683. Name - The object name
  1684. Value - The status flag ( 1 byte) plus the security descriptor in text
  1685. ValueLen - the length of the value
  1686. Return value:
  1687. SCESTATUS - SCEINF_SUCCESS
  1688. SCEINF_WARNING
  1689. SCEINF_NOT_ENOUGH_MEMORY
  1690. SCEINF_INVALID_PARAMETER
  1691. SCEINF_CORRUPT_PROFILE
  1692. SCEINF_INVALID_DATA
  1693. -- */
  1694. {
  1695. SCEINF_STATUS rc=ERROR_BAD_FORMAT;
  1696. DWORD cFields;
  1697. INT Keyvalue1=0;
  1698. DWORD Keyvalue2=0;
  1699. DWORD DataSize;
  1700. PWSTR SDspec=NULL;
  1701. DWORD Len=0;
  1702. //
  1703. // The Registry/File INF layout must have 3 fields for each line.
  1704. // The first field is the key/file name, the 2nd field is the security descriptor index
  1705. // for workstations, and the 3rd field is the security descriptor index for servers
  1706. //
  1707. if ( Name == NULL || Value == NULL ) {
  1708. return(ERROR_INVALID_PARAMETER);
  1709. }
  1710. *Name = NULL;
  1711. *Value = NULL;
  1712. *ValueLen = 0;
  1713. cFields = SetupGetFieldCount( pInfLine );
  1714. if ( cFields < 3 ) {
  1715. if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION ) {
  1716. return(ERROR_SUCCESS);
  1717. } else {
  1718. return(ERROR_INVALID_DATA);
  1719. }
  1720. } else if(SetupGetStringField(pInfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
  1721. *Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1722. (DataSize+1)*sizeof(TCHAR) );
  1723. if( *Name == NULL ) {
  1724. return(ERROR_NOT_ENOUGH_MEMORY);
  1725. } else {
  1726. //
  1727. // the first field is the key/file name. the status is ERROR_BAD_FORMAT now
  1728. //
  1729. if(SetupGetStringField(pInfLine,1,*Name,DataSize,NULL)) {
  1730. #ifdef SCE_DBG
  1731. ScepLogOutput2(0,0, L"Read %s", *Name );
  1732. #endif
  1733. //
  1734. // The 2nd field is the status
  1735. // The 3rd field (and all fields after) is the security descriptor text
  1736. //
  1737. if ( SetupGetIntField(pInfLine, 2, (INT *)&Keyvalue1) &&
  1738. // SetupGetStringField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
  1739. SetupGetMultiSzField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
  1740. *Value = (PWSTR)ScepAlloc( 0, (Keyvalue2+2)*sizeof(WCHAR));
  1741. //
  1742. // add this object
  1743. //
  1744. if ( *Value == NULL ) {
  1745. rc = ERROR_NOT_ENOUGH_MEMORY;
  1746. // } else if ( SetupGetStringField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
  1747. } else if ( SetupGetMultiSzField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
  1748. if ( ObjectFlag & SCE_OBJECT_FLAG_OBJECTS ) {
  1749. if ( Keyvalue1 > SCE_STATUS_NO_AUTO_INHERIT ||
  1750. Keyvalue1 < SCE_STATUS_CHECK ) {
  1751. Keyvalue1 = SCE_STATUS_CHECK;
  1752. }
  1753. *((BYTE *)(*Value)) = (BYTE)Keyvalue1;
  1754. *((CHAR *)(*Value)+1) = '1'; //always treat as container
  1755. } else {
  1756. //
  1757. // services
  1758. //
  1759. if ( Keyvalue1 > SCE_STARTUP_DISABLED ||
  1760. Keyvalue1 < SCE_STARTUP_BOOT ) {
  1761. //
  1762. // default
  1763. //
  1764. Keyvalue1 = SCE_STARTUP_MANUAL;
  1765. }
  1766. *((BYTE *)(*Value)) = 0; // always set status to 0
  1767. *((BYTE *)(*Value)+1) = (BYTE)Keyvalue1;
  1768. }
  1769. //
  1770. // convert the multi-sz delimiter to space, if there is any
  1771. //
  1772. if ( cFields > 3 ) {
  1773. ScepConvertMultiSzToDelim( (*Value+1), Keyvalue2, L'\0', L' ');
  1774. }
  1775. if ( ObjectFlag & SCE_OBJECT_FLAG_OLDSDDL ) {
  1776. //
  1777. // convert old SDDL string to new one
  1778. //
  1779. ScepConvertToSDDLFormat( (*Value+1), Keyvalue2 );
  1780. }
  1781. *ValueLen = Keyvalue2+1;
  1782. rc = ERROR_SUCCESS;
  1783. } else {
  1784. ScepFree(*Value);
  1785. *Value = NULL;
  1786. rc = ERROR_INVALID_DATA;
  1787. }
  1788. }
  1789. }
  1790. // if error, free the memory allocated
  1791. if ( rc != ERROR_SUCCESS ) {
  1792. ScepFree(*Name);
  1793. *Name = NULL;
  1794. }
  1795. }
  1796. }
  1797. if ( rc == ERROR_SUCCESS) {
  1798. //
  1799. // conver the object name to upper case
  1800. //
  1801. // _wcsupr(*Name); should not do this..
  1802. }
  1803. return(rc);
  1804. }
  1805. SCESTATUS
  1806. SceConvertpInfDescription(
  1807. IN HINF hInf,
  1808. IN PSCECONTEXT hProfile
  1809. )
  1810. {
  1811. INFCONTEXT InfLine;
  1812. SCESTATUS rc=SCESTATUS_SUCCESS;
  1813. WCHAR Description[513];
  1814. DWORD Len=0;
  1815. DWORD DataSize=0;
  1816. DWORD i, cFields;
  1817. if ( hInf == INVALID_HANDLE_VALUE ||
  1818. hProfile == NULL ) {
  1819. return(SCESTATUS_INVALID_PARAMETER);
  1820. }
  1821. if ( SetupFindFirstLine(hInf,szDescription,NULL,&InfLine) ) {
  1822. memset(Description, '\0', 513*sizeof(WCHAR));
  1823. // get description from Inf
  1824. do {
  1825. cFields = SetupGetFieldCount( &InfLine );
  1826. for ( i=0; i<cFields && rc==SCESTATUS_SUCCESS; i++) {
  1827. if(SetupGetStringField(&InfLine, i+1, Description+Len, 512-Len, &DataSize) ) {
  1828. Len += DataSize;
  1829. if ( Len >= 512 ) {
  1830. Len = 512;
  1831. Description[512] = L'\0';
  1832. break;
  1833. }
  1834. if ( i == cFields-1 )
  1835. Description[Len-1] = L' ';
  1836. else
  1837. Description[Len-1] = L',';
  1838. } else
  1839. rc = SCESTATUS_INVALID_DATA;
  1840. }
  1841. if ( Len >= 512 )
  1842. break;
  1843. } while ( rc == SCESTATUS_SUCCESS &&
  1844. SetupFindNextLine(&InfLine, &InfLine));
  1845. if ( rc == SCESTATUS_SUCCESS && Description[0] ) {
  1846. //
  1847. // save description to Jet
  1848. // NOTE: Jet requires long value update must be done in a transaction
  1849. //
  1850. rc = SceJetStartTransaction( hProfile );
  1851. if ( SCESTATUS_SUCCESS == rc ) {
  1852. Description[Len] = L'\0';
  1853. rc = SceJetSetValueInVersion(
  1854. hProfile,
  1855. "SmTblVersion",
  1856. "ProfileDescription",
  1857. (PWSTR)Description,
  1858. Len*sizeof(WCHAR),
  1859. JET_prepReplace
  1860. );
  1861. if ( SCESTATUS_SUCCESS == rc ) {
  1862. SceJetCommitTransaction( hProfile, 0 );
  1863. } else {
  1864. SceJetRollback( hProfile, 0 );
  1865. }
  1866. }
  1867. }
  1868. }
  1869. return(rc);
  1870. }
  1871. SCESTATUS
  1872. ScepConvertFreeTextAccountToSid(
  1873. IN OUT LSA_HANDLE *pPolicyHandle,
  1874. IN PWSTR mszAccounts,
  1875. IN ULONG dwLen,
  1876. OUT PWSTR *pmszNewAccounts,
  1877. OUT DWORD *pNewLen
  1878. )
  1879. {
  1880. if ( pPolicyHandle == NULL ||
  1881. pmszNewAccounts == NULL || pNewLen == NULL ) {
  1882. return(SCESTATUS_INVALID_PARAMETER);
  1883. }
  1884. *pNewLen = 0;
  1885. *pmszNewAccounts = NULL;
  1886. PWSTR pCurr = mszAccounts;
  1887. DWORD cnt=0;
  1888. //
  1889. // count how many entries in the list
  1890. //
  1891. while ( pCurr && *pCurr != L'\0' ) {
  1892. cnt++;
  1893. pCurr += wcslen(pCurr)+1;
  1894. }
  1895. if ( cnt == 0 ) {
  1896. return(SCESTATUS_SUCCESS);
  1897. }
  1898. NTSTATUS NtStatus=STATUS_SUCCESS;
  1899. if ( *pPolicyHandle == NULL ) {
  1900. NtStatus = ScepOpenLsaPolicy(
  1901. MAXIMUM_ALLOWED, //GENERIC_ALL,
  1902. pPolicyHandle,
  1903. TRUE
  1904. );
  1905. if ( !NT_SUCCESS(NtStatus) ) {
  1906. return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
  1907. }
  1908. }
  1909. //
  1910. // allocate temp buffer for the sid string pointers
  1911. //
  1912. PWSTR *pSidStrs = (PWSTR *)ScepAlloc(LPTR, cnt*sizeof(PWSTR));
  1913. if ( pSidStrs == NULL ) {
  1914. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1915. }
  1916. DWORD *pSidLen = (DWORD *)ScepAlloc(LPTR, cnt*sizeof(DWORD));
  1917. if ( pSidLen == NULL ) {
  1918. ScepFree(pSidStrs);
  1919. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1920. }
  1921. BOOL *pSidFree = (BOOL *)ScepAlloc(LPTR, cnt*sizeof(BOOL));
  1922. if ( pSidFree == NULL ) {
  1923. ScepFree(pSidStrs);
  1924. ScepFree(pSidLen);
  1925. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1926. }
  1927. pCurr = mszAccounts;
  1928. DWORD i = 0;
  1929. BOOL bConvert=FALSE;
  1930. PWSTR SidString, pTemp;
  1931. DWORD StrLen;
  1932. SCESTATUS rc;
  1933. while ( pCurr && *pCurr != L'\0' &&
  1934. ( i < cnt ) ) {
  1935. pSidStrs[i] = pCurr;
  1936. pSidFree[i] = FALSE;
  1937. pSidLen[i] = wcslen(pCurr);
  1938. pTemp = pCurr + pSidLen[i] + 1;
  1939. if ( *pCurr != L'*' && wcschr(pCurr, L'\\') == 0 ) {
  1940. //
  1941. // this is a name format and it's an isolated name
  1942. // let's resolve it to a SID string
  1943. //
  1944. SidString = NULL;
  1945. StrLen = 0;
  1946. rc = ScepConvertNameToSidString( *pPolicyHandle,
  1947. pCurr,
  1948. FALSE, //TRUE,
  1949. &SidString,
  1950. &StrLen
  1951. );
  1952. if ( rc == SCESTATUS_SUCCESS &&
  1953. SidString ) {
  1954. //
  1955. // got a sid string
  1956. //
  1957. pSidStrs[i] = SidString;
  1958. pSidLen[i] = StrLen;
  1959. pSidFree[i] = TRUE;
  1960. bConvert = TRUE;
  1961. }
  1962. }
  1963. i ++;
  1964. pCurr = pTemp;
  1965. }
  1966. //
  1967. // now we need to build the new string
  1968. //
  1969. rc = SCESTATUS_SUCCESS;
  1970. if ( bConvert ) {
  1971. DWORD dwTotal=0;
  1972. for ( i=0; i<cnt; i++ ) {
  1973. dwTotal += pSidLen[i];
  1974. dwTotal ++; // for the NULL terminator
  1975. }
  1976. if ( dwTotal ) {
  1977. dwTotal ++; // for the last NULL terminator
  1978. *pmszNewAccounts = (PWSTR)ScepAlloc(LPTR, dwTotal*sizeof(WCHAR));
  1979. if ( *pmszNewAccounts ) {
  1980. pCurr = *pmszNewAccounts;
  1981. for ( i=0; i<cnt; i++ ) {
  1982. wcsncpy(pCurr, pSidStrs[i], pSidLen[i]);
  1983. pCurr += pSidLen[i];
  1984. *pCurr = L'\0';
  1985. pCurr++;
  1986. }
  1987. *pNewLen = dwTotal;
  1988. } else {
  1989. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1990. }
  1991. }
  1992. }
  1993. for ( i=0; i<cnt; i++ ) {
  1994. if ( pSidFree[i] && pSidStrs[i] ) {
  1995. ScepFree(pSidStrs[i]);
  1996. }
  1997. }
  1998. ScepFree(pSidStrs);
  1999. ScepFree(pSidLen);
  2000. ScepFree(pSidFree);
  2001. return(rc);
  2002. }