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.

3222 lines
95 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_REG_ADD SCE_PRIV_ADD
  20. #define SCE_REG_REMOVE SCE_PRIV_REMOVE
  21. #define SCE_REG_ADD_REMOVE_VALUE 8
  22. #define SCE_OBJECT_FLAG_OBJECTS 1
  23. #define SCE_OBJECT_FLAG_OLDSDDL 2
  24. #define SCE_OBJECT_FLAG_UNKNOWN_VERSION 4
  25. //
  26. // Forward references
  27. //
  28. SCEINF_STATUS
  29. SceInfpGetOneObject(
  30. IN PINFCONTEXT pInfLine,
  31. IN DWORD ObjectFlag,
  32. OUT PWSTR *Name,
  33. OUT PWSTR *Value,
  34. OUT PDWORD ValueLen
  35. );
  36. #define SCE_CONVERT_INF_MULTISZ 0x01
  37. #define SCE_CONVERT_INF_PRIV 0x02
  38. #define SCE_CONVERT_INF_GROUP 0x04
  39. #define SCE_CONVERT_INF_NEWVERSION 0x08
  40. #define SCE_CONVERT_INF_REGVALUE 0x10
  41. SCESTATUS
  42. SceConvertpInfKeyValue(
  43. IN PCWSTR InfSectionName,
  44. IN HINF hInf,
  45. IN PSCECONTEXT hProfile,
  46. IN DWORD dwTableOption,
  47. IN DWORD dwConvertOption,
  48. IN LONG GpoID,
  49. IN OPTIONAL PCWSTR pcwszKey,
  50. OUT PSCE_NAME_LIST *pKeyList
  51. );
  52. SCESTATUS
  53. SceConvertpInfObject(
  54. IN PCWSTR InfSectionName,
  55. IN UINT ObjectType,
  56. IN DWORD ObjectFlag,
  57. IN HINF hInf,
  58. IN PSCECONTEXT hProfile,
  59. IN DWORD dwTableOption,
  60. IN LONG GpoID
  61. );
  62. SCESTATUS
  63. SceConvertpInfDescription(
  64. IN HINF hInf,
  65. IN PSCECONTEXT hProfile
  66. );
  67. SCESTATUS
  68. SceConvertpAttachmentSections(
  69. IN HINF hInf,
  70. IN PSCECONTEXT hProfile,
  71. IN DWORD dwTableOption,
  72. IN LONG GpoID,
  73. IN SCE_ATTACHMENT_TYPE aType
  74. );
  75. SCESTATUS
  76. SceConvertpWMIAttachmentSections(
  77. IN HINF hInf,
  78. IN PSCECONTEXT hProfile,
  79. IN DWORD dwTableOption,
  80. IN LONG GpoID
  81. );
  82. SCESTATUS
  83. SceConvertpOneAttachmentSection(
  84. IN HINF hInf,
  85. IN PSCECONTEXT hProfile,
  86. IN PWSTR SectionName,
  87. IN DWORD dwTableOption,
  88. IN LONG GpoID
  89. );
  90. SCESTATUS
  91. ScepBuildNewPrivilegeList(
  92. IN LSA_HANDLE *pPolicyHandle,
  93. IN PWSTR PrivName,
  94. IN PWSTR mszUsers,
  95. IN ULONG dwBuildOption,
  96. OUT PWSTR *pmszNewUsers,
  97. OUT DWORD *pNewLen
  98. );
  99. SCESTATUS
  100. ScepAddToPrivilegeList(
  101. OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
  102. IN PWSTR Name,
  103. IN DWORD Len,
  104. IN DWORD PrivValue
  105. );
  106. SCESTATUS
  107. ScepBuildNewMultiSzRegValue(
  108. IN PWSTR pszKeyName,
  109. IN PWSTR pszStrValue,
  110. IN DWORD dwValueLen,
  111. OUT PWSTR* ppszNewValue,
  112. OUT PDWORD pdwNewLen
  113. );
  114. SCESTATUS
  115. ScepBuildRegMultiSzValue(
  116. IN PWSTR pszKeyName,
  117. IN PWSTR pszAddList OPTIONAL,
  118. IN DWORD dwAddLen,
  119. IN PWSTR pszRemoveList OPTIONAL,
  120. IN DWORD dwRemoveLen,
  121. IN PWSTR pszPrefix,
  122. OUT PWSTR* ppszNewValue,
  123. OUT PDWORD pdwNewValueLen
  124. );
  125. //
  126. // Function definitions
  127. //
  128. SCESTATUS
  129. SceJetConvertInfToJet(
  130. IN PCWSTR InfFile,
  131. IN LPSTR JetDbName,
  132. IN SCEJET_CREATE_TYPE Flags,
  133. IN DWORD Options,
  134. IN AREA_INFORMATION Area
  135. )
  136. /**++
  137. Function Description:
  138. This function converts a SCP profile in INF format to a Jet database format
  139. for the area provided. The SCP profile information is converted into the
  140. local policy table (SMP) in the Jet database.
  141. If the Jet database already exists, Flags is used to decide either overwrite,
  142. reuse, or just error out. All possible errors occur inside the routine are
  143. saved in the optional Errlog if Errlog is not NULL
  144. Arguments:
  145. InfFile - The Inf file name to convert from
  146. JetDbName - the SCP profile in Jet format to convert into
  147. Flags - Used when there is a duplicated Jet database
  148. SCEJET_OVERWRITE
  149. SCEJET_OPEN
  150. 0
  151. Options - the conversion options
  152. Area - the area to convert
  153. Return Value:
  154. -- **/
  155. {
  156. PSCECONTEXT hProfile=NULL;
  157. SCESTATUS rc;
  158. PSCE_NAME_LIST pProfileList=NULL,
  159. pProfile=NULL;
  160. DWORD Count;
  161. PSECURITY_DESCRIPTOR pSD=NULL;
  162. SECURITY_INFORMATION SeInfo;
  163. HINF hInf=NULL;
  164. RPC_STATUS RpcStatus=RPC_S_OK;
  165. INT Revision = 0;
  166. DWORD ObjectFlag=0;
  167. INFCONTEXT InfLine;
  168. DWORD dwConvertOption=0;
  169. if ( InfFile == NULL ||
  170. JetDbName == NULL ) {
  171. return(SCESTATUS_INVALID_PARAMETER);
  172. }
  173. //
  174. // open the inf profile
  175. //
  176. rc = SceInfpOpenProfile(
  177. InfFile,
  178. &hInf
  179. );
  180. if ( rc != SCESTATUS_SUCCESS ) {
  181. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  182. SCEDLL_ERROR_OPEN,
  183. (PWSTR)InfFile);
  184. return(rc);
  185. }
  186. LONG GpoID=0;
  187. //
  188. // create/open the Jet database
  189. //
  190. DWORD dwNewOption = 0;
  191. // MREGE_POLICY option allows opening the temp merge policy table to build new policy
  192. // TATTOO option allows creating/opening the tattoo table into SAP context
  193. if ( Options & SCE_POLICY_TEMPLATE )
  194. dwNewOption |= SCE_TABLE_OPTION_MERGE_POLICY | SCE_TABLE_OPTION_TATTOO;
  195. // this check handles setup case (to create/open tattoo table)
  196. else {
  197. if ( (Options & SCE_SYSTEM_DB) )
  198. dwNewOption |= SCE_TABLE_OPTION_TATTOO;
  199. // dc demote should reset account policy and user rights at reboot (from tattoo table)
  200. if ( Options & SCE_DC_DEMOTE )
  201. dwNewOption |= SCE_TABLE_OPTION_DEMOTE_TATTOO;
  202. }
  203. rc = SceJetCreateFile(JetDbName,
  204. Flags,
  205. dwNewOption,
  206. &hProfile);
  207. if ( rc != SCESTATUS_SUCCESS ) {
  208. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  209. SCEDLL_ERROR_CREATE, L"database");
  210. goto CleanUp;
  211. }
  212. if ( Options & SCE_SYSTEM_DB ) {
  213. //
  214. // set Admin F, CO F to the database (protected)
  215. //
  216. rc = ConvertTextSecurityDescriptor (
  217. L"D:P(A;;GA;;;CO)(A;;GA;;;BA)(A;;GA;;;SY)",
  218. &pSD,
  219. &Count, // temp var for SDsize
  220. &SeInfo
  221. );
  222. if ( rc == NO_ERROR ) {
  223. ScepChangeAclRevision(pSD, ACL_REVISION);
  224. //
  225. // use current token as the owner (because this database is
  226. // to be created
  227. //
  228. HANDLE Token=NULL;
  229. if (!OpenThreadToken( GetCurrentThread(),
  230. TOKEN_QUERY,
  231. TRUE,
  232. &Token)) {
  233. if(ERROR_NO_TOKEN == GetLastError()){
  234. if(!OpenProcessToken( GetCurrentProcess(),
  235. TOKEN_QUERY,
  236. &Token)) {
  237. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  238. }
  239. } else {
  240. ScepLogOutput3(1, GetLastError(), SCEDLL_ERROR_QUERY_INFO, L"TOKEN");
  241. }
  242. }
  243. if ( Token ) {
  244. PSECURITY_DESCRIPTOR pNewSD=NULL;
  245. //
  246. // RtlNewSecurityObjectEx must be called on the process context (system)
  247. // because it will try to get process information inside the api.
  248. //
  249. RpcRevertToSelf();
  250. rc = RtlNtStatusToDosError(
  251. RtlNewSecurityObjectEx(
  252. NULL,
  253. pSD,
  254. &pNewSD,
  255. NULL, // GUID
  256. FALSE,
  257. SEF_DACL_AUTO_INHERIT |
  258. SEF_AVOID_OWNER_CHECK |
  259. SEF_AVOID_PRIVILEGE_CHECK,
  260. Token,
  261. &FileGenericMapping
  262. ));
  263. RpcStatus = RpcImpersonateClient( NULL );
  264. if ( RpcStatus == RPC_S_OK ) {
  265. if ( rc == NO_ERROR ) {
  266. if ( !SetFileSecurityA (
  267. JetDbName,
  268. SeInfo,
  269. pNewSD
  270. ) ) {
  271. rc = GetLastError();
  272. ScepLogOutput3(1, rc,
  273. SCEDLL_ERROR_SET_SECURITY, L"database");
  274. }
  275. ScepFree(pNewSD);
  276. } else {
  277. ScepLogOutput3(1, rc,
  278. SCEDLL_ERROR_BUILD_SD, L"database");
  279. }
  280. } else {
  281. if ( rc == NO_ERROR ) {
  282. ScepFree(pNewSD);
  283. }
  284. ScepLogOutput3(1, I_RpcMapWin32Status(RpcStatus),
  285. SCEDLL_ERROR_BUILD_SD, L"database");
  286. }
  287. CloseHandle(Token);
  288. }
  289. ScepFree(pSD);
  290. } else
  291. ScepLogOutput3(1, rc, SCEDLL_ERROR_BUILD_SD, L"database");
  292. }
  293. if ( RpcStatus != RPC_S_OK ) {
  294. goto CleanUp;
  295. }
  296. if ( !(Options & SCE_POLICY_TEMPLATE) ) {
  297. //
  298. // if not in the middle of policy propagation, use Jet transaction
  299. // otherwise, use the temp table concept.
  300. //
  301. SceJetStartTransaction( hProfile );
  302. //
  303. //If it is in demote or snapshot mode delete local policy.
  304. //
  305. if ( (Options & SCE_DC_DEMOTE) &&
  306. (Options & SCE_SYSTEM_DB) ) {
  307. ScepDeleteInfoForAreas(
  308. hProfile,
  309. SCE_ENGINE_SMP,
  310. AREA_ALL
  311. );
  312. ScepDeleteInfoForAreas(
  313. hProfile,
  314. SCE_ENGINE_SAP, // tattoo
  315. AREA_ALL
  316. );
  317. } else if ( Options & SCE_GENERATE_ROLLBACK ) {
  318. ScepDeleteInfoForAreas(
  319. hProfile,
  320. SCE_ENGINE_SMP,
  321. AREA_ALL
  322. );
  323. }
  324. } else if ( Options & SCE_POLICY_FIRST ) {
  325. //
  326. // The ENGINE_SCP table points to the new merge table
  327. // instead of the existing one.
  328. //
  329. // delete everything in SCP then
  330. // copy Tattoo to SCP
  331. //
  332. rc = ScepDeleteInfoForAreas(
  333. hProfile,
  334. SCE_ENGINE_SCP,
  335. AREA_ALL
  336. );
  337. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND ) {
  338. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  339. SCEDLL_ERROR_DELETE, L"SCP");
  340. goto CleanUp;
  341. }
  342. //
  343. // delete GPO table to start over
  344. //
  345. SceJetDeleteAll( hProfile,
  346. "SmTblGpo",
  347. SCEJET_TABLE_GPO
  348. );
  349. PSCE_ERROR_LOG_INFO Errlog=NULL;
  350. ScepLogOutput3(2, rc, SCEDLL_COPY_LOCAL);
  351. // copy from tattoo table to effective policy table
  352. rc = ScepCopyLocalToMergeTable( hProfile,
  353. Options,
  354. (ProductType == NtProductLanManNt) ? SCE_LOCAL_POLICY_DC : 0,
  355. &Errlog );
  356. ScepLogWriteError( Errlog,1 );
  357. ScepFreeErrorLog( Errlog );
  358. Errlog = NULL;
  359. if ( rc != SCESTATUS_SUCCESS ) {
  360. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  361. SCEDLL_ERROR_COPY);
  362. goto CleanUp;
  363. }
  364. //
  365. // now, migrate database if tattoo table doesn't exist (in existing database)
  366. // this could happen if someone manually copied a database to the system
  367. // database location, or if the database failed to be migrated in setup
  368. //
  369. if ( hProfile->JetSapID == JET_tableidNil ) {
  370. SceJetCreateTable(
  371. hProfile,
  372. "SmTblTattoo",
  373. SCEJET_TABLE_TATTOO,
  374. SCEJET_CREATE_IN_BUFFER,
  375. NULL,
  376. NULL
  377. );
  378. }
  379. }
  380. TCHAR szGpoName[MAX_PATH];
  381. szGpoName[0] = L'\0';
  382. szGpoName[1] = L'\0';
  383. szGpoName[2] = L'\0';
  384. if ( Options & SCE_POLICY_TEMPLATE ) {
  385. //
  386. // get the GPO path and GPOID
  387. //
  388. GetPrivateProfileString(TEXT("Version"),
  389. TEXT("GPOPath"),
  390. TEXT(""),
  391. szGpoName,
  392. MAX_PATH,
  393. InfFile
  394. );
  395. if ( szGpoName[0] != L'\0' ) {
  396. PWSTR pTemp = wcschr(szGpoName, L'\\');
  397. if ( pTemp ) {
  398. *pTemp = L'\0';
  399. }
  400. GpoID = SceJetGetGpoIDByName(hProfile,
  401. szGpoName,
  402. TRUE // add if it's not there
  403. );
  404. //
  405. // if GpoID is -1, an error occurred
  406. //
  407. if ( GpoID < 0 ) {
  408. rc = GetLastError();
  409. if ( rc != SCESTATUS_SUCCESS ) {
  410. ScepLogOutput3( 1, ScepDosErrorToSceStatus(rc),
  411. SCEDLL_ERROR_CONVERT, (PWSTR)szGpoName);
  412. goto CleanUp;
  413. }
  414. }
  415. }
  416. }
  417. //
  418. // query the version # to determine if the SDDL string should be migrated
  419. //
  420. if ( SetupFindFirstLine(hInf,L"Version",L"Revision",&InfLine) ) {
  421. if ( !SetupGetIntField(&InfLine, 1, (INT *)&Revision) ) {
  422. Revision = 0;
  423. }
  424. }
  425. if ( Revision == 0 ) ObjectFlag = SCE_OBJECT_FLAG_OLDSDDL;
  426. if ( Revision > SCE_TEMPLATE_MAX_SUPPORTED_VERSION ) {
  427. dwConvertOption = SCE_CONVERT_INF_NEWVERSION;
  428. ObjectFlag |= SCE_OBJECT_FLAG_UNKNOWN_VERSION;
  429. }
  430. //
  431. // process each area
  432. //
  433. if ( Area & AREA_SECURITY_POLICY ) {
  434. if ( !( Options & SCE_NO_DOMAIN_POLICY) ) {
  435. // System Access section
  436. rc = SceConvertpInfKeyValue(
  437. szSystemAccess,
  438. hInf,
  439. hProfile,
  440. dwNewOption,
  441. dwConvertOption,
  442. GpoID,
  443. NULL,
  444. NULL
  445. );
  446. if ( rc != SCESTATUS_SUCCESS ) {
  447. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  448. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szSystemAccess);
  449. goto CleanUp;
  450. }
  451. }
  452. rc = SceConvertpInfKeyValue(
  453. szSystemAccess,
  454. hInf,
  455. hProfile,
  456. dwNewOption,
  457. dwConvertOption,
  458. GpoID,
  459. L"LSAAnonymousNameLookup",
  460. NULL
  461. );
  462. if ( rc != SCESTATUS_SUCCESS ) {
  463. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  464. SCEDLL_ERROR_CONVERT_SECTION, L"LSAAnonymousNameLookup");
  465. goto CleanUp;
  466. }
  467. //
  468. // configure event log settings in setup too
  469. // since local policy table is not used in policy prop anymore
  470. //
  471. // if ( !(Options & SCE_SYSTEM_DB) ||
  472. // (Options & SCE_POLICY_TEMPLATE) ) {
  473. // System Log section
  474. rc = SceConvertpInfKeyValue(
  475. szAuditSystemLog,
  476. hInf,
  477. hProfile,
  478. dwNewOption,
  479. dwConvertOption,
  480. GpoID,
  481. NULL,
  482. NULL
  483. );
  484. if ( rc != SCESTATUS_SUCCESS ) {
  485. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  486. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSystemLog);
  487. goto CleanUp;
  488. }
  489. // Security Log section
  490. rc = SceConvertpInfKeyValue(
  491. szAuditSecurityLog,
  492. hInf,
  493. hProfile,
  494. dwNewOption,
  495. dwConvertOption,
  496. GpoID,
  497. NULL,
  498. NULL
  499. );
  500. if ( rc != SCESTATUS_SUCCESS ) {
  501. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  502. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditSecurityLog);
  503. goto CleanUp;
  504. }
  505. // Application Log section
  506. rc = SceConvertpInfKeyValue(
  507. szAuditApplicationLog,
  508. hInf,
  509. hProfile,
  510. dwNewOption,
  511. dwConvertOption,
  512. GpoID,
  513. NULL,
  514. NULL
  515. );
  516. if ( rc != SCESTATUS_SUCCESS ) {
  517. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  518. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditApplicationLog);
  519. goto CleanUp;
  520. }
  521. // }
  522. // Audit Event section
  523. rc = SceConvertpInfKeyValue(
  524. szAuditEvent,
  525. hInf,
  526. hProfile,
  527. dwNewOption,
  528. dwConvertOption,
  529. GpoID,
  530. NULL,
  531. NULL
  532. );
  533. if ( rc != SCESTATUS_SUCCESS ) {
  534. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  535. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szAuditEvent);
  536. goto CleanUp;
  537. }
  538. if ( !( Options & SCE_NO_DOMAIN_POLICY) &&
  539. (ProductType == NtProductLanManNt) &&
  540. !( Options & SCE_DC_DEMOTE) ) {
  541. // Kerberos section
  542. rc = SceConvertpInfKeyValue(
  543. szKerberosPolicy,
  544. hInf,
  545. hProfile,
  546. dwNewOption,
  547. dwConvertOption,
  548. GpoID,
  549. NULL,
  550. NULL
  551. );
  552. if ( rc != SCESTATUS_SUCCESS ) {
  553. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  554. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szKerberosPolicy);
  555. goto CleanUp;
  556. }
  557. }
  558. // registry values
  559. rc = SceConvertpInfKeyValue(
  560. szRegistryValues,
  561. hInf,
  562. hProfile,
  563. dwNewOption,
  564. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_REGVALUE,
  565. GpoID,
  566. NULL,
  567. NULL
  568. );
  569. if ( rc != SCESTATUS_SUCCESS ) {
  570. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  571. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryValues);
  572. goto CleanUp;
  573. }
  574. rc = SceConvertpAttachmentSections(hInf,
  575. hProfile,
  576. (Options & SCE_POLICY_TEMPLATE) ? TRUE : FALSE,
  577. GpoID,
  578. SCE_ATTACHMENT_POLICY);
  579. if ( rc != SCESTATUS_SUCCESS ) {
  580. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  581. SCEDLL_SAP_ERROR_ENUMERATE, L"policy attachments.");
  582. goto CleanUp;
  583. }
  584. }
  585. if ( Area & AREA_REGISTRY_SECURITY ) {
  586. //
  587. // Object type - Registry
  588. //
  589. rc = SceConvertpInfObject(
  590. szRegistryKeys,
  591. 1,
  592. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  593. hInf,
  594. hProfile,
  595. dwNewOption,
  596. GpoID
  597. );
  598. if ( rc != SCESTATUS_SUCCESS ) {
  599. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  600. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szRegistryKeys);
  601. goto CleanUp;
  602. }
  603. }
  604. if ( Area & AREA_FILE_SECURITY ) {
  605. // File security
  606. rc = SceConvertpInfObject(
  607. szFileSecurity,
  608. 2,
  609. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  610. hInf,
  611. hProfile,
  612. dwNewOption,
  613. GpoID
  614. );
  615. if ( rc != SCESTATUS_SUCCESS ) {
  616. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  617. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szFileSecurity);
  618. goto CleanUp;
  619. }
  620. }
  621. #if 0
  622. //
  623. // DS object security
  624. //
  625. rc = SceConvertpInfObject(
  626. szDSSecurity,
  627. 3,
  628. ObjectFlag | SCE_OBJECT_FLAG_OBJECTS,
  629. hInf,
  630. hProfile,
  631. dwNewOption,
  632. GpoID
  633. );
  634. if ( rc != SCESTATUS_SUCCESS ) {
  635. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  636. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szDSSecurity);
  637. goto CleanUp;
  638. }
  639. #endif
  640. if ( Area & AREA_SYSTEM_SERVICE ) {
  641. //
  642. // Service General Settings
  643. //
  644. rc = SceConvertpInfObject(
  645. szServiceGeneral,
  646. 0,
  647. ObjectFlag,
  648. hInf,
  649. hProfile,
  650. dwNewOption,
  651. GpoID
  652. );
  653. if ( rc != SCESTATUS_SUCCESS ) {
  654. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  655. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szServiceGeneral);
  656. goto CleanUp;
  657. }
  658. //
  659. // each service's specific settings
  660. //
  661. rc = SceConvertpAttachmentSections(hInf,
  662. hProfile,
  663. dwNewOption,
  664. GpoID,
  665. SCE_ATTACHMENT_SERVICE);
  666. if ( rc != SCESTATUS_SUCCESS ) {
  667. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  668. SCEDLL_SAP_ERROR_ENUMERATE, L"service attachments.");
  669. goto CleanUp;
  670. }
  671. }
  672. if ( (Area & AREA_ATTACHMENTS) ) {
  673. //
  674. // each service's specific settings
  675. //
  676. rc = SceConvertpWMIAttachmentSections(hInf,
  677. hProfile,
  678. dwNewOption,
  679. GpoID
  680. );
  681. if ( rc != SCESTATUS_SUCCESS ) {
  682. goto CleanUp;
  683. }
  684. }
  685. if ( Area & AREA_PRIVILEGES ) {
  686. //
  687. // Multi-Sz type - privilege/rights
  688. //
  689. rc = SceConvertpInfKeyValue(
  690. szPrivilegeRights,
  691. hInf,
  692. hProfile,
  693. dwNewOption,
  694. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_PRIV,
  695. GpoID,
  696. NULL,
  697. NULL
  698. );
  699. if ( rc != SCESTATUS_SUCCESS ) {
  700. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  701. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szPrivilegeRights);
  702. goto CleanUp;
  703. }
  704. }
  705. if ( Area & AREA_GROUP_MEMBERSHIP ) {
  706. // group membership
  707. rc = SceConvertpInfKeyValue(
  708. szGroupMembership,
  709. hInf,
  710. hProfile,
  711. dwNewOption,
  712. dwConvertOption | SCE_CONVERT_INF_MULTISZ | SCE_CONVERT_INF_GROUP,
  713. GpoID,
  714. NULL,
  715. NULL
  716. );
  717. if ( rc != SCESTATUS_SUCCESS ) {
  718. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  719. SCEDLL_ERROR_CONVERT_SECTION, (PWSTR)szGroupMembership);
  720. goto CleanUp;
  721. }
  722. }
  723. //
  724. // if there is a description, convert it.
  725. //
  726. SceConvertpInfDescription(
  727. hInf,
  728. hProfile);
  729. if ( !(Options & SCE_POLICY_TEMPLATE) ) {
  730. //
  731. // Commit changes
  732. //
  733. SceJetCommitTransaction( hProfile, 0 );
  734. } else if ( Options & SCE_POLICY_LAST ) {
  735. //
  736. // update the LastUsedMergeTable field
  737. //
  738. DWORD dwThisTable = hProfile->Type & 0xF0L;
  739. if ( SCEJET_MERGE_TABLE_1 == dwThisTable ||
  740. SCEJET_MERGE_TABLE_2 == dwThisTable ) {
  741. rc = SceJetSetValueInVersion(
  742. hProfile,
  743. "SmTblVersion",
  744. "LastUsedMergeTable",
  745. (PWSTR)&dwThisTable,
  746. 4,
  747. JET_prepReplace
  748. );
  749. }
  750. }
  751. CleanUp:
  752. //
  753. // close the inf profile
  754. //
  755. SceInfpCloseProfile(hInf);
  756. if ( pProfileList != NULL ) {
  757. ScepFreeNameList(pProfileList);
  758. }
  759. //
  760. // Rollback
  761. //
  762. if ( !(Options & SCE_POLICY_TEMPLATE) &&
  763. (RpcStatus == RPC_S_OK) &&
  764. (rc != SCESTATUS_SUCCESS) ) {
  765. SceJetRollback( hProfile, 0 );
  766. }
  767. //
  768. // Close the JET database
  769. //
  770. SceJetCloseFile( hProfile, TRUE, FALSE );
  771. if ( RpcStatus != RPC_S_OK ) {
  772. rc = I_RpcMapWin32Status(RpcStatus);
  773. }
  774. return(rc);
  775. }
  776. SCESTATUS
  777. SceConvertpAttachmentSections(
  778. IN HINF hInf,
  779. IN PSCECONTEXT hProfile,
  780. IN DWORD dwTableOption,
  781. IN LONG GpoID,
  782. IN SCE_ATTACHMENT_TYPE aType
  783. )
  784. {
  785. SCESTATUS rc;
  786. PSCE_SERVICES pServiceList=NULL, pNode;
  787. rc = ScepEnumServiceEngines( &pServiceList, aType );
  788. if ( rc == SCESTATUS_SUCCESS ) {
  789. for ( pNode=pServiceList; pNode != NULL; pNode=pNode->Next) {
  790. rc = SceConvertpOneAttachmentSection(hInf,
  791. hProfile,
  792. pNode->ServiceName,
  793. dwTableOption,
  794. GpoID
  795. );
  796. if ( rc != SCESTATUS_SUCCESS ) {
  797. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  798. SCEDLL_ERROR_CONVERT_SECTION, pNode->ServiceName );
  799. break;
  800. }
  801. }
  802. SceFreePSCE_SERVICES(pServiceList);
  803. } else if ( rc == SCESTATUS_PROFILE_NOT_FOUND ||
  804. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  805. // if no service exist, just ignore
  806. rc = SCESTATUS_SUCCESS;
  807. }
  808. return(rc);
  809. }
  810. SCESTATUS
  811. SceConvertpWMIAttachmentSections(
  812. IN HINF hInf,
  813. IN PSCECONTEXT hProfile,
  814. IN DWORD dwTableOption,
  815. IN LONG GpoID
  816. )
  817. {
  818. SCESTATUS rc=SCESTATUS_SUCCESS;
  819. INFCONTEXT InfLine;
  820. WCHAR SectionName[513];
  821. DWORD DataSize=0;
  822. if ( SetupFindFirstLine(hInf, szAttachments,NULL,&InfLine) ) {
  823. do {
  824. memset(SectionName, '\0', 513*sizeof(WCHAR));
  825. // get each attachment section name
  826. if(SetupGetStringField(&InfLine, 0, SectionName, 512, &DataSize) ) {
  827. rc = SceConvertpOneAttachmentSection(hInf,
  828. hProfile,
  829. SectionName,
  830. dwTableOption,
  831. GpoID
  832. );
  833. if ( rc != SCESTATUS_SUCCESS ) {
  834. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  835. SCEDLL_ERROR_CONVERT_SECTION, SectionName );
  836. break;
  837. }
  838. } else {
  839. rc = ScepDosErrorToSceStatus(GetLastError());
  840. }
  841. } while ( rc == SCESTATUS_SUCCESS &&
  842. SetupFindNextLine(&InfLine, &InfLine));
  843. }
  844. return(rc);
  845. }
  846. SCESTATUS
  847. SceConvertpOneAttachmentSection(
  848. IN HINF hInf,
  849. IN PSCECONTEXT hProfile,
  850. IN PWSTR SectionName,
  851. IN DWORD dwTableOption,
  852. IN LONG GpoID
  853. )
  854. {
  855. SCESTATUS rc;
  856. PSCESVC_CONFIGURATION_INFO pServiceInfo=NULL;
  857. //
  858. // read inf info for the service
  859. //
  860. rc = SceSvcpGetInformationTemplate(
  861. hInf,
  862. SectionName,
  863. NULL, // not a single key
  864. &pServiceInfo
  865. );
  866. if ( rc == SCESTATUS_SUCCESS && pServiceInfo != NULL ) {
  867. //
  868. // write the information to SCP or SMP table
  869. //
  870. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  871. rc = SceSvcpSetInfo(
  872. hProfile,
  873. SceSvcInternalUse,
  874. SectionName,
  875. NULL,
  876. TRUE, // to support incremental template, DO NOT overwrite the whole section
  877. GpoID,
  878. pServiceInfo
  879. );
  880. } else {
  881. rc = SceSvcpSetInfo(
  882. hProfile,
  883. SceSvcConfigurationInfo,
  884. SectionName,
  885. NULL,
  886. TRUE, // to support incremental template, DO NOT overwrite the whole section
  887. 0,
  888. pServiceInfo
  889. );
  890. }
  891. //
  892. // free buffer
  893. //
  894. SceSvcpFreeMemory(pServiceInfo);
  895. pServiceInfo = NULL;
  896. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  897. rc = SCESTATUS_SUCCESS;
  898. }
  899. return(rc);
  900. }
  901. SCESTATUS
  902. SceConvertpInfKeyValue(
  903. IN PCWSTR InfSectionName,
  904. IN HINF hInf,
  905. IN PSCECONTEXT hProfile,
  906. IN DWORD dwTableOption,
  907. IN DWORD dwConvertOption,
  908. IN LONG GpoID,
  909. IN OPTIONAL PCWSTR pcwszKey,
  910. OUT PSCE_NAME_LIST *pKeyList OPTIONAL
  911. )
  912. /* ++
  913. Routine Description:
  914. This routine converts INF sections which are in a key=value format. Value
  915. could be in MultiSz format (dwConvertOption & SCE_CONVERT_INF_MULTISZ).
  916. The optional pKeyList is a list of all keys in the section. This option
  917. is used when dynamic sections are converted.
  918. Arguments:
  919. InfSectionName - the INF section name to convert
  920. hInf - the Inf file handle
  921. hprofile - the Jet database context
  922. dwTableOption - SCE_TABLE_OPTION_MERGE_POLICY = within policy propagation
  923. SCE_TABLE_OPTION_TATTOO - system db (in setup)
  924. dwConvertOption - SCE_CONVERT_INF_MULTISZ - MultiSz type value
  925. SCE_CONVERT_INF_PRIV - user right section
  926. SCE_CONVERT_INF_GROUP - group membership section
  927. GpoID - the group policy ID for this item
  928. pKeyList - a list of all keys in the section.
  929. Return Value:
  930. -- */
  931. {
  932. SCESTATUS rc;
  933. DOUBLE SectionID;
  934. PSCESECTION hSection=NULL;
  935. PSCESECTION hSectionTattoo=NULL;
  936. INFCONTEXT InfLine;
  937. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  938. PWSTR pSidStr=NULL;
  939. PWSTR pKeyStr=NULL;
  940. PWSTR StrValue=NULL;
  941. DWORD ValueLen=0;
  942. LSA_HANDLE LsaPolicy=NULL;
  943. DWORD Len=0;
  944. if ( InfSectionName == NULL ||
  945. hInf == INVALID_HANDLE_VALUE ||
  946. hProfile == NULL ) {
  947. return(SCESTATUS_INVALID_PARAMETER);
  948. }
  949. //
  950. // get section's ID. if the section does not exist, add it to the section table
  951. //
  952. rc = SceJetGetSectionIDByName(
  953. hProfile,
  954. InfSectionName,
  955. &SectionID
  956. );
  957. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  958. rc = SceJetAddSection(
  959. hProfile,
  960. InfSectionName,
  961. &SectionID
  962. );
  963. }
  964. if ( rc != SCESTATUS_SUCCESS ) {
  965. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  966. SCEDLL_ERROR_QUERY_INFO, (PWSTR)InfSectionName );
  967. return(rc);
  968. }
  969. if ( SetupFindFirstLine(hInf,InfSectionName,pcwszKey,&InfLine) ) {
  970. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  971. //
  972. // open the SCP section
  973. //
  974. rc = SceJetOpenSection(
  975. hProfile,
  976. SectionID,
  977. SCEJET_TABLE_SCP,
  978. &hSection
  979. );
  980. } else {
  981. //
  982. // open SMP table
  983. //
  984. rc = SceJetOpenSection(
  985. hProfile,
  986. SectionID,
  987. SCEJET_TABLE_SMP,
  988. &hSection
  989. );
  990. //
  991. // open the tattoo (in order to update tattoo value in setup)
  992. // do not care error
  993. //
  994. if ( dwTableOption & SCE_TABLE_OPTION_TATTOO )
  995. SceJetOpenSection(hProfile, SectionID,
  996. SCEJET_TABLE_TATTOO,
  997. &hSectionTattoo);
  998. }
  999. if ( rc != SCESTATUS_SUCCESS ) {
  1000. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1001. SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
  1002. if (hSection != NULL )
  1003. SceJetCloseSection( &hSection, TRUE);
  1004. if (hSectionTattoo != NULL )
  1005. SceJetCloseSection( &hSectionTattoo, TRUE);
  1006. return(rc);
  1007. }
  1008. //
  1009. // Open LSA policy handle for group name lookup, if any
  1010. // if policy handle can't be opened, import name format
  1011. //
  1012. if ( dwConvertOption & SCE_CONVERT_INF_GROUP ) {
  1013. ScepOpenLsaPolicy(
  1014. MAXIMUM_ALLOWED,
  1015. &LsaPolicy,
  1016. TRUE
  1017. );
  1018. }
  1019. //
  1020. // process each line in the section and save to the scp table.
  1021. // Each INF line has a key and a value.
  1022. //
  1023. do {
  1024. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(TCHAR));
  1025. rc = SCESTATUS_BAD_FORMAT;
  1026. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  1027. //
  1028. // check if newer version (keys) are passed
  1029. //
  1030. if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
  1031. if ( dwConvertOption & SCE_CONVERT_INF_PRIV ) {
  1032. //
  1033. // user rights from new version
  1034. // filter out all unknown rights
  1035. //
  1036. if ( -1 == ScepLookupPrivByName(Keyname) ) {
  1037. rc = SCESTATUS_SUCCESS;
  1038. goto NextLine;
  1039. }
  1040. } else if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
  1041. //
  1042. // convert registry values, should check number of fields
  1043. //
  1044. if ( SetupGetFieldCount( &InfLine ) < 2 ) {
  1045. rc = SCESTATUS_SUCCESS;
  1046. goto NextLine;
  1047. }
  1048. }
  1049. }
  1050. if ( (dwConvertOption & SCE_CONVERT_INF_GROUP) &&
  1051. ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ||
  1052. (Keyname[0] != L'*') ) ) {
  1053. //
  1054. // this is a group in name format
  1055. //
  1056. PWSTR pTemp = (PWSTR)Keyname;
  1057. //
  1058. // search for the suffix (szMembers or szMemberof or szPrivileges)
  1059. //
  1060. while ( pTemp = wcsstr(pTemp, szMembers) ) {
  1061. if ( *(pTemp+wcslen(szMembers)) != L'\0') {
  1062. pTemp++;
  1063. ValueLen = 0;
  1064. } else {
  1065. break;
  1066. }
  1067. }
  1068. if ( pTemp == NULL ) {
  1069. pTemp = (PWSTR)Keyname;
  1070. while ( pTemp = wcsstr(pTemp, szMemberof) ) {
  1071. if ( *(pTemp+wcslen(szMemberof)) != L'\0') {
  1072. pTemp++;
  1073. ValueLen = 1;
  1074. } else {
  1075. break;
  1076. }
  1077. }
  1078. if ( pTemp == NULL ) {
  1079. pTemp = (PWSTR)Keyname;
  1080. while ( pTemp = wcsstr(pTemp, szPrivileges) ) {
  1081. if ( *(pTemp+wcslen(szPrivileges)) != L'\0') {
  1082. pTemp++;
  1083. ValueLen = 2;
  1084. } else {
  1085. break;
  1086. }
  1087. }
  1088. }
  1089. }
  1090. if ( pTemp == NULL ) {
  1091. //
  1092. // this is an unknown group format, just import the keyname
  1093. // for supported version; for new version template, ignore
  1094. // this line
  1095. //
  1096. if ( (dwConvertOption & SCE_CONVERT_INF_NEWVERSION) ) {
  1097. rc = SCESTATUS_SUCCESS;
  1098. goto NextLine;
  1099. }
  1100. } else if ( Keyname[0] != L'*' ) {
  1101. *pTemp = L'\0';
  1102. Len=0;
  1103. if ( LsaPolicy ) {
  1104. //
  1105. // convert group name (domain\account) into *SID format
  1106. //
  1107. ScepConvertNameToSidString(
  1108. LsaPolicy,
  1109. Keyname,
  1110. FALSE,
  1111. &pSidStr,
  1112. &Len
  1113. );
  1114. } else {
  1115. if ( ScepLookupWellKnownName(
  1116. Keyname,
  1117. NULL,
  1118. &pSidStr ) ) {
  1119. Len = wcslen(pSidStr);
  1120. }
  1121. }
  1122. //
  1123. // restore the "_"
  1124. //
  1125. *pTemp = L'_';
  1126. if ( pSidStr ) {
  1127. //
  1128. // add the suffix
  1129. //
  1130. pKeyStr = (PWSTR)ScepAlloc(0, (Len+wcslen(pTemp)+1)*sizeof(WCHAR));
  1131. if ( pKeyStr ) {
  1132. wcscpy(pKeyStr, pSidStr);
  1133. wcscat(pKeyStr, pTemp);
  1134. } else {
  1135. //
  1136. // use the name instead - out of memory will be caught later
  1137. //
  1138. }
  1139. ScepFree(pSidStr);
  1140. pSidStr = NULL;
  1141. }
  1142. }
  1143. }
  1144. if ( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1145. SetupGetMultiSzField(&InfLine, 1, NULL, 0, &ValueLen)) ||
  1146. (!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1147. SetupGetStringField(&InfLine, 1, NULL, 0, &ValueLen)) ) {
  1148. if ( ValueLen > 1 ) {
  1149. StrValue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1150. (ValueLen+1)*sizeof(TCHAR));
  1151. if( StrValue == NULL ) {
  1152. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1153. } else if( ((dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1154. SetupGetMultiSzField(&InfLine, 1, StrValue, ValueLen, NULL)) ||
  1155. (!(dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1156. SetupGetStringField(&InfLine,1,StrValue,ValueLen,NULL)) ) {
  1157. //
  1158. // if dealing with registry values only, do the following:
  1159. // compress regtype into one CHAR instead of many WCHARS
  1160. // (can canonicalize REG_QWORD value later by arithmetic padding etc.- doesn't
  1161. // make sense now since registry api's treat REG_QWORD as a string anyway)
  1162. // Also, resolve the Add/Remove format
  1163. //
  1164. rc = SCESTATUS_SUCCESS;
  1165. if ( dwConvertOption & SCE_CONVERT_INF_REGVALUE ) {
  1166. DWORD LenStrValue = wcslen(StrValue);
  1167. PWSTR NewRegValue = NULL;
  1168. DWORD NewValueLen = 0;
  1169. if (LenStrValue > 1) {
  1170. *((CHAR *)StrValue) = (CHAR) (_wtol(StrValue) + '0');
  1171. memmove( StrValue+1,
  1172. StrValue + LenStrValue,
  1173. sizeof(WCHAR) * (ValueLen - LenStrValue));
  1174. ValueLen -= (LenStrValue - 1);
  1175. }
  1176. //
  1177. // if the reg value is of the type add/remove format in the template,
  1178. // then we need to resolve the add/remove instructions to generate
  1179. // the exact value to save in the DB
  1180. //
  1181. if(SCE_REG_ADD_REMOVE_VALUE == *((CHAR *)StrValue) - '0'){
  1182. rc = ScepBuildNewMultiSzRegValue(Keyname,
  1183. StrValue,
  1184. ValueLen,
  1185. &NewRegValue,
  1186. &NewValueLen
  1187. );
  1188. if(SCESTATUS_SUCCESS == rc){
  1189. ScepFree(StrValue);
  1190. StrValue = NewRegValue;
  1191. ValueLen = NewValueLen;
  1192. //
  1193. // if we have no buffer to set, then just go
  1194. // to the next line
  1195. // This happens only if the reg key/value does not
  1196. // exist on the system and we don't have an
  1197. // "add" instruction in the inf line
  1198. //
  1199. if(!StrValue || 0 == NewValueLen){
  1200. goto NextLine;
  1201. }
  1202. //
  1203. // now change the reg value type to multisz since
  1204. // the add/remove is now resolved.
  1205. //
  1206. *((CHAR *)StrValue) = (CHAR) (REG_MULTI_SZ + '0');
  1207. }
  1208. else{
  1209. ScepFree(StrValue);
  1210. StrValue = NULL;
  1211. }
  1212. }
  1213. }
  1214. } else {
  1215. ScepFree(StrValue);
  1216. StrValue = NULL;
  1217. }
  1218. } else {
  1219. rc = SCESTATUS_SUCCESS;
  1220. ValueLen = 0;
  1221. }
  1222. PWSTR NewValue=NULL;
  1223. DWORD NewLen=0;
  1224. if ( rc == SCESTATUS_SUCCESS ) {
  1225. if ( (dwConvertOption & SCE_CONVERT_INF_MULTISZ) &&
  1226. StrValue != NULL &&
  1227. (dwConvertOption & SCE_CONVERT_INF_PRIV) &&
  1228. ( _wcsicmp(SCE_PRIV_ADD, StrValue) == 0 ||
  1229. _wcsicmp(SCE_PRIV_REMOVE, StrValue) == 0) ) {
  1230. //
  1231. // another format for user rights (ADD: REMOVE:...)
  1232. //
  1233. rc = ScepBuildNewPrivilegeList(&LsaPolicy,
  1234. Keyname,
  1235. StrValue,
  1236. SCE_BUILD_ENUMERATE_PRIV,
  1237. &NewValue,
  1238. &NewLen);
  1239. if ( rc == SCESTATUS_SUCCESS ) {
  1240. ScepFree(StrValue);
  1241. StrValue = NewValue;
  1242. ValueLen = NewLen;
  1243. }
  1244. }
  1245. }
  1246. if ( ( rc == SCESTATUS_SUCCESS) &&
  1247. !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  1248. StrValue &&
  1249. ( (dwConvertOption & SCE_CONVERT_INF_PRIV) ||
  1250. (dwConvertOption & SCE_CONVERT_INF_GROUP)) ) {
  1251. //
  1252. // convert any free text format accounts from account domain
  1253. // to sid format if it's resolvable.
  1254. //
  1255. NewValue = NULL;
  1256. NewLen = 0;
  1257. rc = ScepConvertFreeTextAccountToSid(&LsaPolicy,
  1258. StrValue,
  1259. ValueLen,
  1260. &NewValue,
  1261. &NewLen);
  1262. if ( ( rc == SCESTATUS_SUCCESS) &&
  1263. NewValue ) {
  1264. ScepFree(StrValue);
  1265. StrValue = NewValue;
  1266. ValueLen = NewLen;
  1267. }
  1268. }
  1269. if ( rc == SCESTATUS_SUCCESS ) {
  1270. //
  1271. // write this line to JET database
  1272. // within policy propagation, write the GPOID too
  1273. //
  1274. rc = SceJetSetLine(
  1275. hSection,
  1276. pKeyStr ? pKeyStr : Keyname,
  1277. FALSE,
  1278. StrValue,
  1279. ValueLen*sizeof(TCHAR),
  1280. (dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
  1281. );
  1282. if ( rc != SCESTATUS_SUCCESS ) {
  1283. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1284. SCEDLL_ERROR_WRITE_INFO, Keyname);
  1285. }
  1286. //
  1287. // if this is not policy propagation and it's the system db,
  1288. // check if the tattoo value exists and if so, update it
  1289. // but if this is in dc demotion, always import them into the
  1290. // tattoo table so at reboot when policy propagates, it would
  1291. // reset the system settings to a standalone server
  1292. //
  1293. if ( !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  1294. (dwTableOption & SCE_TABLE_OPTION_TATTOO) &&
  1295. hSectionTattoo ) {
  1296. if ( pKeyStr )
  1297. Len = wcslen(pKeyStr);
  1298. else
  1299. Len = wcslen(Keyname);
  1300. if ( (dwTableOption & SCE_TABLE_OPTION_DEMOTE_TATTOO) ||
  1301. (SCESTATUS_SUCCESS == SceJetSeek(
  1302. hSectionTattoo,
  1303. pKeyStr ? pKeyStr : Keyname,
  1304. Len*sizeof(WCHAR),
  1305. SCEJET_SEEK_EQ_NO_CASE)) ) {
  1306. SceJetSetLine(
  1307. hSectionTattoo,
  1308. pKeyStr ? pKeyStr : Keyname,
  1309. FALSE,
  1310. StrValue,
  1311. ValueLen*sizeof(TCHAR),
  1312. 0
  1313. );
  1314. }
  1315. }
  1316. ScepFree(StrValue);
  1317. StrValue = NULL;
  1318. if (pKeyList != NULL) {
  1319. if ( (rc=ScepAddToNameList(pKeyList, Keyname,0)) != NO_ERROR ) {
  1320. ScepLogOutput3(1, rc, SCEDLL_SCP_ERROR_ADD, Keyname);
  1321. rc = ScepDosErrorToSceStatus(rc);
  1322. ScepFreeNameList(*pKeyList);
  1323. }
  1324. }
  1325. }
  1326. }
  1327. if ( pKeyStr ) {
  1328. ScepFree(pKeyStr);
  1329. pKeyStr = NULL;
  1330. }
  1331. NextLine:
  1332. if (rc != SCESTATUS_SUCCESS)
  1333. ScepLogOutput3( 1, ScepSceStatusToDosError(rc),
  1334. SCEDLL_ERROR_CONVERT, Keyname);
  1335. }
  1336. } while( rc == SCESTATUS_SUCCESS && SetupFindNextLine(&InfLine, &InfLine));
  1337. SceJetCloseSection( &hSection, TRUE);
  1338. if ( hSectionTattoo )
  1339. SceJetCloseSection( &hSectionTattoo, TRUE);
  1340. }
  1341. if ( LsaPolicy ) {
  1342. LsaClose(LsaPolicy);
  1343. }
  1344. return(rc);
  1345. }
  1346. SCESTATUS
  1347. ScepBuildNewPrivilegeList(
  1348. IN OUT LSA_HANDLE *pPolicyHandle,
  1349. IN PWSTR PrivName,
  1350. IN PWSTR mszUsers,
  1351. IN ULONG dwBuildOption,
  1352. OUT PWSTR *pmszNewUsers,
  1353. OUT DWORD *pNewLen
  1354. )
  1355. {
  1356. if ( pPolicyHandle == NULL ||
  1357. PrivName == NULL || mszUsers == NULL ||
  1358. pmszNewUsers == NULL || pNewLen == NULL ) {
  1359. return(SCESTATUS_INVALID_PARAMETER);
  1360. }
  1361. *pNewLen = 0;
  1362. *pmszNewUsers = NULL;
  1363. //
  1364. // lookup the priv first
  1365. //
  1366. DWORD PrivValue = ScepLookupPrivByName(PrivName);
  1367. if ( PrivValue == -1 || PrivValue >= 64 ) {
  1368. return(SCESTATUS_INVALID_DATA);
  1369. }
  1370. NTSTATUS NtStatus=STATUS_SUCCESS;
  1371. if ( *pPolicyHandle == NULL ) {
  1372. NtStatus = ScepOpenLsaPolicy(
  1373. MAXIMUM_ALLOWED, //GENERIC_ALL,
  1374. pPolicyHandle,
  1375. TRUE
  1376. );
  1377. if ( !NT_SUCCESS(NtStatus) ) {
  1378. return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
  1379. }
  1380. }
  1381. PSCE_PRIVILEGE_VALUE_LIST pAccountList=NULL;
  1382. if ( dwBuildOption & SCE_BUILD_ENUMERATE_PRIV ) {
  1383. NtStatus = ScepBuildAccountsToRemove(
  1384. *pPolicyHandle,
  1385. (PrivValue < 32) ? (1 << PrivValue) : 0,
  1386. (PrivValue >= 32) ? (1 << (PrivValue-32)) : 0,
  1387. SCE_BUILD_IGNORE_UNKNOWN | SCE_BUILD_ACCOUNT_SID_STRING,
  1388. NULL,
  1389. 0,
  1390. NULL,
  1391. &pAccountList
  1392. );
  1393. }
  1394. SCESTATUS rc=SCESTATUS_SUCCESS;
  1395. if ( NT_SUCCESS(NtStatus) ) {
  1396. //
  1397. // pAccountList can be NULL (no users are assigned of this privilege)
  1398. //
  1399. PWSTR pCurr = mszUsers;
  1400. BOOL bMode = FALSE; // add
  1401. DWORD Len;
  1402. DWORD SidStrLen;
  1403. PWSTR CurrSidString=NULL;
  1404. PSCE_PRIVILEGE_VALUE_LIST pTemp, pParent;
  1405. BOOL bFreeCurrSidString = FALSE;
  1406. while ( pCurr && *pCurr != L'\0' ) {
  1407. Len = wcslen(pCurr);
  1408. if ( _wcsicmp(SCE_PRIV_ADD, pCurr) == 0 ) {
  1409. bMode = FALSE; // add
  1410. } else if ( _wcsicmp(SCE_PRIV_REMOVE, pCurr) == 0 ) {
  1411. bMode = TRUE; // remove
  1412. } else {
  1413. //
  1414. // get SID string for the account if it's a name
  1415. //
  1416. if (*pCurr == L'*') {
  1417. CurrSidString = pCurr;
  1418. SidStrLen = Len;
  1419. }
  1420. else if (SCESTATUS_SUCCESS == ScepConvertNameToSidString(
  1421. *pPolicyHandle,
  1422. pCurr,
  1423. FALSE,
  1424. &CurrSidString,
  1425. &SidStrLen
  1426. )) {
  1427. bFreeCurrSidString = TRUE;
  1428. }
  1429. else {
  1430. CurrSidString = pCurr;
  1431. SidStrLen = Len;
  1432. }
  1433. for ( pTemp=pAccountList, pParent=NULL; pTemp != NULL;
  1434. pParent=pTemp, pTemp = pTemp->Next ) {
  1435. if ( _wcsicmp(pTemp->Name, CurrSidString) == 0 ) {
  1436. break;
  1437. }
  1438. }
  1439. if ( bMode == FALSE ) {
  1440. if ( pTemp == NULL ) {
  1441. // add this one in
  1442. rc = ScepAddToPrivilegeList(&pAccountList, CurrSidString, SidStrLen, 0);
  1443. }
  1444. } else {
  1445. if ( pTemp ) {
  1446. // remove this one out
  1447. if ( pParent ) {
  1448. pParent->Next = pTemp->Next;
  1449. } else {
  1450. pAccountList = pTemp->Next;
  1451. }
  1452. // free this one
  1453. pTemp->Next = NULL;
  1454. ScepFreePrivilegeValueList(pTemp);
  1455. pTemp = NULL;
  1456. }
  1457. }
  1458. }
  1459. //
  1460. // free CurrSidString if it's allocated
  1461. // (BVT: have to be careful here - MULTI_SZ potentially being freed many times)
  1462. //
  1463. if ( bFreeCurrSidString ) {
  1464. LocalFree(CurrSidString);
  1465. CurrSidString = NULL;
  1466. bFreeCurrSidString = FALSE;
  1467. }
  1468. SidStrLen = 0;
  1469. if ( SCESTATUS_SUCCESS != rc ) {
  1470. break;
  1471. }
  1472. // move to next element
  1473. pCurr += Len + 1;
  1474. }
  1475. if ( SCESTATUS_SUCCESS == rc ) {
  1476. DWORD TotalLen = 0;
  1477. for ( pTemp=pAccountList; pTemp != NULL; pTemp = pTemp->Next ) {
  1478. pTemp->PrivLowPart = wcslen(pTemp->Name);
  1479. TotalLen += pTemp->PrivLowPart+1;
  1480. }
  1481. *pmszNewUsers = (PWSTR)ScepAlloc(0, (TotalLen+1)*sizeof(WCHAR));
  1482. if (*pmszNewUsers ) {
  1483. *pNewLen = TotalLen;
  1484. TotalLen = 0;
  1485. for ( pTemp=pAccountList; pTemp != NULL && TotalLen <= *pNewLen;
  1486. pTemp = pTemp->Next ) {
  1487. wcscpy(*pmszNewUsers+TotalLen, pTemp->Name);
  1488. TotalLen += pTemp->PrivLowPart;
  1489. *(*pmszNewUsers+TotalLen) = L'\0';
  1490. TotalLen++;
  1491. }
  1492. *(*pmszNewUsers+TotalLen) = L'\0';
  1493. } else {
  1494. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1495. }
  1496. }
  1497. } else {
  1498. rc = ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus));
  1499. }
  1500. return(rc);
  1501. }
  1502. SCESTATUS
  1503. ScepBuildNewMultiSzRegValue(
  1504. IN PWSTR pszKeyName,
  1505. IN PWSTR pszStrValue,
  1506. IN DWORD dwValueLen,
  1507. OUT PWSTR* ppszNewValue,
  1508. OUT PDWORD pdwNewLen
  1509. )
  1510. /* ++
  1511. Routine Description:
  1512. This routine resolves a multisz reg value in add/remove format to
  1513. the exact multisz value
  1514. Arguments:
  1515. pszKeyName [in] - Reg key and value path
  1516. pszStrValue [in] - the multisz value in add/remove
  1517. format including the reg type
  1518. dwValueLen [in] - Number of chars of the value
  1519. ppszNewValue [out] - the resolved value
  1520. pdwNewLen [out] - number of chars for the resolved value
  1521. Return Value:
  1522. SCESTATUS value
  1523. -- */
  1524. {
  1525. PWSTR pszAddList = NULL;
  1526. PWSTR pszRemoveList = NULL;
  1527. PWSTR pCur = NULL;
  1528. PWSTR pAddCur = NULL;
  1529. PWSTR pRemoveCur = NULL;
  1530. DWORD dwAddListSize = 0;
  1531. DWORD dwRemoveListSize = 0;
  1532. BOOL bRemove = FALSE;
  1533. DWORD dwLen = 0;
  1534. SCESTATUS rc = SCESTATUS_SUCCESS;
  1535. //
  1536. // validate parameters
  1537. //
  1538. if(!pszKeyName || !pszStrValue ||
  1539. !ppszNewValue || !pdwNewLen){
  1540. return SCESTATUS_INVALID_PARAMETER;
  1541. }
  1542. //
  1543. // Clear return buffers
  1544. //
  1545. *ppszNewValue = NULL;
  1546. *pdwNewLen = 0;
  1547. //
  1548. // initialize the cursor to skip the reg type
  1549. // which is the first item in the multisz string
  1550. //
  1551. pCur = pszStrValue + wcslen(pszStrValue) + 1;
  1552. //
  1553. // Build the add/remove value into an "add" buffer and
  1554. // "remove" buffer
  1555. //
  1556. while( ( (DWORD)(pCur - pszStrValue) < dwValueLen) &&
  1557. (*pCur != L'\0') ){
  1558. dwLen = wcslen(pCur);
  1559. //
  1560. // Set mode that next item is an "add" item
  1561. // or "remove" item
  1562. //
  1563. if(0 == _wcsicmp(SCE_REG_ADD, pCur)){
  1564. bRemove = FALSE;
  1565. pCur += dwLen + 1;
  1566. continue;
  1567. }
  1568. else if(0 == _wcsicmp(SCE_REG_REMOVE, pCur)){
  1569. bRemove = TRUE;
  1570. pCur += dwLen + 1;
  1571. continue;
  1572. }
  1573. //
  1574. // add to "add" buffer if an "add" item
  1575. //
  1576. if(!bRemove){
  1577. //
  1578. // only allocate the "add list" buffer if we hit an add item
  1579. // and only allocate once
  1580. //
  1581. if(!pszAddList){
  1582. pszAddList = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwValueLen*sizeof(WCHAR));
  1583. if(!pszAddList){
  1584. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1585. goto ExitHandler;
  1586. }
  1587. pAddCur = pszAddList;
  1588. }
  1589. wcscpy(pAddCur, pCur);
  1590. pAddCur += dwLen + 1;
  1591. }
  1592. //
  1593. // add to "remove" buffer if an "remove" item
  1594. //
  1595. else{
  1596. //
  1597. // only allocate the "remove list" buffer if we hit a remove item
  1598. // and only allocate once
  1599. //
  1600. if(!pszRemoveList){
  1601. pszRemoveList = (PWSTR) ScepAlloc(LMEM_ZEROINIT, dwValueLen*sizeof(WCHAR));
  1602. if(!pszRemoveList){
  1603. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1604. goto ExitHandler;
  1605. }
  1606. pRemoveCur = pszRemoveList;
  1607. }
  1608. wcscpy(pRemoveCur, pCur);
  1609. pRemoveCur += dwLen + 1;
  1610. }
  1611. pCur += dwLen + 1;
  1612. }
  1613. //
  1614. // calculate the buffers sizes
  1615. //
  1616. if(pszAddList){
  1617. dwAddListSize = (pAddCur - pszAddList + 1) * sizeof(WCHAR);
  1618. }
  1619. if(pszRemoveList){
  1620. dwRemoveListSize = (pRemoveCur - pszRemoveList + 1) * sizeof(WCHAR);
  1621. }
  1622. //
  1623. // Create the new resolved buffer
  1624. //
  1625. rc = ScepBuildRegMultiSzValue(pszKeyName,
  1626. pszAddList,
  1627. dwAddListSize,
  1628. pszRemoveList,
  1629. dwRemoveListSize,
  1630. pszStrValue,
  1631. ppszNewValue,
  1632. pdwNewLen
  1633. );
  1634. if(SCESTATUS_SUCCESS != rc){
  1635. goto ExitHandler;
  1636. }
  1637. ExitHandler:
  1638. //
  1639. // clean up.
  1640. //
  1641. if(pszAddList){
  1642. ScepFree(pszAddList);
  1643. }
  1644. if(pszRemoveList){
  1645. ScepFree(pszRemoveList);
  1646. }
  1647. if(SCESTATUS_SUCCESS != rc){
  1648. if(*ppszNewValue){
  1649. ScepFree(*ppszNewValue);
  1650. *ppszNewValue = NULL;
  1651. }
  1652. *pdwNewLen = 0;
  1653. }
  1654. return rc;
  1655. }
  1656. SCESTATUS
  1657. ScepBuildRegMultiSzValue(
  1658. IN PWSTR pszKeyName,
  1659. IN PWSTR pszAddList OPTIONAL,
  1660. IN DWORD dwAddSize,
  1661. IN PWSTR pszRemoveList OPTIONAL,
  1662. IN DWORD dwRemoveSize,
  1663. IN PWSTR pszPrefix,
  1664. OUT PWSTR* ppszNewValue,
  1665. OUT PDWORD pdwNewValueLen
  1666. )
  1667. /* ++
  1668. Routine Description:
  1669. This routine resolves a multisz reg value for a given "add" buffer
  1670. and "remove" buffer
  1671. Arguments:
  1672. pszKeyName [in] - Reg key and value path.
  1673. pszAddList [in][optional] - "add" buffer.
  1674. dwAddSize [in] - the "add" buffer size in bytes.
  1675. pszRemoveList [in][optional] - the "remove" buffer.
  1676. dwRemoveSize [in] - the "remove" buffer size in bytes.
  1677. pszPrefix [in] - prefix reg value to be prepended to the
  1678. returned value.
  1679. ppszNewValue [out] - the resolved value.
  1680. pdwNewLen [out] - number of chars for the resolved value.
  1681. Return Value:
  1682. SCESTATUS value
  1683. -- */
  1684. {
  1685. HKEY hKeyRoot = NULL;
  1686. PWSTR pStart = NULL;
  1687. PWSTR pValue = NULL;
  1688. PWSTR pTemp = NULL;
  1689. DWORD rc = ERROR_SUCCESS;
  1690. BOOL bRestoreValue = FALSE;
  1691. PWSTR pszData = NULL;
  1692. DWORD dwDataSize = 0;
  1693. PWSTR pszNewData = NULL;
  1694. DWORD dwNewDataSize = 0;
  1695. DWORD dwRegType = 0;
  1696. DWORD dwPrefixLen = 0;
  1697. //
  1698. // validate parameters
  1699. //
  1700. if(!pszKeyName || !ppszNewValue ||
  1701. !pdwNewValueLen || !pszPrefix){
  1702. return SCESTATUS_INVALID_PARAMETER;
  1703. }
  1704. //
  1705. // we have to have either an add list or a remove list
  1706. //
  1707. if(!pszAddList && !pszRemoveList){
  1708. return SCESTATUS_INVALID_PARAMETER;
  1709. }
  1710. //
  1711. // Clear the return buffers
  1712. //
  1713. *ppszNewValue = NULL;
  1714. *pdwNewValueLen = 0;
  1715. //
  1716. // find the prefix len
  1717. //
  1718. dwPrefixLen = wcslen(pszPrefix);
  1719. //
  1720. // obtain the registry key name
  1721. //
  1722. pStart = wcschr(pszKeyName, L'\\');
  1723. if ( (7 == pStart-pszKeyName) &&
  1724. (0 == _wcsnicmp(L"MACHINE", pszKeyName, 7)) ) {
  1725. hKeyRoot = HKEY_LOCAL_MACHINE;
  1726. } else if ( (5 == pStart-pszKeyName) &&
  1727. (0 == _wcsnicmp(L"USERS", pszKeyName, 5)) ) {
  1728. hKeyRoot = HKEY_USERS;
  1729. } else if ( (12 == pStart-pszKeyName) &&
  1730. (0 == _wcsnicmp(L"CLASSES_ROOT", pszKeyName, 12)) ) {
  1731. hKeyRoot = HKEY_CLASSES_ROOT;
  1732. } else {
  1733. rc = ERROR_INVALID_DATA;
  1734. goto ExitHandler;
  1735. }
  1736. //
  1737. // find the value name
  1738. //
  1739. pValue = pStart+1;
  1740. do {
  1741. pTemp = wcschr(pValue, L'\\');
  1742. if ( pTemp ) {
  1743. pValue = pTemp+1;
  1744. }
  1745. } while ( pTemp );
  1746. if ( pValue == pStart+1 ) {
  1747. rc = ERROR_INVALID_DATA;
  1748. goto ExitHandler;
  1749. }
  1750. //
  1751. // terminate the subkey for now
  1752. //
  1753. *(pValue-1) = L'\0';
  1754. bRestoreValue = TRUE;
  1755. rc = ScepRegQueryValue(hKeyRoot,
  1756. pStart+1,
  1757. pValue,
  1758. (PVOID*)&pszData,
  1759. &dwRegType,
  1760. &dwDataSize
  1761. );
  1762. //
  1763. // if the key or the value is not found or the value is empty,
  1764. // then the new value is the "add" buffer.
  1765. //
  1766. if((ERROR_FILE_NOT_FOUND == rc) ||
  1767. (sizeof(WCHAR) >= dwDataSize)){
  1768. if(pszAddList){
  1769. *ppszNewValue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwAddSize + (dwPrefixLen+1)*sizeof(WCHAR));
  1770. if(!*ppszNewValue){
  1771. rc = ERROR_NOT_ENOUGH_MEMORY;
  1772. goto ExitHandler;
  1773. }
  1774. wcsncpy(*ppszNewValue, pszPrefix, dwPrefixLen);
  1775. CopyMemory(*ppszNewValue + dwPrefixLen + 1, pszAddList, dwAddSize);
  1776. *pdwNewValueLen = (dwAddSize / sizeof(WCHAR)) + dwPrefixLen + 1;
  1777. }
  1778. rc = ERROR_SUCCESS;
  1779. }
  1780. else{
  1781. if(ERROR_SUCCESS != rc){
  1782. goto ExitHandler;
  1783. }
  1784. if(REG_MULTI_SZ != dwRegType){
  1785. rc = ERROR_INVALID_PARAMETER;
  1786. goto ExitHandler;
  1787. }
  1788. //
  1789. // if we have a "remove" buffer, then remove the items from
  1790. // the queried value
  1791. //
  1792. if(pszRemoveList){
  1793. rc = ScepRemoveMultiSzItems(pszData,
  1794. dwDataSize,
  1795. pszRemoveList,
  1796. dwRemoveSize,
  1797. &pszNewData,
  1798. &dwNewDataSize
  1799. );
  1800. if(ERROR_SUCCESS != rc){
  1801. goto ExitHandler;
  1802. }
  1803. }
  1804. //
  1805. // if we have an "add" buffer, then add the items to the
  1806. // value
  1807. //
  1808. if(pszAddList){
  1809. if(pszData && pszNewData){
  1810. ScepFree(pszData);
  1811. pszData = pszNewData;
  1812. dwDataSize = dwNewDataSize;
  1813. pszNewData = NULL;
  1814. dwNewDataSize = 0;
  1815. }
  1816. rc = ScepAddMultiSzItems(pszData,
  1817. dwDataSize,
  1818. pszAddList,
  1819. dwAddSize,
  1820. &pszNewData,
  1821. &dwNewDataSize
  1822. );
  1823. if(ERROR_SUCCESS != rc){
  1824. goto ExitHandler;
  1825. }
  1826. }
  1827. *ppszNewValue = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwNewDataSize + (dwPrefixLen+1)*sizeof(WCHAR));
  1828. if(!*ppszNewValue){
  1829. rc = ERROR_NOT_ENOUGH_MEMORY;
  1830. goto ExitHandler;
  1831. }
  1832. wcsncpy(*ppszNewValue, pszPrefix, dwPrefixLen);
  1833. CopyMemory(*ppszNewValue + dwPrefixLen + 1, pszNewData, dwNewDataSize);
  1834. *pdwNewValueLen = (dwNewDataSize / sizeof(WCHAR)) + dwPrefixLen + 1;
  1835. }
  1836. ExitHandler:
  1837. //
  1838. // clean up.
  1839. //
  1840. if(bRestoreValue){
  1841. *(pValue-1) = L'\\';
  1842. }
  1843. if(pszData){
  1844. ScepFree(pszData);
  1845. }
  1846. if(pszNewData){
  1847. ScepFree(pszNewData);
  1848. }
  1849. if(ERROR_SUCCESS != rc){
  1850. if(*ppszNewValue){
  1851. ScepFree(*ppszNewValue);
  1852. *ppszNewValue = NULL;
  1853. }
  1854. *pdwNewValueLen = 0;
  1855. }
  1856. return ScepDosErrorToSceStatus(rc);
  1857. }
  1858. SCESTATUS
  1859. SceConvertpInfObject(
  1860. IN PCWSTR InfSectionName,
  1861. IN UINT ObjectType,
  1862. IN DWORD ObjectFlag,
  1863. IN HINF hInf,
  1864. IN PSCECONTEXT hProfile,
  1865. IN DWORD dwTableOption,
  1866. IN LONG GpoID
  1867. )
  1868. /* ++
  1869. Routine Description:
  1870. This routine converts INF sections which are in object-security format,
  1871. for example, Registry Keys and File Security sections. These sections
  1872. must have 3 fields on each line. The first field is the object's name,
  1873. the second field is a status flag, and the third field is the security
  1874. descriptor text. The infomration saved in the Jet database for each
  1875. object is the object's name as the key, and the text format security
  1876. descriptor plus 1 byte status flag as the value.
  1877. Arguments:
  1878. InfSectionName - the INF section name to convert
  1879. ObjectType - The object's type
  1880. 1 = Registry
  1881. 2 = File
  1882. 3 = DS object
  1883. hInf - the Inf file handle
  1884. hprofile - the Jet database context
  1885. Return Value:
  1886. -- */
  1887. {
  1888. SCESTATUS rc;
  1889. DOUBLE SectionID;
  1890. PSCESECTION hSection=NULL;
  1891. PSCESECTION hSectionTattoo=NULL;
  1892. INFCONTEXT InfLine;
  1893. PWSTR TempName=NULL;
  1894. PWSTR Name=NULL;
  1895. PWSTR Value=NULL;
  1896. DWORD ValueLen;
  1897. SCEINF_STATUS InfErr;
  1898. TCHAR ObjName[MAX_PATH];
  1899. if ( InfSectionName == NULL ||
  1900. hInf == INVALID_HANDLE_VALUE ||
  1901. hProfile == NULL ) {
  1902. return(SCESTATUS_INVALID_PARAMETER);
  1903. }
  1904. //
  1905. // get section's ID. if the section does not exist, add it to the section table
  1906. //
  1907. rc = SceJetGetSectionIDByName(
  1908. hProfile,
  1909. InfSectionName,
  1910. &SectionID
  1911. );
  1912. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  1913. rc = SceJetAddSection(
  1914. hProfile,
  1915. InfSectionName,
  1916. &SectionID
  1917. );
  1918. }
  1919. if ( rc != SCESTATUS_SUCCESS ) {
  1920. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1921. SCEDLL_SCP_ERROR_ADD, (PWSTR)InfSectionName);
  1922. return(rc);
  1923. }
  1924. if ( SetupFindFirstLine(hInf,InfSectionName,NULL,&InfLine) ) {
  1925. //
  1926. // open the section
  1927. //
  1928. if ( dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY ) {
  1929. rc = SceJetOpenSection(
  1930. hProfile,
  1931. SectionID,
  1932. SCEJET_TABLE_SCP,
  1933. &hSection
  1934. );
  1935. } else {
  1936. //
  1937. // SMP exists, also open the SMP section
  1938. //
  1939. rc = SceJetOpenSection(
  1940. hProfile,
  1941. SectionID,
  1942. SCEJET_TABLE_SMP,
  1943. &hSection
  1944. );
  1945. if ( dwTableOption & SCE_TABLE_OPTION_TATTOO ) {
  1946. //
  1947. // if it's in setup, should check if tattoo table needs to be updated
  1948. // do not care error
  1949. //
  1950. SceJetOpenSection(
  1951. hProfile,
  1952. SectionID,
  1953. SCEJET_TABLE_TATTOO,
  1954. &hSectionTattoo
  1955. );
  1956. }
  1957. }
  1958. if ( rc != SCESTATUS_SUCCESS ) {
  1959. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  1960. SCEDLL_ERROR_OPEN, (PWSTR)InfSectionName);
  1961. if ( hSection )
  1962. SceJetCloseSection( &hSection, TRUE);
  1963. if ( hSectionTattoo )
  1964. SceJetCloseSection( &hSectionTattoo, TRUE);
  1965. return(rc);
  1966. }
  1967. //
  1968. // process each line in the section and save to the scp table.
  1969. //
  1970. BOOL bIgnore;
  1971. do {
  1972. //
  1973. // Get string fields. Don't care the key name or if it exist.
  1974. // Must have at least 3 fields each line.
  1975. //
  1976. bIgnore = FALSE;
  1977. InfErr = SceInfpGetOneObject(&InfLine,
  1978. ObjectFlag,
  1979. &TempName,
  1980. &Value,
  1981. &ValueLen
  1982. );
  1983. rc = ScepDosErrorToSceStatus(InfErr);
  1984. if ( rc == SCESTATUS_SUCCESS && TempName != NULL ) {
  1985. //
  1986. // check to see if the object name needs translated
  1987. //
  1988. if ( ObjectType == 3 ) {
  1989. //
  1990. // DS object
  1991. //
  1992. rc = ScepConvertLdapToJetIndexName(TempName, &Name);
  1993. } else if ( ObjectType == 2 && TempName[0] == L'\\' ) {
  1994. //
  1995. // do not support UNC name format
  1996. //
  1997. rc = SCESTATUS_INVALID_DATA;
  1998. } else if ( ObjectType == 2 && wcschr(TempName, L'%') != NULL ) {
  1999. //
  2000. // translate the name
  2001. //
  2002. rc = ScepTranslateFileDirName( TempName, &Name);
  2003. if ( rc == ERROR_PATH_NOT_FOUND ) {
  2004. if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION )
  2005. bIgnore = TRUE;
  2006. rc = SCESTATUS_INVALID_DATA;
  2007. } else if ( rc != NO_ERROR )
  2008. rc = ScepDosErrorToSceStatus(rc);
  2009. } else {
  2010. Name = TempName;
  2011. TempName = NULL;
  2012. }
  2013. //
  2014. // write this line to JET database
  2015. //
  2016. if ( rc == SCESTATUS_SUCCESS ) {
  2017. //
  2018. // convert to lowercase
  2019. //
  2020. Name = _wcslwr(Name);
  2021. //
  2022. // within policy propagation, write the GPOID too
  2023. //
  2024. rc = SceJetSetLine(
  2025. hSection,
  2026. Name,
  2027. TRUE,
  2028. Value,
  2029. ValueLen*sizeof(TCHAR),
  2030. (dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) ? GpoID : 0
  2031. );
  2032. if ( hSectionTattoo &&
  2033. !(dwTableOption & SCE_TABLE_OPTION_MERGE_POLICY) &&
  2034. (dwTableOption & SCE_TABLE_OPTION_TATTOO ) ) {
  2035. //
  2036. // if it's in setup (not policy prop) and tattoo table exists
  2037. // check if tattoo value exists for this one and if so, update it
  2038. // do not care error
  2039. //
  2040. if ( SCESTATUS_SUCCESS == SceJetSeek(
  2041. hSectionTattoo,
  2042. Name,
  2043. wcslen(Name)*sizeof(WCHAR),
  2044. SCEJET_SEEK_EQ_NO_CASE) ) {
  2045. SceJetSetLine(
  2046. hSectionTattoo,
  2047. Name,
  2048. TRUE,
  2049. Value,
  2050. ValueLen*sizeof(TCHAR),
  2051. 0
  2052. );
  2053. }
  2054. }
  2055. }
  2056. if ( rc != SCESTATUS_SUCCESS) {
  2057. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  2058. SCEDLL_ERROR_CONVERT, TempName );
  2059. }
  2060. ScepFree(Value);
  2061. Value = NULL;
  2062. ScepFree(TempName);
  2063. TempName = NULL;
  2064. ScepFree(Name);
  2065. Name = NULL;
  2066. } else if ( (ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION) &&
  2067. rc == SCESTATUS_SUCCESS && TempName == NULL ) {
  2068. //
  2069. // this one is ignored because it came from a newer version
  2070. // of template.
  2071. //
  2072. } else {
  2073. ObjName[0] = L'\0';
  2074. SetupGetStringField(&InfLine,1,ObjName,MAX_PATH,&ValueLen);
  2075. ScepLogOutput3(1, ScepSceStatusToDosError(rc),
  2076. SCEDLL_ERROR_CONVERT, ObjName );
  2077. }
  2078. //
  2079. // for a newer version template, if a env variable can't be resolved
  2080. // it will be ignored.
  2081. //
  2082. if ( bIgnore ) rc = SCESTATUS_SUCCESS;
  2083. if ( SCESTATUS_INVALID_DATA == rc ) {
  2084. //
  2085. // if a environment variable or other invalid data is found
  2086. // in the template, will continue to process other areas/items
  2087. // but the error will be eventually returned to the caller
  2088. //
  2089. gbInvalidData = TRUE;
  2090. rc = SCESTATUS_SUCCESS;
  2091. }
  2092. if ( rc != SCESTATUS_SUCCESS )
  2093. break; // do..while loop
  2094. } while( SetupFindNextLine(&InfLine,&InfLine) );
  2095. SceJetCloseSection( &hSection, TRUE);
  2096. if ( hSectionTattoo ) SceJetCloseSection( &hSectionTattoo, TRUE);
  2097. }
  2098. return(rc);
  2099. }
  2100. SCEINF_STATUS
  2101. SceInfpGetOneObject(
  2102. IN PINFCONTEXT pInfLine,
  2103. IN DWORD ObjectFlag,
  2104. OUT PWSTR *Name,
  2105. OUT PWSTR *Value,
  2106. OUT PDWORD ValueLen
  2107. )
  2108. /* ++
  2109. Routine Description:
  2110. This routine retrieves security setting for one object (a registry key,
  2111. or a file) from the INF file (SCP type). Each object in these sections
  2112. is represented by one line. Each object has 3 fields, a name, status flag,
  2113. and a security setting.
  2114. Arguments:
  2115. pInfLine - Current line context from the INF file for one object
  2116. Name - The object name
  2117. Value - The status flag ( 1 byte) plus the security descriptor in text
  2118. ValueLen - the length of the value
  2119. Return value:
  2120. SCESTATUS - SCEINF_SUCCESS
  2121. SCEINF_WARNING
  2122. SCEINF_NOT_ENOUGH_MEMORY
  2123. SCEINF_INVALID_PARAMETER
  2124. SCEINF_CORRUPT_PROFILE
  2125. SCEINF_INVALID_DATA
  2126. -- */
  2127. {
  2128. SCEINF_STATUS rc=ERROR_BAD_FORMAT;
  2129. DWORD cFields;
  2130. INT Keyvalue1=0;
  2131. DWORD Keyvalue2=0;
  2132. DWORD DataSize;
  2133. PWSTR SDspec=NULL;
  2134. DWORD Len=0;
  2135. //
  2136. // The Registry/File INF layout must have 3 fields for each line.
  2137. // The first field is the key/file name, the 2nd field is the security descriptor index
  2138. // for workstations, and the 3rd field is the security descriptor index for servers
  2139. //
  2140. if ( Name == NULL || Value == NULL ) {
  2141. return(ERROR_INVALID_PARAMETER);
  2142. }
  2143. *Name = NULL;
  2144. *Value = NULL;
  2145. *ValueLen = 0;
  2146. cFields = SetupGetFieldCount( pInfLine );
  2147. if ( cFields < 3 ) {
  2148. if ( ObjectFlag & SCE_OBJECT_FLAG_UNKNOWN_VERSION ) {
  2149. return(ERROR_SUCCESS);
  2150. } else {
  2151. return(ERROR_INVALID_DATA);
  2152. }
  2153. } else if(SetupGetStringField(pInfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
  2154. *Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  2155. (DataSize+1)*sizeof(TCHAR) );
  2156. if( *Name == NULL ) {
  2157. return(ERROR_NOT_ENOUGH_MEMORY);
  2158. } else {
  2159. //
  2160. // the first field is the key/file name. the status is ERROR_BAD_FORMAT now
  2161. //
  2162. if(SetupGetStringField(pInfLine,1,*Name,DataSize,NULL)) {
  2163. #ifdef SCE_DBG
  2164. ScepLogOutput2(0,0, L"Read %s", *Name );
  2165. #endif
  2166. //
  2167. // The 2nd field is the status
  2168. // The 3rd field (and all fields after) is the security descriptor text
  2169. //
  2170. if ( SetupGetIntField(pInfLine, 2, (INT *)&Keyvalue1) &&
  2171. // SetupGetStringField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
  2172. SetupGetMultiSzField(pInfLine, 3, NULL, 0, &Keyvalue2) ) {
  2173. *Value = (PWSTR)ScepAlloc( 0, (Keyvalue2+2)*sizeof(WCHAR));
  2174. //
  2175. // add this object
  2176. //
  2177. if ( *Value == NULL ) {
  2178. rc = ERROR_NOT_ENOUGH_MEMORY;
  2179. // } else if ( SetupGetStringField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
  2180. } else if ( SetupGetMultiSzField(pInfLine, 3, (*Value)+1, Keyvalue2, NULL) ) {
  2181. if ( ObjectFlag & SCE_OBJECT_FLAG_OBJECTS ) {
  2182. if ( Keyvalue1 > SCE_STATUS_NO_AUTO_INHERIT ||
  2183. Keyvalue1 < SCE_STATUS_CHECK ) {
  2184. Keyvalue1 = SCE_STATUS_CHECK;
  2185. }
  2186. *((BYTE *)(*Value)) = (BYTE)Keyvalue1;
  2187. *((CHAR *)(*Value)+1) = '1'; //always treat as container
  2188. } else {
  2189. //
  2190. // services
  2191. //
  2192. if ( Keyvalue1 > SCE_STARTUP_DISABLED ||
  2193. Keyvalue1 < SCE_STARTUP_BOOT ) {
  2194. //
  2195. // default
  2196. //
  2197. Keyvalue1 = SCE_STARTUP_MANUAL;
  2198. }
  2199. *((BYTE *)(*Value)) = 0; // always set status to 0
  2200. *((BYTE *)(*Value)+1) = (BYTE)Keyvalue1;
  2201. }
  2202. //
  2203. // convert the multi-sz delimiter to space, if there is any
  2204. //
  2205. if ( cFields > 3 ) {
  2206. ScepConvertMultiSzToDelim( (*Value+1), Keyvalue2, L'\0', L' ');
  2207. }
  2208. if ( ObjectFlag & SCE_OBJECT_FLAG_OLDSDDL ) {
  2209. //
  2210. // convert old SDDL string to new one
  2211. //
  2212. ScepConvertToSDDLFormat( (*Value+1), Keyvalue2 );
  2213. }
  2214. *ValueLen = Keyvalue2+1;
  2215. rc = ERROR_SUCCESS;
  2216. } else {
  2217. ScepFree(*Value);
  2218. *Value = NULL;
  2219. rc = ERROR_INVALID_DATA;
  2220. }
  2221. }
  2222. }
  2223. // if error, free the memory allocated
  2224. if ( rc != ERROR_SUCCESS ) {
  2225. ScepFree(*Name);
  2226. *Name = NULL;
  2227. }
  2228. }
  2229. }
  2230. if ( rc == ERROR_SUCCESS) {
  2231. //
  2232. // conver the object name to upper case
  2233. //
  2234. // _wcsupr(*Name); should not do this..
  2235. }
  2236. return(rc);
  2237. }
  2238. SCESTATUS
  2239. SceConvertpInfDescription(
  2240. IN HINF hInf,
  2241. IN PSCECONTEXT hProfile
  2242. )
  2243. {
  2244. INFCONTEXT InfLine;
  2245. SCESTATUS rc=SCESTATUS_SUCCESS;
  2246. WCHAR Description[513];
  2247. DWORD Len=0;
  2248. DWORD DataSize=0;
  2249. DWORD i, cFields;
  2250. if ( hInf == INVALID_HANDLE_VALUE ||
  2251. hProfile == NULL ) {
  2252. return(SCESTATUS_INVALID_PARAMETER);
  2253. }
  2254. if ( SetupFindFirstLine(hInf,szDescription,NULL,&InfLine) ) {
  2255. memset(Description, '\0', 513*sizeof(WCHAR));
  2256. // get description from Inf
  2257. do {
  2258. cFields = SetupGetFieldCount( &InfLine );
  2259. for ( i=0; i<cFields && rc==SCESTATUS_SUCCESS; i++) {
  2260. if(SetupGetStringField(&InfLine, i+1, Description+Len, 512-Len, &DataSize) ) {
  2261. Len += DataSize;
  2262. if ( Len >= 512 ) {
  2263. Len = 512;
  2264. Description[512] = L'\0';
  2265. break;
  2266. }
  2267. if ( i == cFields-1 )
  2268. Description[Len-1] = L' ';
  2269. else
  2270. Description[Len-1] = L',';
  2271. } else
  2272. rc = SCESTATUS_INVALID_DATA;
  2273. }
  2274. if ( Len >= 512 )
  2275. break;
  2276. } while ( rc == SCESTATUS_SUCCESS &&
  2277. SetupFindNextLine(&InfLine, &InfLine));
  2278. if ( rc == SCESTATUS_SUCCESS && Description[0] ) {
  2279. //
  2280. // save description to Jet
  2281. // NOTE: Jet requires long value update must be done in a transaction
  2282. //
  2283. rc = SceJetStartTransaction( hProfile );
  2284. if ( SCESTATUS_SUCCESS == rc ) {
  2285. Description[Len] = L'\0';
  2286. rc = SceJetSetValueInVersion(
  2287. hProfile,
  2288. "SmTblVersion",
  2289. "ProfileDescription",
  2290. (PWSTR)Description,
  2291. Len*sizeof(WCHAR),
  2292. JET_prepReplace
  2293. );
  2294. if ( SCESTATUS_SUCCESS == rc ) {
  2295. SceJetCommitTransaction( hProfile, 0 );
  2296. } else {
  2297. SceJetRollback( hProfile, 0 );
  2298. }
  2299. }
  2300. }
  2301. }
  2302. return(rc);
  2303. }
  2304. SCESTATUS
  2305. ScepConvertRelativeSidToSidString(
  2306. IN PWSTR pwszRelSid,
  2307. OUT PWSTR *ppwszSid)
  2308. /*
  2309. Routine Description:
  2310. Given a relative SID string "#-RSID", convert to full SID "*S-domain SID-RSID"
  2311. relative to primary domain
  2312. Arguments:
  2313. pwszRelSid - relative SID
  2314. ppwszSid - output SID
  2315. Return Value:
  2316. WIN32 error code
  2317. */
  2318. {
  2319. NTSTATUS NtStatus;
  2320. DWORD rc = ERROR_SUCCESS;
  2321. PPOLICY_ACCOUNT_DOMAIN_INFO AccountDomainInfo=NULL;
  2322. PPOLICY_PRIMARY_DOMAIN_INFO PrimaryDomainInfo=NULL;
  2323. ULONG ulRid;
  2324. DWORD dwSize;
  2325. PWSTR pwszDomainSid = NULL;
  2326. //
  2327. // get primary domain SID
  2328. //
  2329. NtStatus = ScepGetLsaDomainInfo(
  2330. &AccountDomainInfo,
  2331. &PrimaryDomainInfo
  2332. );
  2333. rc = RtlNtStatusToDosError(NtStatus);
  2334. if ( ERROR_SUCCESS == rc )
  2335. {
  2336. rc = ScepConvertSidToPrefixStringSid(
  2337. PrimaryDomainInfo->Sid,
  2338. &pwszDomainSid);
  2339. }
  2340. if ( ERROR_SUCCESS == rc ) {
  2341. *ppwszSid = (LPWSTR) ScepAlloc(LMEM_ZEROINIT,
  2342. (wcslen(pwszDomainSid) + wcslen(&pwszRelSid[1]) + 1) * sizeof(WCHAR));
  2343. if(!*ppwszSid)
  2344. rc = ERROR_NOT_ENOUGH_MEMORY;
  2345. }
  2346. //
  2347. // build full SID from domain SID and #-RSID, skipping the #
  2348. //
  2349. if ( ERROR_SUCCESS == rc ) {
  2350. wcscpy(*ppwszSid, pwszDomainSid);
  2351. wcscat(*ppwszSid, &pwszRelSid[1]);
  2352. }
  2353. if(AccountDomainInfo != NULL) {
  2354. LsaFreeMemory(AccountDomainInfo);
  2355. }
  2356. if(PrimaryDomainInfo != NULL) {
  2357. LsaFreeMemory(PrimaryDomainInfo);
  2358. }
  2359. return(ScepDosErrorToSceStatus(rc));
  2360. }
  2361. SCESTATUS
  2362. ScepConvertSpecialAccountToSid(
  2363. IN OUT LSA_HANDLE *pPolicyHandle,
  2364. IN PWSTR mszAccounts,
  2365. IN ULONG dwLen,
  2366. bool fFreeTextAccount,
  2367. OUT PWSTR *pmszNewAccounts,
  2368. OUT DWORD *pNewLen
  2369. )
  2370. {
  2371. if ( pPolicyHandle == NULL ||
  2372. pmszNewAccounts == NULL || pNewLen == NULL ) {
  2373. return(SCESTATUS_INVALID_PARAMETER);
  2374. }
  2375. *pNewLen = 0;
  2376. *pmszNewAccounts = NULL;
  2377. PWSTR pCurr = mszAccounts;
  2378. DWORD cnt=0;
  2379. //
  2380. // count how many entries in the list
  2381. //
  2382. while ( pCurr && *pCurr != L'\0' ) {
  2383. cnt++;
  2384. pCurr += wcslen(pCurr)+1;
  2385. }
  2386. if ( cnt == 0 ) {
  2387. return(SCESTATUS_SUCCESS);
  2388. }
  2389. NTSTATUS NtStatus=STATUS_SUCCESS;
  2390. if ( *pPolicyHandle == NULL ) {
  2391. NtStatus = ScepOpenLsaPolicy(
  2392. MAXIMUM_ALLOWED, //GENERIC_ALL,
  2393. pPolicyHandle,
  2394. TRUE
  2395. );
  2396. if ( !NT_SUCCESS(NtStatus) ) {
  2397. return(ScepDosErrorToSceStatus(RtlNtStatusToDosError(NtStatus)));
  2398. }
  2399. }
  2400. //
  2401. // allocate temp buffer for the sid string pointers
  2402. //
  2403. PWSTR *pSidStrs = (PWSTR *)ScepAlloc(LPTR, cnt*sizeof(PWSTR));
  2404. if ( pSidStrs == NULL ) {
  2405. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2406. }
  2407. DWORD *pSidLen = (DWORD *)ScepAlloc(LPTR, cnt*sizeof(DWORD));
  2408. if ( pSidLen == NULL ) {
  2409. ScepFree(pSidStrs);
  2410. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2411. }
  2412. BOOL *pSidFree = (BOOL *)ScepAlloc(LPTR, cnt*sizeof(BOOL));
  2413. if ( pSidFree == NULL ) {
  2414. ScepFree(pSidStrs);
  2415. ScepFree(pSidLen);
  2416. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2417. }
  2418. pCurr = mszAccounts;
  2419. DWORD i = 0;
  2420. BOOL bConvert=FALSE;
  2421. PWSTR SidString, pTemp;
  2422. DWORD StrLen;
  2423. SCESTATUS rc;
  2424. while ( pCurr && *pCurr != L'\0' &&
  2425. ( i < cnt ) ) {
  2426. pSidStrs[i] = pCurr;
  2427. pSidFree[i] = FALSE;
  2428. pSidLen[i] = wcslen(pCurr);
  2429. pTemp = pCurr + pSidLen[i] + 1;
  2430. if ( fFreeTextAccount && *pCurr != L'*' && wcschr(pCurr, L'\\') == 0 ) {
  2431. //
  2432. // this is a name format and it's an isolated name
  2433. // let's resolve it to a SID string
  2434. //
  2435. SidString = NULL;
  2436. StrLen = 0;
  2437. rc = ScepConvertNameToSidString( *pPolicyHandle,
  2438. pCurr,
  2439. FALSE, //TRUE,
  2440. &SidString,
  2441. &StrLen
  2442. );
  2443. if ( rc == SCESTATUS_SUCCESS &&
  2444. SidString ) {
  2445. //
  2446. // got a sid string
  2447. //
  2448. pSidStrs[i] = SidString;
  2449. pSidLen[i] = StrLen;
  2450. pSidFree[i] = TRUE;
  2451. bConvert = TRUE;
  2452. }
  2453. }
  2454. else if ( !fFreeTextAccount && *pCurr == RELATIVE_SID_PREFIX ) {
  2455. // this is a relative SID in format "#-512", convert to "*S-current domain SID-512"
  2456. rc = ScepConvertRelativeSidToSidString(pCurr, &SidString);
  2457. if( SCESTATUS_SUCCESS == rc) {
  2458. pSidStrs[i] = SidString;
  2459. pSidLen[i] = wcslen(SidString);
  2460. pSidFree[i] = TRUE;
  2461. bConvert = TRUE;
  2462. }
  2463. }
  2464. i ++;
  2465. pCurr = pTemp;
  2466. }
  2467. //
  2468. // now we need to build the new string
  2469. //
  2470. rc = SCESTATUS_SUCCESS;
  2471. if ( bConvert ) {
  2472. DWORD dwTotal=0;
  2473. for ( i=0; i<cnt; i++ ) {
  2474. dwTotal += pSidLen[i];
  2475. dwTotal ++; // for the NULL terminator
  2476. }
  2477. if ( dwTotal ) {
  2478. dwTotal ++; // for the last NULL terminator
  2479. *pmszNewAccounts = (PWSTR)ScepAlloc(LPTR, dwTotal*sizeof(WCHAR));
  2480. if ( *pmszNewAccounts ) {
  2481. pCurr = *pmszNewAccounts;
  2482. for ( i=0; i<cnt; i++ ) {
  2483. wcsncpy(pCurr, pSidStrs[i], pSidLen[i]);
  2484. pCurr += pSidLen[i];
  2485. *pCurr = L'\0';
  2486. pCurr++;
  2487. }
  2488. *pNewLen = dwTotal;
  2489. } else {
  2490. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2491. }
  2492. }
  2493. }
  2494. for ( i=0; i<cnt; i++ ) {
  2495. if ( pSidFree[i] && pSidStrs[i] ) {
  2496. ScepFree(pSidStrs[i]);
  2497. }
  2498. }
  2499. ScepFree(pSidStrs);
  2500. ScepFree(pSidLen);
  2501. ScepFree(pSidFree);
  2502. return(rc);
  2503. }
  2504. SCESTATUS
  2505. ScepConvertFreeTextAccountToSid(
  2506. IN OUT LSA_HANDLE *pPolicyHandle,
  2507. IN PWSTR mszAccounts,
  2508. IN ULONG dwLen,
  2509. OUT PWSTR *pmszNewAccounts,
  2510. OUT DWORD *pNewLen
  2511. )
  2512. {
  2513. return ScepConvertSpecialAccountToSid(
  2514. pPolicyHandle,
  2515. mszAccounts,
  2516. dwLen,
  2517. true,
  2518. pmszNewAccounts,
  2519. pNewLen);
  2520. }
  2521. SCESTATUS
  2522. ScepConvertRelativeSidAccountToSid(
  2523. IN OUT LSA_HANDLE *pPolicyHandle,
  2524. IN PWSTR mszAccounts,
  2525. IN ULONG dwLen,
  2526. OUT PWSTR *pmszNewAccounts,
  2527. OUT DWORD *pNewLen
  2528. )
  2529. {
  2530. return ScepConvertSpecialAccountToSid(
  2531. pPolicyHandle,
  2532. mszAccounts,
  2533. dwLen,
  2534. false,
  2535. pmszNewAccounts,
  2536. pNewLen);
  2537. }