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.

6510 lines
195 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. pfget.cpp
  5. Abstract:
  6. Routines to get information from jet database (configuration/analysis
  7. info).
  8. Author:
  9. Jin Huang (jinhuang) 28-Oct-1996
  10. Revision History:
  11. jinhuang 26-Jan-1998 splitted to client-server
  12. --*/
  13. #include "serverp.h"
  14. #include <io.h>
  15. #include "pfp.h"
  16. #include "kerberos.h"
  17. #include "regvalue.h"
  18. #include <sddl.h>
  19. #pragma hdrstop
  20. //#define SCE_DBG 1
  21. #define SCE_INTERNAL_NP 0x80
  22. #define SCE_ALLOC_MAX_NODE 10
  23. typedef struct _SCE_BROWSE_CALLBACK_VALUE {
  24. DWORD Len;
  25. UCHAR *Value;
  26. } SCE_BROWSE_CALLBACK_VALUE;
  27. //
  28. // Forward references
  29. //
  30. SCESTATUS
  31. ScepGetSystemAccess(
  32. IN PSCECONTEXT hProfile,
  33. IN SCETYPE ProfileType,
  34. OUT PSCE_PROFILE_INFO pProfileInfo,
  35. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  36. );
  37. SCESTATUS
  38. ScepGetVariableValue(
  39. IN PSCESECTION hSection,
  40. IN SCETYPE ProfileType,
  41. IN PCWSTR KeyName,
  42. OUT PWSTR *Value,
  43. OUT PDWORD ValueLen
  44. );
  45. SCESTATUS
  46. ScepAddToPrivilegeList(
  47. OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
  48. IN PWSTR Name,
  49. IN DWORD Len,
  50. IN DWORD PrivValue
  51. );
  52. SCESTATUS
  53. ScepGetGroupMembership(
  54. IN PSCECONTEXT hProfile,
  55. IN SCETYPE ProfileType,
  56. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  57. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  58. );
  59. SCESTATUS
  60. ScepGetGroupMembershipFromOneTable(
  61. IN LSA_HANDLE LsaPolicy,
  62. IN PSCECONTEXT hProfile,
  63. IN SCETYPE ProfileType,
  64. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  65. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  66. );
  67. SCESTATUS
  68. ScepGetObjectList(
  69. IN PSCECONTEXT hProfile,
  70. IN SCETYPE ProfileType,
  71. IN PCWSTR SectionName,
  72. OUT PSCE_OBJECT_LIST *pObjectRoots,
  73. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  74. );
  75. SCESTATUS
  76. ScepGetDsRoot(
  77. IN PSCECONTEXT hProfile,
  78. IN SCETYPE ProfileType,
  79. IN PCWSTR SectionName,
  80. OUT PSCE_OBJECT_LIST *pObjectRoots,
  81. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  82. );
  83. SCESTATUS
  84. ScepBuildDsTree(
  85. OUT PSCE_OBJECT_CHILD_LIST *TreeRoot,
  86. IN ULONG Level,
  87. IN WCHAR Delim,
  88. IN PCWSTR ObjectFullName
  89. );
  90. SCESTATUS
  91. ScepGetObjectFromOneTable(
  92. IN PSCECONTEXT hProfile,
  93. IN SCETYPE ProfileType,
  94. IN PCWSTR SectionName,
  95. OUT PSCE_OBJECT_LIST *pObjectRoots,
  96. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  97. );
  98. SCESTATUS
  99. ScepGetObjectChildrenFromOneTable(
  100. IN PSCECONTEXT hProfile,
  101. IN SCETYPE ProfileType,
  102. IN AREA_INFORMATION Area,
  103. IN PWSTR ObjectPrefix,
  104. IN SCE_SUBOBJECT_TYPE Option,
  105. OUT PVOID *Buffer,
  106. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  107. );
  108. BYTE
  109. ScepGetObjectStatusFlag(
  110. IN PSCECONTEXT hProfile,
  111. IN SCETYPE ProfileType,
  112. IN AREA_INFORMATION Area,
  113. IN PWSTR ObjectPrefix,
  114. IN BOOL bLookForParent
  115. );
  116. SCESTATUS
  117. ScepGetAuditing(
  118. IN PSCECONTEXT hProfile,
  119. IN SCETYPE ProfileType,
  120. OUT PSCE_PROFILE_INFO pProfileInfo,
  121. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  122. );
  123. SCESTATUS
  124. ScepGetPrivilegesFromOneTable(
  125. IN LSA_HANDLE LsaPolicy,
  126. IN PSCECONTEXT hProfile,
  127. IN SCETYPE ProfileType,
  128. IN DWORD dwAccountFormat,
  129. OUT PVOID *pPrivileges,
  130. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  131. );
  132. SCESTATUS
  133. ScepGetSystemServices(
  134. IN PSCECONTEXT hProfile,
  135. IN SCETYPE ProfileType,
  136. OUT PSCE_SERVICES *pServiceList,
  137. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  138. );
  139. BOOL
  140. ScepSearchItemInChildren(
  141. IN PWSTR ItemName,
  142. IN DWORD NameLen,
  143. IN PSCE_OBJECT_CHILDREN_NODE *pArrObject,
  144. IN DWORD arrCount,
  145. OUT LONG *pFindIndex
  146. );
  147. DWORD
  148. ScepAddItemToChildren(
  149. IN PSCE_OBJECT_CHILDREN_NODE ThisNode OPTIONAL,
  150. IN PWSTR ItemName,
  151. IN DWORD NameLen,
  152. IN BOOL IsContainer,
  153. IN BYTE Status,
  154. IN DWORD ChildCount,
  155. IN OUT PSCE_OBJECT_CHILDREN_NODE **ppArrObject,
  156. IN OUT DWORD *pArrCount,
  157. IN OUT DWORD *pMaxCount,
  158. IN OUT LONG *pFindIndex
  159. );
  160. PWSTR
  161. ScepSpecialCaseRegkeyCcs(
  162. IN OUT PWSTR ObjectName
  163. );
  164. //
  165. // function definitions
  166. //
  167. SCESTATUS
  168. ScepGetDatabaseInfo(
  169. IN PSCECONTEXT hProfile,
  170. IN SCETYPE ProfileType,
  171. IN AREA_INFORMATION Area,
  172. IN DWORD dwAccountFormat,
  173. OUT PSCE_PROFILE_INFO *ppInfoBuffer,
  174. IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  175. )
  176. /**++
  177. Function Description:
  178. This function reads all or part of information from a SCP/SAP/SMP profile
  179. depending on the ProfileType, into the InfoBuffer. ProfileType is saved in
  180. the ppInfoBuffer's Type field.
  181. A handle to the profile (Jet database) is passed into the routine every
  182. time this routine is called. Area specifies one or more pre-defined security
  183. areas to get information. One area's information may be saved in multiple
  184. sections in the profile.
  185. The memory related to the area(s) will be reset/freed before loading
  186. information from the profile. If the return code is SCESTATUS_SUCCESS, then
  187. the output InfoBuffer contains the requested information. Otherwise,
  188. InfoBuffer contains nothing for the area(s) specified.
  189. Arguments:
  190. hProfile - The handle to the profile to read from.
  191. ProfileType - value to indicate engine type.
  192. SCE_ENGINE_SCP
  193. SCE_ENGINE_SAP
  194. SCE_ENGINE_SMP
  195. Area - area(s) for which to get information from
  196. AREA_SECURITY_POLICY
  197. AREA_PRIVILEGES
  198. AREA_GROUP_MEMBERSHIP
  199. AREA_REGISTRY_SECURITY
  200. AREA_SYSTEM_SERVICE
  201. AREA_FILE_SECURITY
  202. ppInfoBuffer - The address of SCP/SAP/SMP buffers. If it is NULL, a buffer
  203. will be created which must be freed by LocalFree. The
  204. output is the information requested if successful, or
  205. nothing if fail.
  206. Errlog - A buffer to hold all error codes/text encountered when
  207. parsing the INF file. If Errlog is NULL, no further error
  208. information is returned except the return DWORD
  209. Return Value:
  210. SCESTATUS_SUCCESS
  211. SCESTATUS_PROFILE_NOT_FOUND
  212. SCESTATUS_NOT_ENOUGH_RESOURCE
  213. SCESTATUS_INVALID_PARAMETER
  214. SCESTATUS_BAD_FORMAT
  215. SCESTATUS_INVALID_DATA
  216. -- **/
  217. {
  218. SCESTATUS rc=SCESTATUS_SUCCESS;
  219. DWORD Len;
  220. BOOL bBufAlloc=FALSE;
  221. NT_PRODUCT_TYPE theType;
  222. //
  223. // if the JET database is not opened then return
  224. //
  225. if ( hProfile == NULL ) {
  226. return( SCESTATUS_INVALID_PARAMETER );
  227. }
  228. //
  229. // address for InfoBuffer cannot be NULL
  230. //
  231. if ( ppInfoBuffer == NULL ) {
  232. return( SCESTATUS_INVALID_PARAMETER );
  233. }
  234. //
  235. // check scetype
  236. //
  237. if ( ProfileType > SCE_ENGINE_SMP ) {
  238. return(SCESTATUS_INVALID_PARAMETER);
  239. }
  240. //
  241. // check to see if there is a SMP or SCP table
  242. //
  243. if ( hProfile->JetSmpID == JET_tableidNil ||
  244. hProfile->JetScpID == JET_tableidNil ) {
  245. return(SCESTATUS_PROFILE_NOT_FOUND);
  246. }
  247. if ( ProfileType == SCE_ENGINE_GPO &&
  248. hProfile->JetScpID == hProfile->JetSmpID ) {
  249. //
  250. // there is no domain GPO policy
  251. //
  252. return(SCESTATUS_PROFILE_NOT_FOUND);
  253. }
  254. //
  255. // design on this part is changed.
  256. // if there is no SAP table which means the system has not been
  257. // analyzed based on the template in SMP, return error and UI
  258. // will display "no analysis is performed"
  259. //
  260. if ( ProfileType == SCE_ENGINE_SAP &&
  261. hProfile->JetSapID == JET_tableidNil) {
  262. return(SCESTATUS_PROFILE_NOT_FOUND);
  263. }
  264. //
  265. // create buffer if it is NULL
  266. //
  267. if ( *ppInfoBuffer == NULL) {
  268. //
  269. // allocate memory
  270. //
  271. Len = sizeof(SCE_PROFILE_INFO);
  272. *ppInfoBuffer = (PSCE_PROFILE_INFO)ScepAlloc( (UINT)0, Len);
  273. if ( *ppInfoBuffer == NULL ) {
  274. return( SCESTATUS_NOT_ENOUGH_RESOURCE );
  275. }
  276. memset(*ppInfoBuffer, '\0', Len);
  277. bBufAlloc = TRUE;
  278. (*ppInfoBuffer)->Type = ( ProfileType==SCE_ENGINE_GPO) ? SCE_ENGINE_SCP : ProfileType;
  279. }
  280. /*
  281. // Design changed. Checking is moved above creating the buffer.
  282. if ( ProfileType == SCE_ENGINE_SAP &&
  283. hProfile->JetSapID == JET_tableidNil) {
  284. //
  285. // if no SAP table is there, which means configuration is done
  286. // but analysis is not done, we treat it as everything is fine
  287. // reset the buffer to SCE_NO_VALUE
  288. //
  289. ScepResetSecurityPolicyArea(*ppInfoBuffer);
  290. // return(SCESTATUS_PROFILE_NOT_FOUND);
  291. return(SCESTATUS_SUCCESS);
  292. }
  293. */
  294. //
  295. // Free related memory and reset the buffer before parsing
  296. // there is a problem here for now. it clears the handle and
  297. // filename too. So comment it out.
  298. SceFreeMemory( (PVOID)(*ppInfoBuffer), (DWORD)Area );
  299. //
  300. // system access
  301. //
  302. if ( Area & AREA_SECURITY_POLICY ) {
  303. rc = ScepGetSystemAccess(
  304. hProfile,
  305. ProfileType,
  306. *ppInfoBuffer,
  307. Errlog
  308. );
  309. if( rc != SCESTATUS_SUCCESS )
  310. goto Done;
  311. //
  312. // system auditing
  313. //
  314. rc = ScepGetAuditing(hProfile,
  315. ProfileType,
  316. *ppInfoBuffer,
  317. Errlog
  318. );
  319. if( rc != SCESTATUS_SUCCESS )
  320. goto Done;
  321. #if _WIN32_WINNT>=0x0500
  322. if ( RtlGetNtProductType(&theType) ) {
  323. if ( theType == NtProductLanManNt ) {
  324. rc = ScepGetKerberosPolicy(
  325. hProfile,
  326. ProfileType,
  327. &((*ppInfoBuffer)->pKerberosInfo),
  328. Errlog
  329. );
  330. if ( rc != SCESTATUS_SUCCESS )
  331. goto Done;
  332. }
  333. }
  334. #endif
  335. //
  336. // registry values
  337. //
  338. rc = ScepGetRegistryValues(
  339. hProfile,
  340. ProfileType,
  341. &((*ppInfoBuffer)->aRegValues),
  342. &((*ppInfoBuffer)->RegValueCount),
  343. Errlog
  344. );
  345. if ( rc != SCESTATUS_SUCCESS )
  346. goto Done;
  347. }
  348. //
  349. // privilege/rights
  350. //
  351. if ( Area & AREA_PRIVILEGES ) {
  352. //
  353. // SCP/SMP/SAP privilegeAssignedTo are all in the same address in the
  354. // SCE_PROFILE_INFO structure.
  355. //
  356. rc = ScepGetPrivileges(
  357. hProfile,
  358. ProfileType,
  359. dwAccountFormat,
  360. (PVOID *)&( (*ppInfoBuffer)->OtherInfo.scp.u.pPrivilegeAssignedTo ),
  361. Errlog
  362. );
  363. if( rc != SCESTATUS_SUCCESS )
  364. goto Done;
  365. }
  366. //
  367. // group memberships
  368. //
  369. if ( (Area & AREA_GROUP_MEMBERSHIP) &&
  370. (ProfileType != SCE_ENGINE_GPO) ) {
  371. rc = ScepGetGroupMembership(
  372. hProfile,
  373. ProfileType,
  374. &((*ppInfoBuffer)->pGroupMembership),
  375. Errlog
  376. );
  377. if( rc != SCESTATUS_SUCCESS )
  378. goto Done;
  379. }
  380. //
  381. // registry keys security
  382. //
  383. if ( (Area & AREA_REGISTRY_SECURITY) &&
  384. (ProfileType != SCE_ENGINE_GPO) ) {
  385. rc = ScepGetObjectList(
  386. hProfile,
  387. ProfileType,
  388. szRegistryKeys,
  389. &((*ppInfoBuffer)->pRegistryKeys.pOneLevel),
  390. Errlog
  391. );
  392. if ( rc != SCESTATUS_SUCCESS )
  393. goto Done;
  394. }
  395. //
  396. // file security
  397. //
  398. if ( (Area & AREA_FILE_SECURITY) &&
  399. (ProfileType != SCE_ENGINE_GPO) ) {
  400. rc = ScepGetObjectList(
  401. hProfile,
  402. ProfileType,
  403. szFileSecurity,
  404. &((*ppInfoBuffer)->pFiles.pOneLevel),
  405. Errlog
  406. );
  407. if ( rc != SCESTATUS_SUCCESS )
  408. goto Done;
  409. }
  410. //
  411. // DS object security
  412. //
  413. #if 0
  414. #if _WIN32_WINNT>=0x0500
  415. if ( (Area & AREA_DS_OBJECTS) &&
  416. (ProfileType != SCE_ENGINE_GPO) &&
  417. RtlGetNtProductType(&theType) ) {
  418. if ( theType == NtProductLanManNt ) {
  419. rc = ScepGetDsRoot(
  420. hProfile,
  421. ProfileType,
  422. szDSSecurity,
  423. &((*ppInfoBuffer)->pDsObjects.pOneLevel),
  424. Errlog
  425. );
  426. if ( rc != SCESTATUS_SUCCESS )
  427. goto Done;
  428. }
  429. }
  430. #endif
  431. #endif
  432. if ( (Area & AREA_SYSTEM_SERVICE) &&
  433. (ProfileType != SCE_ENGINE_GPO) ) {
  434. rc = ScepGetSystemServices(
  435. hProfile,
  436. ProfileType,
  437. &((*ppInfoBuffer)->pServices),
  438. Errlog
  439. );
  440. if ( rc != SCESTATUS_SUCCESS )
  441. goto Done;
  442. }
  443. Done:
  444. if ( rc != SCESTATUS_SUCCESS ) {
  445. //
  446. // need free memory because some fatal error happened
  447. //
  448. if ( bBufAlloc ) {
  449. SceFreeProfileMemory(*ppInfoBuffer);
  450. *ppInfoBuffer = NULL;
  451. } else
  452. SceFreeMemory( (PVOID)(*ppInfoBuffer), (DWORD)Area );
  453. }
  454. return(rc);
  455. }
  456. SCESTATUS
  457. ScepGetSystemAccess(
  458. IN PSCECONTEXT hProfile,
  459. IN SCETYPE ProfileType,
  460. OUT PSCE_PROFILE_INFO pProfileInfo,
  461. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  462. )
  463. /*++
  464. Routine Description:
  465. This routine retrieves system access area information from the Jet database
  466. and stores in the output buffer pProfileInfo. System access information
  467. includes information in [System Access] sections.
  468. Arguments:
  469. hProfile - The profile handle context
  470. pProfileinfo - the output buffer to hold profile info (SCP or SAP).
  471. Errlog - A buffer to hold all error codes/text encountered when
  472. parsing the INF file. If Errlog is NULL, no further error
  473. information is returned except the return DWORD
  474. Return value:
  475. SCESTATUS - SCESTATUS_SUCCESS
  476. SCESTATUS_NOT_ENOUGH_RESOURCE
  477. SCESTATUS_INVALID_PARAMETER
  478. SCESTATUS_BAD_FORMAT
  479. SCESTATUS_INVALID_DATA
  480. --*/
  481. {
  482. SCESTATUS rc;
  483. PSCESECTION hSection=NULL;
  484. SCE_KEY_LOOKUP AccessKeys[] = {
  485. {(PWSTR)TEXT("MinimumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordAge), 'D'},
  486. {(PWSTR)TEXT("MaximumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MaximumPasswordAge), 'D'},
  487. {(PWSTR)TEXT("MinimumPasswordLength"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordLength), 'D'},
  488. {(PWSTR)TEXT("PasswordComplexity"), offsetof(struct _SCE_PROFILE_INFO, PasswordComplexity), 'D'},
  489. {(PWSTR)TEXT("PasswordHistorySize"), offsetof(struct _SCE_PROFILE_INFO, PasswordHistorySize), 'D'},
  490. {(PWSTR)TEXT("LockoutBadCount"), offsetof(struct _SCE_PROFILE_INFO, LockoutBadCount), 'D'},
  491. {(PWSTR)TEXT("ResetLockoutCount"), offsetof(struct _SCE_PROFILE_INFO, ResetLockoutCount), 'D'},
  492. {(PWSTR)TEXT("LockoutDuration"), offsetof(struct _SCE_PROFILE_INFO, LockoutDuration), 'D'},
  493. {(PWSTR)TEXT("RequireLogonToChangePassword"),offsetof(struct _SCE_PROFILE_INFO, RequireLogonToChangePassword),'D'},
  494. {(PWSTR)TEXT("ForceLogoffWhenHourExpire"),offsetof(struct _SCE_PROFILE_INFO, ForceLogoffWhenHourExpire),'D'},
  495. {(PWSTR)TEXT("ClearTextPassword"), offsetof(struct _SCE_PROFILE_INFO, ClearTextPassword), 'D'},
  496. {(PWSTR)TEXT("LSAAnonymousNameLookup"), offsetof(struct _SCE_PROFILE_INFO, LSAAnonymousNameLookup), 'D'},
  497. {(PWSTR)TEXT("EnableAdminAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableAdminAccount), 'D'},
  498. {(PWSTR)TEXT("EnableGuestAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableGuestAccount), 'D'}
  499. };
  500. DWORD cKeys = sizeof(AccessKeys) / sizeof(SCE_KEY_LOOKUP);
  501. DWORD DataSize=0;
  502. PWSTR Strvalue=NULL;
  503. DWORD SDsize=0;
  504. PSECURITY_DESCRIPTOR pTempSD=NULL;
  505. if ( pProfileInfo == NULL ) {
  506. return(SCESTATUS_INVALID_PARAMETER);
  507. }
  508. rc = ScepGetFixValueSection(
  509. hProfile,
  510. szSystemAccess,
  511. AccessKeys,
  512. cKeys,
  513. ProfileType,
  514. (PVOID)pProfileInfo,
  515. &hSection,
  516. Errlog
  517. );
  518. if ( rc != SCESTATUS_SUCCESS )
  519. return(rc);
  520. //
  521. // get new administrator for SCP and SMP types
  522. //
  523. rc = ScepGetVariableValue(
  524. hSection,
  525. ProfileType,
  526. L"NewAdministratorName",
  527. &Strvalue,
  528. &DataSize
  529. );
  530. if ( rc != SCESTATUS_RECORD_NOT_FOUND &&
  531. rc != SCESTATUS_SUCCESS ) {
  532. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  533. Errlog, SCEERR_QUERY_VALUE,
  534. L"NewAdministratorName"
  535. );
  536. goto Done;
  537. }
  538. rc = SCESTATUS_SUCCESS;
  539. if ( Strvalue ) {
  540. if ( Strvalue[0] != L'\0') {
  541. pProfileInfo->NewAdministratorName = Strvalue;
  542. } else {
  543. pProfileInfo->NewAdministratorName = NULL;
  544. ScepFree(Strvalue);
  545. }
  546. Strvalue = NULL;
  547. }
  548. //
  549. // NewGuestName
  550. //
  551. rc = ScepGetVariableValue(
  552. hSection,
  553. ProfileType,
  554. L"NewGuestName",
  555. &Strvalue,
  556. &DataSize
  557. );
  558. if ( rc != SCESTATUS_RECORD_NOT_FOUND &&
  559. rc != SCESTATUS_SUCCESS ) {
  560. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  561. Errlog, SCEERR_QUERY_VALUE,
  562. L"NewGuestName"
  563. );
  564. goto Done;
  565. }
  566. rc = SCESTATUS_SUCCESS;
  567. if ( Strvalue ) {
  568. if ( Strvalue[0] != L'\0') {
  569. pProfileInfo->NewGuestName = Strvalue;
  570. } else {
  571. pProfileInfo->NewGuestName = NULL;
  572. ScepFree(Strvalue);
  573. }
  574. Strvalue = NULL;
  575. }
  576. Done:
  577. SceJetCloseSection(&hSection, TRUE);
  578. if ( pTempSD != NULL )
  579. ScepFree(pTempSD);
  580. if ( Strvalue != NULL )
  581. ScepFree( Strvalue );
  582. return(rc);
  583. }
  584. SCESTATUS
  585. ScepGetFixValueSection(
  586. IN PSCECONTEXT hProfile,
  587. IN PCWSTR SectionName,
  588. IN SCE_KEY_LOOKUP *Keys,
  589. IN DWORD cKeys,
  590. IN SCETYPE ProfileType,
  591. OUT PVOID pInfo,
  592. OUT PSCESECTION *phSection,
  593. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  594. )
  595. /* ++
  596. -- */
  597. {
  598. SCESTATUS rc;
  599. DWORD i;
  600. TCHAR Value[25];
  601. DWORD RetValueLen;
  602. LONG Keyvalue;
  603. rc = ScepOpenSectionForName(
  604. hProfile,
  605. (ProfileType==SCE_ENGINE_GPO)? SCE_ENGINE_SCP : ProfileType,
  606. SectionName,
  607. phSection
  608. );
  609. if ( SCESTATUS_SUCCESS != rc ) {
  610. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  611. Errlog, SCEERR_OPEN,
  612. SectionName
  613. );
  614. return(rc);
  615. }
  616. JET_COLUMNID ColGpoID = 0;
  617. JET_ERR JetErr;
  618. LONG GpoID=0;
  619. DWORD Actual;
  620. if ( ProfileType == SCE_ENGINE_GPO ) {
  621. JET_COLUMNDEF ColumnGpoIDDef;
  622. JetErr = JetGetTableColumnInfo(
  623. (*phSection)->JetSessionID,
  624. (*phSection)->JetTableID,
  625. "GpoID",
  626. (VOID *)&ColumnGpoIDDef,
  627. sizeof(JET_COLUMNDEF),
  628. JET_ColInfo
  629. );
  630. if ( JET_errSuccess == JetErr ) {
  631. ColGpoID = ColumnGpoIDDef.columnid;
  632. }
  633. }
  634. //
  635. // get each key in the access array
  636. //
  637. for ( i=0; i<cKeys; i++ ) {
  638. memset(Value, '\0', 50);
  639. RetValueLen = 0;
  640. rc = SceJetGetValue(
  641. *phSection,
  642. SCEJET_EXACT_MATCH_NO_CASE,
  643. (PWSTR)(Keys[i].KeyString),
  644. NULL,
  645. 0,
  646. NULL,
  647. Value,
  648. 48,
  649. &RetValueLen
  650. );
  651. if ( RetValueLen > 0 )
  652. Value[RetValueLen/2] = L'\0';
  653. if ( rc == SCESTATUS_SUCCESS ) {
  654. GpoID = 1;
  655. if ( ProfileType == SCE_ENGINE_GPO ) {
  656. //
  657. // query if the setting comes from a GPO
  658. // get GPO ID field from the current line
  659. //
  660. GpoID = 0;
  661. if ( ColGpoID > 0 ) {
  662. JetErr = JetRetrieveColumn(
  663. (*phSection)->JetSessionID,
  664. (*phSection)->JetTableID,
  665. ColGpoID,
  666. (void *)&GpoID,
  667. 4,
  668. &Actual,
  669. 0,
  670. NULL
  671. );
  672. }
  673. }
  674. if ( GpoID > 0 && RetValueLen > 0 && Value[0] != L'\0' )
  675. Keyvalue = _wtol(Value);
  676. else
  677. Keyvalue = SCE_NO_VALUE;
  678. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  679. rc = SCESTATUS_SUCCESS; // it is OK not find a record
  680. Keyvalue = SCE_NO_VALUE;
  681. } else {
  682. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  683. Errlog,
  684. SCEERR_QUERY_VALUE,
  685. Keys[i].KeyString
  686. );
  687. goto Done;
  688. }
  689. #ifdef SCE_DBG
  690. printf("Get info %s (%d) for ", Value, Keyvalue);
  691. wprintf(L"%s. rc=%d, Return Length=%d\n",
  692. Keys[i].KeyString, rc, RetValueLen);
  693. #endif
  694. switch (Keys[i].BufferType ) {
  695. case 'B':
  696. *((BOOL *)((CHAR *)pInfo+Keys[i].Offset)) = (Keyvalue == 1) ? TRUE : FALSE;
  697. break;
  698. case 'D':
  699. *((DWORD *)((CHAR *)pInfo+Keys[i].Offset)) = Keyvalue;
  700. break;
  701. default:
  702. rc = SCESTATUS_INVALID_DATA;
  703. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  704. Errlog,
  705. SCEERR_CANT_FIND_DATATYPE,
  706. Keys[i].KeyString
  707. );
  708. goto Done;
  709. }
  710. }
  711. Done:
  712. //
  713. // close the section
  714. //
  715. if ( rc != SCESTATUS_SUCCESS ) {
  716. SceJetCloseSection(phSection, TRUE);
  717. }
  718. return(rc);
  719. }
  720. SCESTATUS
  721. ScepGetVariableValue(
  722. IN PSCESECTION hSection,
  723. IN SCETYPE ProfileType,
  724. IN PCWSTR KeyName,
  725. OUT PWSTR *Value,
  726. OUT PDWORD ValueLen
  727. )
  728. /* ++
  729. -- */
  730. {
  731. SCESTATUS rc;
  732. rc = SceJetGetValue(
  733. hSection,
  734. SCEJET_EXACT_MATCH_NO_CASE,
  735. (PWSTR)KeyName,
  736. NULL,
  737. 0,
  738. NULL,
  739. NULL,
  740. 0,
  741. ValueLen
  742. );
  743. if ( rc == SCESTATUS_SUCCESS && *ValueLen > 0 ) {
  744. LONG GpoID=1;
  745. if ( ProfileType == SCE_ENGINE_GPO ) {
  746. JET_COLUMNDEF ColumnGpoIDDef;
  747. JET_COLUMNID ColGpoID = 0;
  748. JET_ERR JetErr;
  749. DWORD Actual;
  750. JetErr = JetGetTableColumnInfo(
  751. hSection->JetSessionID,
  752. hSection->JetTableID,
  753. "GpoID",
  754. (VOID *)&ColumnGpoIDDef,
  755. sizeof(JET_COLUMNDEF),
  756. JET_ColInfo
  757. );
  758. GpoID = 0;
  759. if ( JET_errSuccess == JetErr ) {
  760. ColGpoID = ColumnGpoIDDef.columnid;
  761. //
  762. // query if the setting comes from a GPO
  763. // get GPO ID field from the current line
  764. //
  765. JetErr = JetRetrieveColumn(
  766. hSection->JetSessionID,
  767. hSection->JetTableID,
  768. ColGpoID,
  769. (void *)&GpoID,
  770. 4,
  771. &Actual,
  772. 0,
  773. NULL
  774. );
  775. }
  776. }
  777. if ( GpoID > 0 ) {
  778. //
  779. // if DataSize = 0 then the security descriptor is NULL also
  780. //
  781. *Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, *ValueLen+2);
  782. if( *Value == NULL ) {
  783. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  784. } else {
  785. rc = SceJetGetValue(
  786. hSection,
  787. SCEJET_CURRENT,
  788. (PWSTR)KeyName,
  789. NULL,
  790. 0,
  791. NULL,
  792. *Value,
  793. *ValueLen,
  794. ValueLen
  795. );
  796. }
  797. } else {
  798. rc = SCESTATUS_RECORD_NOT_FOUND;
  799. }
  800. }
  801. return(rc);
  802. }
  803. SCESTATUS
  804. ScepGetPrivileges(
  805. IN PSCECONTEXT hProfile,
  806. IN SCETYPE ProfileType,
  807. IN DWORD dwAccountFormat,
  808. OUT PVOID *pPrivileges,
  809. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  810. )
  811. {
  812. SCESTATUS rc;
  813. LSA_HANDLE LsaHandle=NULL;
  814. rc = RtlNtStatusToDosError(
  815. ScepOpenLsaPolicy(
  816. MAXIMUM_ALLOWED,
  817. &LsaHandle,
  818. TRUE
  819. ));
  820. if ( ERROR_SUCCESS != rc ) {
  821. ScepBuildErrorLogInfo(
  822. rc,
  823. Errlog,
  824. SCEDLL_LSA_POLICY
  825. );
  826. return(ScepDosErrorToSceStatus(rc));
  827. }
  828. PSCE_PRIVILEGE_ASSIGNMENT pTempList=NULL, pNode, pPriv, pParent, pTemp;
  829. rc = ScepGetPrivilegesFromOneTable(
  830. LsaHandle,
  831. hProfile,
  832. ProfileType,
  833. dwAccountFormat,
  834. pPrivileges,
  835. Errlog
  836. );
  837. if ( SCESTATUS_SUCCESS == rc && SCE_ENGINE_SAP == ProfileType ) {
  838. //
  839. // get the remaining stuff from SMP
  840. //
  841. rc = ScepGetPrivilegesFromOneTable(
  842. LsaHandle,
  843. hProfile,
  844. SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
  845. dwAccountFormat,
  846. (PVOID *)&pTempList,
  847. Errlog
  848. );
  849. if ( rc == SCESTATUS_SUCCESS ) {
  850. //
  851. // add non-exist nodes to pPrivileges
  852. //
  853. pNode=pTempList;
  854. pParent=NULL;
  855. while ( pNode ) {
  856. //
  857. // if this node does not exist in the SAP
  858. // this node is analyzed with "match" status
  859. // if it already exists in SAP, it is a "mismatched" item
  860. // duplication is prevented by the last argument TRUE
  861. //
  862. for ( pPriv=(PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
  863. pPriv != NULL; pPriv=pPriv->Next ) {
  864. if ( pPriv->Status & SCE_INTERNAL_NP &&
  865. _wcsicmp( pPriv->Name, pNode->Name) == 0 )
  866. break;
  867. }
  868. if ( pPriv ) {
  869. //
  870. // find the entry in SAP, mismatched item
  871. //
  872. if ( pPriv->Status & SCE_STATUS_ERROR_NOT_AVAILABLE ) {
  873. pPriv->Status = SCE_STATUS_ERROR_NOT_AVAILABLE;
  874. } else {
  875. pPriv->Status = SCE_STATUS_MISMATCH;
  876. }
  877. pParent = pNode;
  878. pNode = pNode->Next;
  879. } else {
  880. //
  881. // does not exist in SAP.
  882. // just move this node to SAP, with status SCE_STATUS_GOOD
  883. //
  884. if ( pParent )
  885. pParent->Next = pNode->Next;
  886. else
  887. pTempList = pNode->Next;
  888. pTemp = pNode;
  889. pNode=pNode->Next;
  890. pTemp->Next = (PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
  891. *((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges) = pTemp;
  892. }
  893. }
  894. //
  895. // priv exist in analysis but not in template
  896. //
  897. for ( pPriv=(PSCE_PRIVILEGE_ASSIGNMENT)(*pPrivileges);
  898. pPriv != NULL; pPriv=pPriv->Next ) {
  899. if ( pPriv->Status & SCE_INTERNAL_NP )
  900. pPriv->Status = SCE_STATUS_NOT_CONFIGURED;
  901. }
  902. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  903. rc = SCESTATUS_SUCCESS;
  904. } else {
  905. //
  906. // pPrivileges will be freed outside
  907. //
  908. }
  909. if ( pTempList )
  910. ScepFreePrivilege(pTempList);
  911. }
  912. if ( LsaHandle ) {
  913. LsaClose(LsaHandle);
  914. }
  915. return(rc);
  916. }
  917. SCESTATUS
  918. ScepGetPrivilegesFromOneTable(
  919. IN LSA_HANDLE LsaPolicy,
  920. IN PSCECONTEXT hProfile,
  921. IN SCETYPE ProfileType,
  922. IN DWORD dwAccountFormat,
  923. OUT PVOID *pPrivileges,
  924. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  925. )
  926. /* ++
  927. Routine Description:
  928. Arguments:
  929. Return Value:
  930. -- */
  931. {
  932. SCESTATUS rc;
  933. PSCESECTION hSection=NULL;
  934. WCHAR KeyName[36];
  935. PWSTR Value=NULL;
  936. PSCE_PRIVILEGE_ASSIGNMENT pPrivilegeAssigned=NULL;
  937. PSCE_PRIVILEGE_VALUE_LIST pPrivilegeList=NULL;
  938. DWORD KeyLen=0;
  939. DWORD ValueLen;
  940. DWORD Len;
  941. PWSTR pTemp;
  942. DWORD PrivValue;
  943. if ( pPrivileges == NULL )
  944. return(SCESTATUS_INVALID_PARAMETER);
  945. rc = ScepOpenSectionForName(
  946. hProfile,
  947. (ProfileType==SCE_ENGINE_GPO)? SCE_ENGINE_SCP : ProfileType,
  948. szPrivilegeRights,
  949. &hSection
  950. );
  951. if ( rc != SCESTATUS_SUCCESS ) {
  952. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  953. Errlog, SCEERR_OPEN,
  954. szPrivilegeRights
  955. );
  956. return(rc);
  957. }
  958. JET_COLUMNID ColGpoID = 0;
  959. JET_ERR JetErr;
  960. LONG GpoID;
  961. if ( ProfileType == SCE_ENGINE_GPO ) {
  962. JET_COLUMNDEF ColumnGpoIDDef;
  963. JetErr = JetGetTableColumnInfo(
  964. hSection->JetSessionID,
  965. hSection->JetTableID,
  966. "GpoID",
  967. (VOID *)&ColumnGpoIDDef,
  968. sizeof(JET_COLUMNDEF),
  969. JET_ColInfo
  970. );
  971. if ( JET_errSuccess == JetErr ) {
  972. ColGpoID = ColumnGpoIDDef.columnid;
  973. }
  974. }
  975. //
  976. // goto the first line of this section
  977. //
  978. // memset(KeyName, '\0', 72); KeyName will be manually terminated later
  979. rc = SceJetGetValue(
  980. hSection,
  981. SCEJET_PREFIX_MATCH,
  982. NULL,
  983. KeyName,
  984. 70,
  985. &KeyLen,
  986. NULL,
  987. 0,
  988. &ValueLen
  989. );
  990. while ( rc == SCESTATUS_SUCCESS ||
  991. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  992. //
  993. // terminate the string
  994. //
  995. KeyName[KeyLen/2] = L'\0';
  996. //
  997. // lookup privilege's value
  998. // ignore unknown privileges
  999. //
  1000. if ( ( PrivValue = ScepLookupPrivByName(KeyName) ) == -1 ) {
  1001. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  1002. Errlog,
  1003. SCEERR_INVALID_PRIVILEGE,
  1004. KeyName
  1005. );
  1006. rc = SceJetGetValue(
  1007. hSection,
  1008. SCEJET_NEXT_LINE,
  1009. NULL,
  1010. KeyName,
  1011. 70,
  1012. &KeyLen,
  1013. NULL,
  1014. 0,
  1015. &ValueLen
  1016. );
  1017. continue;
  1018. // rc = SCESTATUS_INVALID_DATA;
  1019. // goto Done;
  1020. }
  1021. GpoID = 1;
  1022. if ( ProfileType == SCE_ENGINE_GPO ) {
  1023. GpoID = 0;
  1024. if ( ColGpoID > 0 ) {
  1025. DWORD Actual;
  1026. JetErr = JetRetrieveColumn(
  1027. hSection->JetSessionID,
  1028. hSection->JetTableID,
  1029. ColGpoID,
  1030. (void *)&GpoID,
  1031. 4,
  1032. &Actual,
  1033. 0,
  1034. NULL
  1035. );
  1036. }
  1037. }
  1038. if ( ProfileType == SCE_ENGINE_GPO &&
  1039. GpoID <= 0 ) {
  1040. //
  1041. // not domain GPO settings
  1042. //
  1043. rc = SceJetGetValue(
  1044. hSection,
  1045. SCEJET_NEXT_LINE,
  1046. NULL,
  1047. KeyName,
  1048. 70,
  1049. &KeyLen,
  1050. NULL,
  1051. 0,
  1052. &ValueLen
  1053. );
  1054. continue;
  1055. }
  1056. //
  1057. // allocate memory for the group name and value string
  1058. //
  1059. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  1060. if ( Value == NULL ) {
  1061. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1062. goto Done;
  1063. }
  1064. //
  1065. // Get the group and its value
  1066. //
  1067. rc = SceJetGetValue(
  1068. hSection,
  1069. SCEJET_CURRENT,
  1070. NULL,
  1071. NULL,
  1072. 0,
  1073. NULL,
  1074. Value,
  1075. ValueLen,
  1076. &ValueLen
  1077. );
  1078. if ( rc != SCESTATUS_SUCCESS )
  1079. goto Done;
  1080. //
  1081. // create a node for this privilege
  1082. //
  1083. if ( ProfileType == SCE_ENGINE_SAP ||
  1084. ProfileType == SCE_ENGINE_SMP ||
  1085. ProfileType == SCE_ENGINE_GPO ||
  1086. ProfileType == SCE_ENGINE_SCP ) {
  1087. //
  1088. // a sce_privilege_assignment structure. allocate buffer
  1089. //
  1090. pPrivilegeAssigned = (PSCE_PRIVILEGE_ASSIGNMENT)ScepAlloc( LMEM_ZEROINIT,
  1091. sizeof(SCE_PRIVILEGE_ASSIGNMENT) );
  1092. if ( pPrivilegeAssigned == NULL ) {
  1093. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1094. goto Done;
  1095. }
  1096. pPrivilegeAssigned->Name = (PWSTR)ScepAlloc( (UINT)0, (wcslen(KeyName)+1)*sizeof(WCHAR));
  1097. if ( pPrivilegeAssigned->Name == NULL ) {
  1098. ScepFree(pPrivilegeAssigned);
  1099. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1100. goto Done;
  1101. }
  1102. wcscpy(pPrivilegeAssigned->Name, KeyName);
  1103. pPrivilegeAssigned->Value = PrivValue;
  1104. if ( SCE_ENGINE_SAP == ProfileType )
  1105. pPrivilegeAssigned->Status = SCE_INTERNAL_NP;
  1106. else
  1107. pPrivilegeAssigned->Status = SCE_STATUS_GOOD;
  1108. }
  1109. //
  1110. // add the multi-sz value string to the node, depending on the value type
  1111. //
  1112. PSID pSid=NULL;
  1113. BOOL bBufferUsed;
  1114. pTemp = Value;
  1115. if (pTemp != NULL && pTemp[0] == L'\0' && ValueLen > 1) {
  1116. pTemp ++;
  1117. }
  1118. while ( rc == SCESTATUS_SUCCESS && pTemp != NULL && pTemp[0]) {
  1119. Len = wcslen(pTemp);
  1120. if ( (ProfileType == SCE_ENGINE_SAP) &&
  1121. (_wcsicmp( SCE_ERROR_STRING, pTemp) == 0) ) {
  1122. //
  1123. // this is an errored item
  1124. //
  1125. pPrivilegeAssigned->Status |= SCE_STATUS_ERROR_NOT_AVAILABLE;
  1126. break;
  1127. }
  1128. //
  1129. // convert pTemp (may be a name, or *SID format) to the right
  1130. // format (SID_STRING, Name, or ACCOUNT_SID)
  1131. //
  1132. switch ( dwAccountFormat ) {
  1133. case SCE_ACCOUNT_SID:
  1134. if ( pTemp[0] == L'*' ) {
  1135. //
  1136. // this is the *SID format, convert to SID
  1137. //
  1138. if ( !ConvertStringSidToSid( pTemp+1, &pSid) ) {
  1139. //
  1140. // if failed to convert from sid string to sid,
  1141. // treat it as any name
  1142. //
  1143. rc = GetLastError();
  1144. }
  1145. } else {
  1146. //
  1147. // lookup name for a sid
  1148. //
  1149. rc = RtlNtStatusToDosError(
  1150. ScepConvertNameToSid(
  1151. LsaPolicy,
  1152. pTemp,
  1153. &pSid
  1154. ));
  1155. }
  1156. if ( ERROR_SUCCESS == rc && pSid ) {
  1157. if ( ProfileType == SCE_ENGINE_SAP ||
  1158. ProfileType == SCE_ENGINE_SMP ||
  1159. ProfileType == SCE_ENGINE_GPO ||
  1160. ProfileType == SCE_ENGINE_SCP ) {
  1161. rc = ScepAddSidToNameList(
  1162. &(pPrivilegeAssigned->AssignedTo),
  1163. pSid,
  1164. TRUE, // reuse the buffer
  1165. &bBufferUsed
  1166. );
  1167. } else {
  1168. //
  1169. // add to privilege list (as Sid)
  1170. //
  1171. rc = ScepAddSidToPrivilegeList(
  1172. &pPrivilegeList,
  1173. pSid,
  1174. TRUE, // reuse the buffer
  1175. PrivValue,
  1176. &bBufferUsed
  1177. );
  1178. }
  1179. if ( rc == ERROR_SUCCESS && bBufferUsed ) {
  1180. pSid = NULL;
  1181. }
  1182. rc = ScepDosErrorToSceStatus(rc);
  1183. } else {
  1184. //
  1185. // add as name format
  1186. //
  1187. if ( ProfileType == SCE_ENGINE_SAP ||
  1188. ProfileType == SCE_ENGINE_SMP ||
  1189. ProfileType == SCE_ENGINE_GPO ||
  1190. ProfileType == SCE_ENGINE_SCP ) {
  1191. rc = ScepAddToNameList(&(pPrivilegeAssigned->AssignedTo), pTemp, Len );
  1192. rc = ScepDosErrorToSceStatus(rc);
  1193. } else {
  1194. //
  1195. // pPrivilegeList is a privilege_value list for each user/group.
  1196. // the LowValue and HighValue fields are combination of all privileges assigned to the user
  1197. //
  1198. rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
  1199. }
  1200. }
  1201. if ( pSid ) {
  1202. LocalFree(pSid);
  1203. pSid = NULL;
  1204. }
  1205. break;
  1206. default:
  1207. if ( (dwAccountFormat != SCE_ACCOUNT_SID_STRING) &&
  1208. (pTemp[0] == L'*') ) {
  1209. //
  1210. // this is a *SID format, must be converted into Domain\Account format
  1211. //
  1212. if ( ProfileType == SCE_ENGINE_SAP ||
  1213. ProfileType == SCE_ENGINE_SMP ||
  1214. ProfileType == SCE_ENGINE_GPO ||
  1215. ProfileType == SCE_ENGINE_SCP ) {
  1216. rc = ScepLookupSidStringAndAddToNameList(
  1217. LsaPolicy,
  1218. &(pPrivilegeAssigned->AssignedTo),
  1219. pTemp, // +1,
  1220. Len // -1
  1221. );
  1222. } else {
  1223. //
  1224. // add to privilege value list
  1225. //
  1226. PWSTR strName=NULL;
  1227. DWORD strLen=0;
  1228. if ( ConvertStringSidToSid( pTemp+1, &pSid) ) {
  1229. rc = RtlNtStatusToDosError(
  1230. ScepConvertSidToName(
  1231. LsaPolicy,
  1232. pSid,
  1233. TRUE, // want domain\account format
  1234. &strName,
  1235. &strLen
  1236. ));
  1237. LocalFree(pSid);
  1238. pSid = NULL;
  1239. } else {
  1240. rc = GetLastError();
  1241. }
  1242. if ( rc == ERROR_SUCCESS ) {
  1243. //
  1244. // add the name to the privilege list
  1245. //
  1246. rc = ScepAddToPrivilegeList(&pPrivilegeList, strName, strLen, PrivValue);
  1247. } else {
  1248. //
  1249. // if couldn't lookup for the name, add *SID to the list
  1250. //
  1251. rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
  1252. }
  1253. if ( strName ) {
  1254. ScepFree(strName);
  1255. strName = NULL;
  1256. }
  1257. }
  1258. } else {
  1259. if ( ProfileType == SCE_ENGINE_SAP ||
  1260. ProfileType == SCE_ENGINE_SMP ||
  1261. ProfileType == SCE_ENGINE_GPO ||
  1262. ProfileType == SCE_ENGINE_SCP ) {
  1263. rc = ScepDosErrorToSceStatus(
  1264. ScepAddToNameList(&(pPrivilegeAssigned->AssignedTo),
  1265. pTemp,
  1266. Len ));
  1267. } else {
  1268. //
  1269. // pPrivilegeList is a privilege_value list for each user/group.
  1270. // the LowValue and HighValue fields are combination of all privileges assigned to the user
  1271. //
  1272. rc = ScepAddToPrivilegeList(&pPrivilegeList, pTemp, Len, PrivValue);
  1273. #ifdef SCE_DBG
  1274. wprintf(L"\tAdd Priv %d for %s (%d bytes)\n", PrivValue, pTemp, Len);
  1275. #endif
  1276. }
  1277. }
  1278. break;
  1279. }
  1280. pTemp += Len +1;
  1281. if ( rc != SCESTATUS_SUCCESS ) {
  1282. ScepBuildErrorLogInfo( ERROR_WRITE_FAULT,
  1283. Errlog,
  1284. SCEERR_ADD,
  1285. KeyName
  1286. );
  1287. }
  1288. }
  1289. //
  1290. // Free memory
  1291. //
  1292. if ( rc != SCESTATUS_SUCCESS ) {
  1293. if ( pPrivilegeAssigned != NULL )
  1294. ScepFreePrivilege(pPrivilegeAssigned);
  1295. if ( pPrivilegeList != NULL )
  1296. ScepFreePrivilegeValueList(pPrivilegeList);
  1297. goto Done;
  1298. }
  1299. //
  1300. // link this to the PSCE_PRIVILEGE_ASSIGNMENT list in pPrivileges
  1301. //
  1302. if ( ProfileType == SCE_ENGINE_SAP ||
  1303. ProfileType == SCE_ENGINE_SMP ||
  1304. ProfileType == SCE_ENGINE_GPO ||
  1305. ProfileType == SCE_ENGINE_SCP ) {
  1306. pPrivilegeAssigned->Next = *((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges);
  1307. *((PSCE_PRIVILEGE_ASSIGNMENT *)pPrivileges) = pPrivilegeAssigned;
  1308. pPrivilegeAssigned = NULL;
  1309. }
  1310. ScepFree(Value);
  1311. Value = NULL;
  1312. //
  1313. // read next line
  1314. //
  1315. // memset(KeyName, '\0', 72); KeyName will be manually terminated
  1316. rc = SceJetGetValue(
  1317. hSection,
  1318. SCEJET_NEXT_LINE,
  1319. NULL,
  1320. KeyName,
  1321. 70,
  1322. &KeyLen,
  1323. NULL,
  1324. 0,
  1325. &ValueLen
  1326. );
  1327. }
  1328. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1329. rc = SCESTATUS_SUCCESS;
  1330. if ( rc == SCESTATUS_SUCCESS ) {
  1331. if ( ProfileType == SCE_ENGINE_SCP_INTERNAL ||
  1332. ProfileType == SCE_ENGINE_SMP_INTERNAL )
  1333. *((PSCE_PRIVILEGE_VALUE_LIST *)pPrivileges) = pPrivilegeList;
  1334. }
  1335. Done:
  1336. //
  1337. // close the find index range
  1338. //
  1339. SceJetGetValue(
  1340. hSection,
  1341. SCEJET_CLOSE_VALUE,
  1342. NULL,
  1343. NULL,
  1344. 0,
  1345. NULL,
  1346. NULL,
  1347. 0,
  1348. NULL
  1349. );
  1350. if ( Value != NULL )
  1351. ScepFree(Value);
  1352. //
  1353. // close the section
  1354. //
  1355. SceJetCloseSection( &hSection, TRUE );
  1356. return(rc);
  1357. }
  1358. SCESTATUS
  1359. ScepAddToPrivilegeList(
  1360. OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
  1361. IN PWSTR Name,
  1362. IN DWORD Len,
  1363. IN DWORD PrivValue
  1364. )
  1365. {
  1366. PSCE_PRIVILEGE_VALUE_LIST pPriv,
  1367. LastOne=NULL;
  1368. if ( pPrivilegeList == NULL || Name == NULL || Len == 0 )
  1369. return(SCESTATUS_INVALID_PARAMETER);
  1370. for ( pPriv = *pPrivilegeList;
  1371. pPriv != NULL;
  1372. LastOne=pPriv, pPriv = pPriv->Next ) {
  1373. if ( ( wcslen(pPriv->Name) == Len ) &&
  1374. ( _wcsnicmp( pPriv->Name, Name, Len ) == 0 ) ) {
  1375. if ( PrivValue < 32 ) {
  1376. pPriv->PrivLowPart |= (1 << PrivValue);
  1377. } else {
  1378. pPriv->PrivHighPart |= (1 << (PrivValue-32) );
  1379. }
  1380. break;
  1381. }
  1382. }
  1383. if ( pPriv == NULL ) {
  1384. //
  1385. // Create a new one
  1386. //
  1387. pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
  1388. sizeof(SCE_PRIVILEGE_VALUE_LIST));
  1389. if ( pPriv == NULL )
  1390. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1391. pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
  1392. if ( pPriv->Name == NULL ) {
  1393. ScepFree(pPriv);
  1394. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1395. }
  1396. wcsncpy(pPriv->Name, Name, Len);
  1397. if ( PrivValue < 32 ) {
  1398. pPriv->PrivLowPart |= (1 << PrivValue);
  1399. } else {
  1400. pPriv->PrivHighPart |= (1 << (PrivValue-32) );
  1401. }
  1402. //
  1403. // link to the list
  1404. //
  1405. if ( LastOne != NULL )
  1406. LastOne->Next = pPriv;
  1407. else
  1408. *pPrivilegeList = pPriv;
  1409. }
  1410. return(SCESTATUS_SUCCESS);
  1411. }
  1412. SCESTATUS
  1413. ScepAddSidToPrivilegeList(
  1414. OUT PSCE_PRIVILEGE_VALUE_LIST *pPrivilegeList,
  1415. IN PSID pSid,
  1416. IN BOOL bReuseBuffer,
  1417. IN DWORD PrivValue,
  1418. OUT BOOL *pbBufferUsed
  1419. )
  1420. {
  1421. if ( pPrivilegeList == NULL || pbBufferUsed == NULL )
  1422. return(SCESTATUS_INVALID_PARAMETER);
  1423. *pbBufferUsed = FALSE;
  1424. if ( pSid == NULL ) {
  1425. return(SCESTATUS_SUCCESS);
  1426. }
  1427. if ( !ScepValidSid(pSid) ) {
  1428. return(SCESTATUS_INVALID_PARAMETER);
  1429. }
  1430. PSCE_PRIVILEGE_VALUE_LIST pPriv,
  1431. LastOne=NULL;
  1432. //
  1433. // check if the sid is already in the list
  1434. //
  1435. for ( pPriv = *pPrivilegeList;
  1436. pPriv != NULL;
  1437. LastOne=pPriv, pPriv = pPriv->Next ) {
  1438. if ( pPriv->Name == NULL ) {
  1439. continue;
  1440. }
  1441. if ( ScepValidSid( (PSID)(pPriv->Name) ) &&
  1442. RtlEqualSid( (PSID)(pPriv->Name), pSid ) ) {
  1443. if ( PrivValue < 32 ) {
  1444. pPriv->PrivLowPart |= (1 << PrivValue);
  1445. } else {
  1446. pPriv->PrivHighPart |= (1 << (PrivValue-32) );
  1447. }
  1448. break;
  1449. }
  1450. }
  1451. if ( pPriv == NULL ) {
  1452. //
  1453. // Create a new one
  1454. //
  1455. pPriv = (PSCE_PRIVILEGE_VALUE_LIST)ScepAlloc( LMEM_ZEROINIT,
  1456. sizeof(SCE_PRIVILEGE_VALUE_LIST));
  1457. if ( pPriv == NULL )
  1458. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1459. if ( bReuseBuffer ) {
  1460. pPriv->Name = (PWSTR)pSid;
  1461. *pbBufferUsed = TRUE;
  1462. } else {
  1463. DWORD Length = RtlLengthSid ( pSid );
  1464. pPriv->Name = (PWSTR)ScepAlloc( LMEM_ZEROINIT, Length);
  1465. if ( pPriv->Name == NULL ) {
  1466. ScepFree(pPriv);
  1467. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1468. }
  1469. RtlCopySid( Length, (PSID)(pPriv->Name), pSid );
  1470. }
  1471. if ( PrivValue < 32 ) {
  1472. pPriv->PrivLowPart |= (1 << PrivValue);
  1473. } else {
  1474. pPriv->PrivHighPart |= (1 << (PrivValue-32) );
  1475. }
  1476. //
  1477. // link to the list
  1478. //
  1479. if ( LastOne != NULL )
  1480. LastOne->Next = pPriv;
  1481. else
  1482. *pPrivilegeList = pPriv;
  1483. }
  1484. return(SCESTATUS_SUCCESS);
  1485. }
  1486. SCESTATUS
  1487. ScepGetGroupMembership(
  1488. IN PSCECONTEXT hProfile,
  1489. IN SCETYPE ProfileType,
  1490. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  1491. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1492. )
  1493. {
  1494. SCESTATUS rc;
  1495. DWORD OneStatus;
  1496. PSCE_GROUP_MEMBERSHIP pTempList=NULL, pNode, pGroup2,
  1497. pParent, pTemp;
  1498. LSA_HANDLE LsaHandle=NULL;
  1499. rc = RtlNtStatusToDosError(
  1500. ScepOpenLsaPolicy(
  1501. MAXIMUM_ALLOWED,
  1502. &LsaHandle,
  1503. TRUE
  1504. ));
  1505. if ( ERROR_SUCCESS != rc ) {
  1506. ScepBuildErrorLogInfo(
  1507. rc,
  1508. Errlog,
  1509. SCEDLL_LSA_POLICY
  1510. );
  1511. return(ScepDosErrorToSceStatus(rc));
  1512. }
  1513. //
  1514. // get groups from the requested table first
  1515. //
  1516. rc = ScepGetGroupMembershipFromOneTable(
  1517. LsaHandle,
  1518. hProfile,
  1519. ProfileType,
  1520. pGroupMembership,
  1521. Errlog
  1522. );
  1523. //
  1524. // return all groups if it is requested for SAP entry
  1525. //
  1526. if ( SCESTATUS_SUCCESS == rc && SCE_ENGINE_SAP == ProfileType ) {
  1527. //
  1528. // get the remaining stuff from SMP
  1529. //
  1530. rc = ScepGetGroupMembershipFromOneTable(
  1531. LsaHandle,
  1532. hProfile,
  1533. SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
  1534. &pTempList,
  1535. Errlog
  1536. );
  1537. if ( rc == SCESTATUS_SUCCESS ) {
  1538. //
  1539. // add non-exist nodes to pObjectRoots
  1540. //
  1541. pNode=pTempList;
  1542. pParent=NULL;
  1543. while ( pNode ) {
  1544. //
  1545. // if this node does not exist in the SAP
  1546. // this node is analyzed with "match" status
  1547. // if it already exists in SAP, it is a "mismatched" item
  1548. // duplication is prevented by the last argument TRUE
  1549. //
  1550. for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
  1551. if ( (pGroup2->Status & SCE_INTERNAL_NP) &&
  1552. _wcsicmp( pGroup2->GroupName, pNode->GroupName) == 0 )
  1553. break;
  1554. }
  1555. if ( pGroup2 ) {
  1556. //
  1557. // find the entry in SAP, mismatched item
  1558. // maybe pMembers, or pMemberOf
  1559. // or not analyzed item, or error items
  1560. //
  1561. OneStatus = pGroup2->Status;
  1562. pGroup2->Status = 0;
  1563. if ( (OneStatus & SCE_GROUP_STATUS_NOT_ANALYZED) ) {
  1564. // this item is added after last inspection
  1565. pGroup2->Status = SCE_GROUP_STATUS_NOT_ANALYZED;
  1566. } else if ( (OneStatus & SCE_GROUP_STATUS_ERROR_ANALYZED) ) {
  1567. // this item errored when analyzing
  1568. pGroup2->Status = SCE_GROUP_STATUS_ERROR_ANALYZED;
  1569. } else {
  1570. if ( pNode->Status & SCE_GROUP_STATUS_NC_MEMBERS ) {
  1571. pGroup2->Status |= SCE_GROUP_STATUS_NC_MEMBERS;
  1572. } else {
  1573. if ( !(OneStatus & SCE_GROUP_STATUS_NC_MEMBERS) ) {
  1574. pGroup2->Status |= SCE_GROUP_STATUS_MEMBERS_MISMATCH;
  1575. } else {
  1576. // a matched members, pGroup2->pMembers should be NULL;
  1577. if ( pGroup2->pMembers ) {
  1578. ScepFreeNameList(pGroup2->pMembers);
  1579. }
  1580. pGroup2->pMembers = pNode->pMembers;
  1581. pNode->pMembers = NULL;
  1582. }
  1583. }
  1584. if ( pNode->Status & SCE_GROUP_STATUS_NC_MEMBEROF ) {
  1585. pGroup2->Status |= SCE_GROUP_STATUS_NC_MEMBEROF;
  1586. } else {
  1587. if ( !(OneStatus & SCE_GROUP_STATUS_NC_MEMBEROF) ) {
  1588. pGroup2->Status |= SCE_GROUP_STATUS_MEMBEROF_MISMATCH;
  1589. } else {
  1590. // a matched memberof, pGroup2->pMemberOf should be NULL;
  1591. if ( pGroup2->pMemberOf ) {
  1592. ScepFreeNameList(pGroup2->pMemberOf);
  1593. }
  1594. pGroup2->pMemberOf = pNode->pMemberOf;
  1595. pNode->pMemberOf = NULL;
  1596. }
  1597. }
  1598. }
  1599. pParent = pNode;
  1600. pNode = pNode->Next;
  1601. } else {
  1602. //
  1603. // does not exist in SAP.
  1604. // this is a matched item on pMembers, and/or pMemberOf
  1605. // just move this node to SAP, with status NC_MEMBERS, or NC_MEMBEROF, or 0
  1606. //
  1607. if ( pParent )
  1608. pParent->Next = pNode->Next;
  1609. else
  1610. pTempList = pNode->Next;
  1611. pTemp = pNode;
  1612. pNode=pNode->Next;
  1613. pTemp->Next = *pGroupMembership;
  1614. *pGroupMembership = pTemp;
  1615. }
  1616. }
  1617. //
  1618. // group exist in analysis but not in template
  1619. //
  1620. for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
  1621. if ( pGroup2->Status & SCE_INTERNAL_NP )
  1622. pGroup2->Status = SCE_GROUP_STATUS_NC_MEMBERS | SCE_GROUP_STATUS_NC_MEMBEROF;
  1623. }
  1624. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  1625. rc = SCESTATUS_SUCCESS;
  1626. } else {
  1627. //
  1628. // pGroupMembership will be freed outside
  1629. //
  1630. }
  1631. if ( pTempList ) {
  1632. ScepFreeGroupMembership(pTempList);
  1633. }
  1634. }
  1635. //
  1636. // now the group name may be in *SID format, conver it now to name
  1637. //
  1638. if ( SCESTATUS_SUCCESS == rc && *pGroupMembership ) {
  1639. for ( pGroup2=*pGroupMembership; pGroup2 != NULL; pGroup2=pGroup2->Next ) {
  1640. if ( pGroup2->GroupName == NULL ) {
  1641. continue;
  1642. }
  1643. if ( pGroup2->GroupName[0] == L'*' ) {
  1644. //
  1645. // *SID format, convert it
  1646. //
  1647. PSID pSid=NULL;
  1648. if ( ConvertStringSidToSid( (pGroup2->GroupName)+1, &pSid) ) {
  1649. PWSTR strName=NULL;
  1650. DWORD strLen=0;
  1651. if (NT_SUCCESS( ScepConvertSidToName(
  1652. LsaHandle,
  1653. pSid,
  1654. TRUE, // want domain\account format
  1655. &strName,
  1656. &strLen
  1657. )) && strName ) {
  1658. ScepFree(pGroup2->GroupName);
  1659. pGroup2->GroupName = strName;
  1660. strName = NULL;
  1661. }
  1662. LocalFree(pSid);
  1663. pSid = NULL;
  1664. }
  1665. }
  1666. }
  1667. }
  1668. if ( LsaHandle ) {
  1669. LsaClose(LsaHandle);
  1670. }
  1671. return(rc);
  1672. }
  1673. SCESTATUS
  1674. ScepGetGroupMembershipFromOneTable(
  1675. IN LSA_HANDLE LsaPolicy,
  1676. IN PSCECONTEXT hProfile,
  1677. IN SCETYPE ProfileType,
  1678. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  1679. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1680. )
  1681. /* ++
  1682. Routine Description:
  1683. This routine retrieves group membership information from the Jet databasae
  1684. and stores in the output buffer pGroupMembership. Group membership information
  1685. is in [Group Membership] section.
  1686. Arguments:
  1687. hProfile - the profile handle context
  1688. ProfileType - Type of the Profile
  1689. SCE_ENGINE_SAP
  1690. SCE_ENGINE_SMP
  1691. SCE_ENGINE_SCP
  1692. pGroupMembership - the output buffer to hold group membership info.
  1693. Errlog - the error list for errors encountered in this routine.
  1694. Return value:
  1695. SCESTATUS - SCESTATUS_SUCCESS
  1696. SCESTATUS_NOT_ENOUGH_RESOURCE
  1697. SCESTATUS_INVALID_PARAMETER
  1698. SCESTATUS_BAD_FORMAT
  1699. SCESTATUS_INVALID_DATA
  1700. -- */
  1701. {
  1702. SCESTATUS rc;
  1703. PSCESECTION hSection=NULL;
  1704. PSCE_GROUP_MEMBERSHIP pGroup=NULL;
  1705. DWORD GroupLen, ValueLen;
  1706. PWSTR GroupName=NULL;
  1707. PWSTR Value=NULL;
  1708. DWORD ValueType;
  1709. ULONG Len;
  1710. PWSTR pTemp;
  1711. if ( pGroupMembership == NULL )
  1712. return(SCESTATUS_INVALID_PARAMETER);
  1713. rc = ScepOpenSectionForName(
  1714. hProfile,
  1715. ProfileType,
  1716. szGroupMembership,
  1717. &hSection
  1718. );
  1719. if ( rc != SCESTATUS_SUCCESS ) {
  1720. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  1721. Errlog,
  1722. SCEERR_OPEN,
  1723. szGroupMembership
  1724. );
  1725. return(rc);
  1726. }
  1727. //
  1728. // goto the first line of this section
  1729. //
  1730. rc = SceJetGetValue(
  1731. hSection,
  1732. SCEJET_PREFIX_MATCH,
  1733. NULL,
  1734. NULL,
  1735. 0,
  1736. &GroupLen,
  1737. NULL,
  1738. 0,
  1739. &ValueLen
  1740. );
  1741. while ( rc == SCESTATUS_SUCCESS ) {
  1742. //
  1743. // allocate memory for the group name and value string
  1744. //
  1745. GroupName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, GroupLen+2);
  1746. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  1747. if ( GroupName == NULL || Value == NULL ) {
  1748. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1749. goto Done;
  1750. }
  1751. //
  1752. // Get the group and its value
  1753. //
  1754. rc = SceJetGetValue(
  1755. hSection,
  1756. SCEJET_CURRENT,
  1757. NULL,
  1758. GroupName,
  1759. GroupLen,
  1760. &GroupLen,
  1761. Value,
  1762. ValueLen,
  1763. &ValueLen
  1764. );
  1765. if ( rc != SCESTATUS_SUCCESS )
  1766. goto Done;
  1767. GroupName[GroupLen/2] = L'\0';
  1768. Value[ValueLen/2] = L'\0';
  1769. #ifdef SCE_DBG
  1770. wprintf(L"rc=%d, group membership: %s=%s\n", rc, GroupName, Value);
  1771. #endif
  1772. if (pTemp = ScepWcstrr(GroupName, szMembers) )
  1773. ValueType = 0;
  1774. else if (pTemp = ScepWcstrr(GroupName, szMemberof) )
  1775. ValueType = 1;
  1776. else if (pTemp = ScepWcstrr(GroupName, szPrivileges) )
  1777. ValueType = 2;
  1778. if ( pTemp == NULL ) {
  1779. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  1780. Errlog,
  1781. SCEERR_CANT_FIND_KEYWORD,
  1782. GroupName
  1783. );
  1784. rc = SCESTATUS_INVALID_DATA;
  1785. goto NextLine; //Done;
  1786. }
  1787. Len = (DWORD)(pTemp - GroupName);
  1788. //
  1789. // if this is the first group, or a different group, create another node
  1790. // Note, the group name may be in SID string format now.
  1791. // Will be converted later (in the calling function) because we don't want
  1792. // to lookup for the same group name several times (each group may have
  1793. // multiple records).
  1794. //
  1795. if ( *pGroupMembership == NULL ||
  1796. _wcsnicmp((*pGroupMembership)->GroupName, GroupName, Len) != 0 ||
  1797. (*pGroupMembership)->GroupName[Len] != L'\0' ) {
  1798. //
  1799. // a new group. allocate buffer
  1800. //
  1801. pGroup = (PSCE_GROUP_MEMBERSHIP)ScepAlloc( LMEM_ZEROINIT, sizeof(SCE_GROUP_MEMBERSHIP) );
  1802. if ( pGroup == NULL ) {
  1803. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1804. goto Done;
  1805. }
  1806. pGroup->GroupName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
  1807. if ( pGroup->GroupName == NULL ) {
  1808. ScepFree(pGroup);
  1809. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1810. goto Done;
  1811. }
  1812. //
  1813. // get right case for group name
  1814. //
  1815. wcsncpy(pGroup->GroupName, GroupName, Len);
  1816. // do not care return codes
  1817. ScepGetGroupCase(pGroup->GroupName, Len);
  1818. pGroup->Next = *pGroupMembership;
  1819. // if ( SCE_ENGINE_SAP == ProfileType )
  1820. pGroup->Status = SCE_GROUP_STATUS_NC_MEMBERS | SCE_GROUP_STATUS_NC_MEMBEROF;
  1821. // else
  1822. // pGroup->Status = 0;
  1823. if ( SCE_ENGINE_SAP == ProfileType )
  1824. pGroup->Status |= SCE_INTERNAL_NP;
  1825. }
  1826. //
  1827. // add the multi-sz value string to the group node, depending on the value type
  1828. //
  1829. pTemp = Value;
  1830. while ( rc == SCESTATUS_SUCCESS && pTemp != NULL && pTemp[0] ) {
  1831. while ( *pTemp && L' ' == *pTemp ) {
  1832. pTemp++;
  1833. }
  1834. if ( SCE_ENGINE_SAP == ProfileType ) {
  1835. if ( !(*pTemp) ) {
  1836. // this is an not analyzed item
  1837. pGroup->Status = SCE_GROUP_STATUS_NOT_ANALYZED |
  1838. SCE_INTERNAL_NP;
  1839. break;
  1840. } else if ( _wcsicmp(SCE_ERROR_STRING, pTemp) == 0 ) {
  1841. // this is error item
  1842. pGroup->Status = SCE_GROUP_STATUS_ERROR_ANALYZED |
  1843. SCE_INTERNAL_NP;
  1844. break;
  1845. }
  1846. }
  1847. if ( !(*pTemp) ) {
  1848. // empty string is not allowed
  1849. break;
  1850. }
  1851. Len = wcslen(pTemp);
  1852. if ( ValueType != 0 && ValueType != 1 ) {
  1853. #if 0
  1854. //
  1855. // privilege with optional via group name
  1856. //
  1857. Status = (*((CHAR *)pTemp)-'0')*10 + ((*((CHAR *)pTemp+1)) - '0');
  1858. PWSTR strName=NULL;
  1859. DWORD strLen=0;
  1860. if ( pTemp[1] == L'*' ) {
  1861. //
  1862. // convert the SID string into name format
  1863. //
  1864. PSID pSid=NULL;
  1865. if ( ConvertStringSidToSid( pTemp+2, &pSid) ) {
  1866. rc = RtlNtStatusToDosError(
  1867. ScepConvertSidToName(
  1868. LsaPolicy,
  1869. pSid,
  1870. TRUE, // want domain\account format
  1871. &strName,
  1872. &strLen
  1873. ));
  1874. LocalFree(pSid);
  1875. pSid = NULL;
  1876. } else {
  1877. rc = GetLastError();
  1878. }
  1879. }
  1880. if ( ERROR_SUCCESS == rc && strName ) {
  1881. rc = ScepAddToNameStatusList(&(pGroup->pPrivilegesHeld),
  1882. strName,
  1883. strLen,
  1884. Status);
  1885. } else {
  1886. //
  1887. // if failed to convert, or it's a name format already
  1888. // just add it to the list
  1889. //
  1890. rc = ScepAddToNameStatusList(&(pGroup->pPrivilegesHeld),
  1891. pTemp+1, Len-1, Status);
  1892. }
  1893. if ( strName ) {
  1894. ScepFree(strName);
  1895. strName = NULL;
  1896. }
  1897. #endif
  1898. } else {
  1899. //
  1900. // members (0) of memberof (1)
  1901. //
  1902. if ( pTemp[0] == L'*' ) {
  1903. //
  1904. // *SID format, convert to name, and add to the list
  1905. //
  1906. rc = ScepLookupSidStringAndAddToNameList(LsaPolicy,
  1907. (ValueType == 0) ?
  1908. &(pGroup->pMembers):
  1909. &(pGroup->pMemberOf),
  1910. pTemp, // +1,
  1911. Len // -1
  1912. );
  1913. } else {
  1914. rc = ScepAddToNameList((ValueType == 0) ?
  1915. &(pGroup->pMembers):
  1916. &(pGroup->pMemberOf),
  1917. pTemp,
  1918. Len );
  1919. }
  1920. }
  1921. #ifdef SCE_DBG
  1922. wprintf(L"Add %s to group list\n", pTemp);
  1923. #endif
  1924. pTemp += Len +1;
  1925. }
  1926. //
  1927. // Free memory
  1928. //
  1929. if ( rc != SCESTATUS_SUCCESS && pGroup != *pGroupMembership ) {
  1930. pGroup->Next = NULL;
  1931. ScepFreeGroupMembership( pGroup );
  1932. goto Done;
  1933. }
  1934. switch ( ValueType ) {
  1935. case 0: // members
  1936. pGroup->Status &= ~SCE_GROUP_STATUS_NC_MEMBERS;
  1937. break;
  1938. case 1:
  1939. pGroup->Status &= ~SCE_GROUP_STATUS_NC_MEMBEROF;
  1940. break;
  1941. }
  1942. *pGroupMembership = pGroup;
  1943. NextLine:
  1944. ScepFree(GroupName);
  1945. GroupName = NULL;
  1946. ScepFree(Value);
  1947. Value = NULL;
  1948. //
  1949. // read next line
  1950. //
  1951. rc = SceJetGetValue(
  1952. hSection,
  1953. SCEJET_NEXT_LINE,
  1954. NULL,
  1955. NULL,
  1956. 0,
  1957. &GroupLen,
  1958. NULL,
  1959. 0,
  1960. &ValueLen
  1961. );
  1962. }
  1963. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  1964. rc = SCESTATUS_SUCCESS;
  1965. Done:
  1966. //
  1967. // close the find index range
  1968. //
  1969. SceJetGetValue(
  1970. hSection,
  1971. SCEJET_CLOSE_VALUE,
  1972. NULL,
  1973. NULL,
  1974. 0,
  1975. NULL,
  1976. NULL,
  1977. 0,
  1978. NULL
  1979. );
  1980. if ( GroupName != NULL )
  1981. ScepFree(GroupName);
  1982. if ( Value != NULL )
  1983. ScepFree(Value);
  1984. //
  1985. // close the section
  1986. //
  1987. SceJetCloseSection( &hSection, TRUE );
  1988. return(rc);
  1989. }
  1990. SCESTATUS
  1991. ScepOpenSectionForName(
  1992. IN PSCECONTEXT hProfile,
  1993. IN SCETYPE ProfileType,
  1994. IN PCWSTR SectionName,
  1995. OUT PSCESECTION *phSection
  1996. )
  1997. {
  1998. SCESTATUS rc;
  1999. DOUBLE SectionID;
  2000. SCEJET_TABLE_TYPE tblType;
  2001. //
  2002. // table type
  2003. //
  2004. switch ( ProfileType ) {
  2005. case SCE_ENGINE_SCP:
  2006. case SCE_ENGINE_SCP_INTERNAL:
  2007. tblType = SCEJET_TABLE_SCP;
  2008. break;
  2009. case SCE_ENGINE_SMP:
  2010. case SCE_ENGINE_SMP_INTERNAL:
  2011. tblType = SCEJET_TABLE_SMP;
  2012. break;
  2013. case SCE_ENGINE_SAP:
  2014. tblType = SCEJET_TABLE_SAP;
  2015. break;
  2016. default:
  2017. return(SCESTATUS_INVALID_PARAMETER);
  2018. }
  2019. //
  2020. // get section id
  2021. //
  2022. rc = SceJetGetSectionIDByName(
  2023. hProfile,
  2024. SectionName,
  2025. &SectionID
  2026. );
  2027. if ( rc != SCESTATUS_SUCCESS )
  2028. return(rc);
  2029. rc = SceJetOpenSection(
  2030. hProfile,
  2031. SectionID,
  2032. tblType,
  2033. phSection
  2034. );
  2035. return(rc);
  2036. }
  2037. SCESTATUS
  2038. ScepGetDsRoot(
  2039. IN PSCECONTEXT hProfile,
  2040. IN SCETYPE ProfileType,
  2041. IN PCWSTR SectionName,
  2042. OUT PSCE_OBJECT_LIST *pObjectRoots,
  2043. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2044. )
  2045. /*
  2046. DS object root has only one entry, which is the DS domain name
  2047. So the list contains only one entry.
  2048. The format of the DS domain name is dc=<domain>,dc=<domain1>,...o=internet,
  2049. which is the DNS name of the DS domain in LDAP format
  2050. */
  2051. {
  2052. SCESTATUS rc;
  2053. PSCESECTION hSection=NULL;
  2054. PSCE_OBJECT_LIST pDsRoot=NULL;
  2055. PWSTR JetName=NULL;
  2056. BOOL IsContainer, LastOne;
  2057. DWORD Count, ValueLen;
  2058. BYTE Status;
  2059. WCHAR StatusFlag=L'\0';
  2060. rc = ScepOpenSectionForName(
  2061. hProfile,
  2062. ProfileType,
  2063. SectionName,
  2064. &hSection
  2065. );
  2066. if ( rc != SCESTATUS_SUCCESS ) {
  2067. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  2068. Errlog,
  2069. SCEERR_OPEN,
  2070. SectionName
  2071. );
  2072. return(rc);
  2073. }
  2074. rc = ScepLdapOpen(NULL);
  2075. if ( rc == SCESTATUS_SUCCESS ) {
  2076. rc = ScepEnumerateDsObjectRoots(
  2077. NULL,
  2078. &pDsRoot
  2079. );
  2080. ScepLdapClose(NULL);
  2081. }
  2082. if ( rc == SCESTATUS_SUCCESS ) {
  2083. if ( pDsRoot == NULL ) {
  2084. rc = SCESTATUS_PROFILE_NOT_FOUND;
  2085. } else {
  2086. //
  2087. // Convert domain root
  2088. //
  2089. rc = ScepConvertLdapToJetIndexName(
  2090. pDsRoot->Name,
  2091. &JetName
  2092. );
  2093. }
  2094. }
  2095. if ( rc == SCESTATUS_SUCCESS ) {
  2096. //
  2097. // goto the line matching the domain root
  2098. //
  2099. rc = SceJetSeek(
  2100. hSection,
  2101. JetName,
  2102. wcslen(JetName)*sizeof(WCHAR),
  2103. SCEJET_SEEK_GE
  2104. );
  2105. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2106. if ( ProfileType == SCE_ENGINE_SAP ) {
  2107. //
  2108. // the domain is not in the table, try another one
  2109. //
  2110. SceJetCloseSection(&hSection, FALSE);
  2111. rc = ScepOpenSectionForName(
  2112. hProfile,
  2113. SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
  2114. SectionName,
  2115. &hSection
  2116. );
  2117. if ( rc == SCESTATUS_SUCCESS ) {
  2118. //
  2119. // get count under the domain
  2120. //
  2121. Count = 0;
  2122. rc = SceJetGetLineCount(
  2123. hSection,
  2124. JetName,
  2125. FALSE,
  2126. &Count);
  2127. if ( rc == SCESTATUS_SUCCESS ||
  2128. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2129. if ( rc == SCESTATUS_SUCCESS )
  2130. pDsRoot->Status = SCE_STATUS_CHECK;
  2131. else
  2132. pDsRoot->Status = SCE_STATUS_NOT_CONFIGURED;
  2133. pDsRoot->IsContainer = TRUE;
  2134. pDsRoot->Count = Count;
  2135. *pObjectRoots = pDsRoot;
  2136. pDsRoot = NULL;
  2137. rc = SCESTATUS_SUCCESS;
  2138. }
  2139. }
  2140. }
  2141. rc = SCESTATUS_SUCCESS;
  2142. } else if ( rc == SCESTATUS_SUCCESS ) {
  2143. //
  2144. // something of the domain exist, get value and count of the domain
  2145. //
  2146. rc = SceJetGetValue(
  2147. hSection,
  2148. SCEJET_EXACT_MATCH,
  2149. JetName,
  2150. NULL,
  2151. 0,
  2152. NULL,
  2153. (PWSTR)&StatusFlag, // two bytes buffer
  2154. 2,
  2155. &ValueLen
  2156. );
  2157. if ( rc == SCESTATUS_SUCCESS ||
  2158. rc == SCESTATUS_BUFFER_TOO_SMALL ||
  2159. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2160. if ( rc != SCESTATUS_RECORD_NOT_FOUND ) {
  2161. LastOne = TRUE;
  2162. Status = *((BYTE *)&StatusFlag);
  2163. IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
  2164. } else {
  2165. LastOne = FALSE;
  2166. IsContainer = TRUE;
  2167. if ( ProfileType == SCE_ENGINE_SAP )
  2168. Status = SCE_STATUS_GOOD;
  2169. else
  2170. Status = SCE_STATUS_CHECK;
  2171. }
  2172. //
  2173. // get count under the domain
  2174. //
  2175. rc = SceJetGetLineCount(
  2176. hSection,
  2177. JetName,
  2178. FALSE,
  2179. &Count);
  2180. if ( rc == SCESTATUS_SUCCESS ) {
  2181. if ( LastOne )
  2182. Count--;
  2183. if ( !IsContainer && Count > 0 ) {
  2184. IsContainer = TRUE;
  2185. }
  2186. //
  2187. // the proper domain name is in pDsRoot
  2188. //
  2189. pDsRoot->Status = Status;
  2190. pDsRoot->IsContainer = IsContainer;
  2191. pDsRoot->Count = Count;
  2192. *pObjectRoots = pDsRoot;
  2193. pDsRoot = NULL;
  2194. }
  2195. }
  2196. }
  2197. if ( SCESTATUS_RECORD_NOT_FOUND == rc ) {
  2198. rc = SCESTATUS_SUCCESS;
  2199. }
  2200. if ( rc != SCESTATUS_SUCCESS ) {
  2201. ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc),
  2202. Errlog, SCEERR_QUERY_INFO,
  2203. L"SCP/SMP");
  2204. }
  2205. if ( JetName != NULL ) {
  2206. ScepFree(JetName);
  2207. }
  2208. } else {
  2209. ScepBuildErrorLogInfo(ScepSceStatusToDosError(rc),
  2210. Errlog, SCEERR_QUERY_INFO,
  2211. SectionName);
  2212. }
  2213. ScepFreeObjectList(pDsRoot);
  2214. SceJetCloseSection(&hSection, TRUE);
  2215. return(rc);
  2216. }
  2217. SCESTATUS
  2218. ScepGetObjectList(
  2219. IN PSCECONTEXT hProfile,
  2220. IN SCETYPE ProfileType,
  2221. IN PCWSTR SectionName,
  2222. OUT PSCE_OBJECT_LIST *pObjectRoots,
  2223. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2224. )
  2225. /* ++
  2226. Routine Description:
  2227. This routine retrieves registry or files security information from the JET
  2228. database for the root only. To get detail under a root object, call
  2229. ScepGetChildrentObject.
  2230. For Profiletype "SCE_ENGINE_SAP" (analysis info), a combination of SMP and SAP
  2231. are returned for a complete set of "analyzed" objects.
  2232. Arguments:
  2233. hProfile - the profile handle context
  2234. ProfileType - value to indicate engine type.
  2235. SCE_ENGINE_SCP
  2236. SCE_ENGINE_SAP
  2237. SCE_ENGINE_SMP
  2238. SectionName - The section name for the objects to retrieve.
  2239. pObjectRoots - The output list of object roots
  2240. Errlog - the cummulative error list to hold errors encountered in this routine.
  2241. Return value:
  2242. SCESTATUS - SCESTATUS_SUCCESS
  2243. SCESTATUS_NOT_ENOUGH_RESOURCE
  2244. SCESTATUS_INVALID_PARAMETER
  2245. SCESTATUS_BAD_FORMAT
  2246. SCESTATUS_INVALID_DATA
  2247. -- */
  2248. {
  2249. SCESTATUS rc;
  2250. PSCE_OBJECT_LIST pTempList=NULL,
  2251. pNode;
  2252. //
  2253. // get roots from the first table first
  2254. //
  2255. rc = ScepGetObjectFromOneTable(
  2256. hProfile,
  2257. ProfileType,
  2258. SectionName,
  2259. pObjectRoots,
  2260. Errlog
  2261. );
  2262. //
  2263. // Ds objects only return the domain name, no need to search SMP
  2264. //
  2265. if ( rc == SCESTATUS_SUCCESS && ProfileType == SCE_ENGINE_SAP ) {
  2266. //
  2267. // get the stuff from SMP
  2268. //
  2269. rc = ScepGetObjectFromOneTable(
  2270. hProfile,
  2271. SCE_ENGINE_SCP, // SCE_ENGINE_SMP,
  2272. SectionName,
  2273. &pTempList,
  2274. Errlog
  2275. );
  2276. if ( rc == SCESTATUS_SUCCESS ) {
  2277. //
  2278. // add non-exist nodes to pObjectRoots
  2279. //
  2280. for ( pNode=pTempList; pNode != NULL; pNode = pNode->Next ) {
  2281. //
  2282. // if this node does not exist in the SAP
  2283. // this node is analyzed with "match" status and
  2284. // no bad children under the node
  2285. // duplication is prevented by the last argument
  2286. //
  2287. rc = ScepAddToObjectList(pObjectRoots, pNode->Name, 0,
  2288. pNode->IsContainer, SCE_STATUS_GOOD, 0, SCE_CHECK_DUP);
  2289. if ( rc != ERROR_SUCCESS ) {
  2290. ScepBuildErrorLogInfo( rc,
  2291. Errlog,
  2292. SCEERR_ADD,
  2293. pNode->Name
  2294. );
  2295. //
  2296. // only the following two errors could be returned
  2297. //
  2298. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  2299. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2300. break;
  2301. } else
  2302. rc = SCESTATUS_INVALID_PARAMETER;
  2303. }
  2304. }
  2305. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2306. rc = SCESTATUS_SUCCESS;
  2307. } else {
  2308. //
  2309. // pObjectRoots will be freed outside
  2310. //
  2311. }
  2312. if ( pTempList ) {
  2313. ScepFreeObjectList(pTempList);
  2314. }
  2315. }
  2316. return(rc);
  2317. }
  2318. SCESTATUS
  2319. ScepGetObjectFromOneTable(
  2320. IN PSCECONTEXT hProfile,
  2321. IN SCETYPE ProfileType,
  2322. IN PCWSTR SectionName,
  2323. OUT PSCE_OBJECT_LIST *pObjectRoots,
  2324. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2325. )
  2326. /* ++
  2327. Routine Description:
  2328. This routine retrieves registry or files security information from the JET
  2329. database for the root only. To get detail under a root object, call
  2330. ScepGetChildrentObject.
  2331. Arguments:
  2332. hProfile - the profile handle context
  2333. ProfileType - value to indicate engine type.
  2334. SCE_ENGINE_SCP
  2335. SCE_ENGINE_SAP
  2336. SCE_ENGINE_SMP
  2337. SectionName - The section name for the objects to retrieve.
  2338. pObjectRoots - The output list of object roots
  2339. Errlog - the cummulative error list to hold errors encountered in this routine.
  2340. Return value:
  2341. SCESTATUS - SCESTATUS_SUCCESS
  2342. SCESTATUS_NOT_ENOUGH_RESOURCE
  2343. SCESTATUS_INVALID_PARAMETER
  2344. SCESTATUS_BAD_FORMAT
  2345. SCESTATUS_INVALID_DATA
  2346. -- */
  2347. {
  2348. SCESTATUS rc;
  2349. PSCESECTION hSection=NULL;
  2350. DWORD ObjectLen=0;
  2351. WCHAR ObjectName[21];
  2352. WCHAR StatusFlag=L'\0';
  2353. BYTE Status=0;
  2354. BOOL IsContainer=TRUE;
  2355. DWORD Len, Count;
  2356. WCHAR Buffer[21];
  2357. BOOL LastOne;
  2358. DWORD ValueLen=0;
  2359. rc = ScepOpenSectionForName(
  2360. hProfile,
  2361. ProfileType,
  2362. SectionName,
  2363. &hSection
  2364. );
  2365. if ( rc != SCESTATUS_SUCCESS ) {
  2366. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  2367. Errlog,
  2368. SCEERR_OPEN,
  2369. SectionName
  2370. );
  2371. return(rc);
  2372. }
  2373. //
  2374. // goto the first line of this section
  2375. //
  2376. rc = SceJetSeek(
  2377. hSection,
  2378. NULL,
  2379. 0,
  2380. SCEJET_SEEK_GE
  2381. );
  2382. while ( rc == SCESTATUS_SUCCESS ||
  2383. rc == SCESTATUS_BUFFER_TOO_SMALL ) {
  2384. memset(ObjectName, '\0', 21*sizeof(WCHAR));
  2385. memset(Buffer, '\0', 21*sizeof(WCHAR));
  2386. rc = SceJetGetValue(
  2387. hSection,
  2388. SCEJET_CURRENT,
  2389. NULL,
  2390. ObjectName,
  2391. 20*sizeof(WCHAR),
  2392. &ObjectLen,
  2393. (PWSTR)&StatusFlag, // two bytes buffer
  2394. 2,
  2395. &ValueLen
  2396. );
  2397. #ifdef SCE_DBG
  2398. wprintf(L"ObjectLen=%d, StatusFlag=%x, ValueLen=%d, rc=%d, ObjectName=%s \n",
  2399. ObjectLen, StatusFlag, ValueLen, rc, ObjectName);
  2400. #endif
  2401. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_BUFFER_TOO_SMALL ) {
  2402. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  2403. Errlog,
  2404. SCEERR_QUERY_VALUE,
  2405. SectionName
  2406. );
  2407. break;
  2408. }
  2409. //
  2410. // get first component of the object
  2411. //
  2412. if ( ObjectLen <= 40 )
  2413. ObjectName[ObjectLen/sizeof(WCHAR)] = L'\0';
  2414. rc = ScepGetNameInLevel(
  2415. ObjectName,
  2416. 1,
  2417. L'\\',
  2418. Buffer,
  2419. &LastOne
  2420. );
  2421. if ( rc == SCESTATUS_SUCCESS ) {
  2422. Len = wcslen(Buffer);
  2423. if ( LastOne ) {
  2424. Status = *((BYTE *)&StatusFlag);
  2425. IsContainer = *((CHAR *)&StatusFlag+1) != '0' ? TRUE : FALSE;
  2426. } else {
  2427. IsContainer = TRUE;
  2428. if ( ProfileType == SCE_ENGINE_SAP )
  2429. Status = SCE_STATUS_GOOD;
  2430. else
  2431. Status = SCE_STATUS_CHECK;
  2432. }
  2433. #ifdef SCE_DBG
  2434. printf("\nStatus=%d, StatusFlag=%x, Len=%d, Buffer=%ws\n", Status, StatusFlag, Len, Buffer);
  2435. #endif
  2436. //
  2437. // get count of this object
  2438. //
  2439. rc = SceJetGetLineCount(
  2440. hSection,
  2441. Buffer,
  2442. FALSE,
  2443. &Count);
  2444. if ( rc == SCESTATUS_SUCCESS ||
  2445. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2446. if ( LastOne )
  2447. Count--;
  2448. if ( !IsContainer && Count > 0 ) {
  2449. IsContainer = TRUE;
  2450. }
  2451. //
  2452. // the root of registry and file are always upper cased
  2453. //
  2454. _wcsupr(Buffer);
  2455. rc = ScepAddToObjectList(pObjectRoots, Buffer, Len,
  2456. IsContainer, Status, Count, 0);
  2457. if ( rc != ERROR_SUCCESS ) {
  2458. ScepBuildErrorLogInfo( rc,
  2459. Errlog,
  2460. SCEERR_ADD,
  2461. Buffer
  2462. );
  2463. // only the following two errors could be returned
  2464. if ( rc == ERROR_NOT_ENOUGH_MEMORY )
  2465. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2466. else
  2467. rc = SCESTATUS_INVALID_PARAMETER;
  2468. }
  2469. }
  2470. if ( rc == SCESTATUS_SUCCESS ) {
  2471. //
  2472. // seek to the next one
  2473. //
  2474. Buffer[Len-1] = (WCHAR)( Buffer[Len-1] + 1);
  2475. rc = SceJetSeek(
  2476. hSection,
  2477. Buffer,
  2478. Len*sizeof(TCHAR),
  2479. SCEJET_SEEK_GT_NO_CASE
  2480. );
  2481. if ( rc != SCESTATUS_SUCCESS && rc != SCESTATUS_RECORD_NOT_FOUND )
  2482. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  2483. Errlog,
  2484. SCEERR_QUERY_VALUE,
  2485. SectionName
  2486. );
  2487. }
  2488. }
  2489. }
  2490. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  2491. rc = SCESTATUS_SUCCESS;
  2492. //
  2493. // close the section
  2494. //
  2495. SceJetCloseSection( &hSection, TRUE );
  2496. return(rc);
  2497. }
  2498. SCESTATUS
  2499. ScepGetAuditing(
  2500. IN PSCECONTEXT hProfile,
  2501. IN SCETYPE ProfileType,
  2502. OUT PSCE_PROFILE_INFO pProfileInfo,
  2503. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2504. )
  2505. /* ++
  2506. Routine Description:
  2507. This routine retrieves system auditing information from the JET database
  2508. and stores in the output buffer pProfileInfo. The auditing information
  2509. is stored in [System Log], [Security Log], [Application Log], [Audit Event],
  2510. [Audit Registry], and [Audit File] sections.
  2511. Arguments:
  2512. hProfile - the profile handle context
  2513. pProfileInfo - the output buffer to hold profile info.
  2514. Errlog - The cummulative error list to hold errors encountered in this routine.
  2515. Return value:
  2516. SCESTATUS - SCESTATUS_SUCCESS
  2517. SCESTATUS_NOT_ENOUGH_RESOURCE
  2518. SCESTATUS_INVALID_PARAMETER
  2519. SCESTATUS_BAD_FORMAT
  2520. SCESTATUS_INVALID_DATA
  2521. -- */
  2522. {
  2523. SCESTATUS rc;
  2524. SCE_KEY_LOOKUP LogKeys[]={
  2525. {(PWSTR)TEXT("MaximumLogSize"), offsetof(struct _SCE_PROFILE_INFO, MaximumLogSize), 'D'},
  2526. {(PWSTR)TEXT("AuditLogRetentionPeriod"),offsetof(struct _SCE_PROFILE_INFO, AuditLogRetentionPeriod), 'D'},
  2527. {(PWSTR)TEXT("RetentionDays"), offsetof(struct _SCE_PROFILE_INFO, RetentionDays), 'D'},
  2528. {(PWSTR)TEXT("RestrictGuestAccess"), offsetof(struct _SCE_PROFILE_INFO, RestrictGuestAccess), 'D'}
  2529. };
  2530. SCE_KEY_LOOKUP EventKeys[]={
  2531. {(PWSTR)TEXT("AuditSystemEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditSystemEvents), 'D'},
  2532. {(PWSTR)TEXT("AuditLogonEvents"), offsetof(struct _SCE_PROFILE_INFO, AuditLogonEvents), 'D'},
  2533. {(PWSTR)TEXT("AuditObjectAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditObjectAccess), 'D'},
  2534. {(PWSTR)TEXT("AuditPrivilegeUse"), offsetof(struct _SCE_PROFILE_INFO, AuditPrivilegeUse), 'D'},
  2535. {(PWSTR)TEXT("AuditPolicyChange"), offsetof(struct _SCE_PROFILE_INFO, AuditPolicyChange), 'D'},
  2536. {(PWSTR)TEXT("AuditAccountManage"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountManage), 'D'},
  2537. {(PWSTR)TEXT("AuditProcessTracking"),offsetof(struct _SCE_PROFILE_INFO, AuditProcessTracking),'D'},
  2538. {(PWSTR)TEXT("AuditDSAccess"), offsetof(struct _SCE_PROFILE_INFO, AuditDSAccess), 'D'},
  2539. {(PWSTR)TEXT("AuditAccountLogon"), offsetof(struct _SCE_PROFILE_INFO, AuditAccountLogon), 'D'}};
  2540. DWORD cKeys = sizeof(EventKeys) / sizeof(SCE_KEY_LOOKUP);
  2541. PCWSTR szAuditLog;
  2542. DWORD i, j;
  2543. PSCESECTION hSection=NULL;
  2544. if ( hProfile == NULL ||
  2545. pProfileInfo == NULL ) {
  2546. return(SCESTATUS_INVALID_PARAMETER);
  2547. }
  2548. for ( i=0; i<3; i++) {
  2549. //
  2550. // Get Event Log setting for system log, security log and application log
  2551. //
  2552. switch (i) {
  2553. case 0:
  2554. szAuditLog = szAuditSystemLog;
  2555. break;
  2556. case 1:
  2557. szAuditLog = szAuditSecurityLog;
  2558. break;
  2559. default:
  2560. szAuditLog = szAuditApplicationLog;
  2561. break;
  2562. }
  2563. //
  2564. // get DWORD values for the section
  2565. //
  2566. rc = ScepGetFixValueSection(
  2567. hProfile,
  2568. szAuditLog,
  2569. LogKeys,
  2570. 4,
  2571. ProfileType,
  2572. (PVOID)pProfileInfo,
  2573. &hSection,
  2574. Errlog
  2575. );
  2576. if ( rc != SCESTATUS_SUCCESS )
  2577. goto Done;
  2578. // close the section
  2579. SceJetCloseSection( &hSection, FALSE );
  2580. //
  2581. // update the Offset for next section
  2582. //
  2583. for ( j=0; j<4; j++ )
  2584. LogKeys[j].Offset += sizeof(DWORD);
  2585. }
  2586. //
  2587. // Get Audit Event info
  2588. //
  2589. //
  2590. // get DWORD values for the section
  2591. //
  2592. rc = ScepGetFixValueSection(
  2593. hProfile,
  2594. szAuditEvent,
  2595. EventKeys,
  2596. cKeys,
  2597. ProfileType,
  2598. (PVOID)pProfileInfo,
  2599. &hSection,
  2600. Errlog
  2601. );
  2602. if ( rc != SCESTATUS_SUCCESS )
  2603. goto Done;
  2604. // close the section
  2605. SceJetCloseSection( &hSection, TRUE );
  2606. Done:
  2607. // close the section
  2608. if ( rc != SCESTATUS_SUCCESS )
  2609. SceJetCloseSection( &hSection, TRUE );
  2610. return(rc);
  2611. }
  2612. //////////////////////////////
  2613. // helper APIs
  2614. //////////////////////////////
  2615. SCESTATUS
  2616. ScepGetUserSection(
  2617. IN PSCECONTEXT hProfile,
  2618. IN SCETYPE ProfileType,
  2619. IN PWSTR Name,
  2620. OUT PVOID *ppInfo,
  2621. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2622. )
  2623. /* ++
  2624. Function Description:
  2625. This routine get a dynamic section's information for a security area.
  2626. Dynamic sections are those created dynamically, based on other sections'
  2627. related information. Dynamic sections in a profile include User Security
  2628. Profiles for SCP and User Settings for SAP/SMP. Name contains the section's
  2629. identifier, either the section's name, or a partial name (e.g., a user
  2630. name) for the section. The output must be casted to different structure,
  2631. depending on the ProfileType and Area.
  2632. The output buffer contains one instance of the requested information,
  2633. e.g., one user security profile or one user's setting. To get all dynamic
  2634. sections, this routine must be called repeatly. The output buffer must
  2635. be freed by LocalFree after its use.
  2636. Arguments:
  2637. hProfile - The handle of the profile
  2638. ProfileType - The type of the profile to read
  2639. Name - The dynamic section's identifier
  2640. ppInfo - Output buffer (PSCE_USER_PROFILE or PSCE_USER_SETTING)
  2641. Errlog - The error log buffer
  2642. Return Value:
  2643. SCESTATUS_SUCCESS
  2644. SCESTATUS_PROFILE_NOT_FOUND
  2645. SCESTATUS_NOT_ENOUGH_RESOURCE
  2646. SCESTATUS_INVALID_PARAMETER
  2647. SCESTATUS_BAD_FORMAT
  2648. SCESTATUS_INVALID_DATA
  2649. -- */
  2650. {
  2651. //
  2652. // not support area
  2653. // if need this area later, refer to usersav directory for archived code
  2654. //
  2655. return(SCESTATUS_SERVICE_NOT_SUPPORT);
  2656. }
  2657. SCESTATUS
  2658. ScepGetObjectChildren(
  2659. IN PSCECONTEXT hProfile,
  2660. IN SCETYPE ProfileType,
  2661. IN AREA_INFORMATION Area,
  2662. IN PWSTR ObjectPrefix,
  2663. IN SCE_SUBOBJECT_TYPE Option,
  2664. OUT PVOID *Buffer,
  2665. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2666. )
  2667. /*
  2668. Routine Description
  2669. This routine is the same as ScepGetObjectChildrenFromOneTable, except when
  2670. ProfileType is SCE_ENGINE_SAP, in which case, object children in SMP is also
  2671. looked up and returned so the returned list contains the complete set of
  2672. the objects analyzed.
  2673. Arguments:
  2674. See ScepGetObjectChildrenFromOneTable
  2675. Return Value:
  2676. See ScepGetObjectChildrenFromOneTable
  2677. */
  2678. {
  2679. SCESTATUS rc;
  2680. rc = ScepGetObjectChildrenFromOneTable(
  2681. hProfile,
  2682. ProfileType,
  2683. Area,
  2684. ObjectPrefix,
  2685. Option,
  2686. Buffer,
  2687. Errlog
  2688. );
  2689. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2690. rc = SCESTATUS_SUCCESS;
  2691. }
  2692. if ( rc == SCESTATUS_SERVICE_NOT_SUPPORT &&
  2693. ProfileType == SCE_ENGINE_SAP &&
  2694. Option == SCE_IMMEDIATE_CHILDREN ) {
  2695. return( SCESTATUS_RECORD_NOT_FOUND); // no acl support, do not allow children
  2696. }
  2697. if ( rc == SCESTATUS_SUCCESS &&
  2698. ProfileType == SCE_ENGINE_SAP &&
  2699. Option == SCE_IMMEDIATE_CHILDREN ) {
  2700. PSCE_OBJECT_CHILDREN pTempList=NULL;
  2701. PSCE_OBJECT_CHILDREN_NODE *pArrObject=NULL;
  2702. DWORD arrCount=0, MaxCount=0;
  2703. LONG FindIndex;
  2704. if ( *Buffer ) {
  2705. arrCount = ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount;
  2706. MaxCount = ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount;
  2707. pArrObject = &(((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject);
  2708. }
  2709. //
  2710. // get object children from SMP table too
  2711. //
  2712. rc = ScepGetObjectChildrenFromOneTable(
  2713. hProfile,
  2714. SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
  2715. Area,
  2716. ObjectPrefix,
  2717. Option,
  2718. (PVOID *)(&pTempList),
  2719. Errlog
  2720. );
  2721. if ( rc == SCESTATUS_SUCCESS && pTempList ) {
  2722. //
  2723. // add non-exist nodes to Buffer
  2724. //
  2725. DWORD i;
  2726. PSCE_OBJECT_CHILDREN_NODE *pTmpObject= &(pTempList->arrObject);
  2727. for ( i=0; i<pTempList->nCount; i++ ) {
  2728. //
  2729. // if this node does not exist in the SAP
  2730. // this node is analyzed with "match" status and
  2731. // no bad children under the node
  2732. // duplication is prevented by the last argument
  2733. //
  2734. if ( pTmpObject[i] == NULL ||
  2735. pTmpObject[i]->Name == NULL ) {
  2736. continue;
  2737. }
  2738. FindIndex = -1;
  2739. pTmpObject[i]->Status = SCE_STATUS_GOOD;
  2740. rc = ScepAddItemToChildren(
  2741. pTmpObject[i],
  2742. pTmpObject[i]->Name,
  2743. 0,
  2744. pTmpObject[i]->IsContainer,
  2745. pTmpObject[i]->Status,
  2746. pTmpObject[i]->Count,
  2747. &pArrObject,
  2748. &arrCount,
  2749. &MaxCount,
  2750. &FindIndex
  2751. );
  2752. if ( rc == ERROR_SUCCESS ) {
  2753. //
  2754. // successfully added
  2755. //
  2756. pTmpObject[i] = NULL;
  2757. } else if ( rc == ERROR_DUP_NAME ) {
  2758. //
  2759. // node already exist, ignore the error
  2760. //
  2761. rc = ERROR_SUCCESS;
  2762. } else {
  2763. ScepBuildErrorLogInfo( rc,
  2764. Errlog,
  2765. SCEERR_ADD,
  2766. pTmpObject[i]->Name
  2767. );
  2768. //
  2769. // only the following two errors could be returned
  2770. //
  2771. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  2772. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2773. break;
  2774. } else
  2775. rc = SCESTATUS_INVALID_PARAMETER;
  2776. }
  2777. }
  2778. } else if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  2779. rc = SCESTATUS_SUCCESS;
  2780. }
  2781. if ( pTempList ) {
  2782. ScepFreeObjectChildren(pTempList);
  2783. }
  2784. if ( rc == SCESTATUS_SUCCESS ) {
  2785. //
  2786. // detect if status of this container or any of its "immediate" parent
  2787. // is in "auto-inherit" status. If so, query from the system to
  2788. // get good items.
  2789. //
  2790. BYTE ParentStatus = ScepGetObjectStatusFlag(
  2791. hProfile,
  2792. SCE_ENGINE_SCP, //SCE_ENGINE_SMP,
  2793. Area,
  2794. ObjectPrefix,
  2795. TRUE);
  2796. BYTE AnalysisStatus = ScepGetObjectStatusFlag(
  2797. hProfile,
  2798. SCE_ENGINE_SAP,
  2799. Area,
  2800. ObjectPrefix,
  2801. FALSE);
  2802. //
  2803. // compute the status to be used for all enumerated objects
  2804. //
  2805. BYTE NewStatus;
  2806. if ( AnalysisStatus == SCE_STATUS_ERROR_NOT_AVAILABLE ||
  2807. AnalysisStatus == SCE_STATUS_NOT_ANALYZED ) {
  2808. NewStatus = SCE_STATUS_NOT_ANALYZED;
  2809. } else if ( ParentStatus == SCE_STATUS_OVERWRITE ) {
  2810. NewStatus = SCE_STATUS_GOOD;
  2811. } else {
  2812. NewStatus = SCE_STATUS_NOT_CONFIGURED;
  2813. }
  2814. //
  2815. // even though there is no parent in SMP, still return all objects
  2816. //
  2817. // if ( (BYTE)-1 != ParentStatus ) {
  2818. // if any child is found for this level
  2819. // get the remaining "good" status nodes from system
  2820. //
  2821. PWSTR WildCard=NULL;
  2822. DWORD BufSize;
  2823. switch ( Area ) {
  2824. case AREA_FILE_SECURITY:
  2825. struct _wfinddata_t FileInfo;
  2826. intptr_t hFile;
  2827. BOOL BackSlashExist;
  2828. BufSize = wcslen(ObjectPrefix)+4;
  2829. WildCard = (PWSTR)ScepAlloc( 0, (BufSize+1)*sizeof(WCHAR));
  2830. if ( !WildCard ) {
  2831. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2832. break;
  2833. }
  2834. BackSlashExist = ScepLastBackSlash(ObjectPrefix);
  2835. if ( BackSlashExist )
  2836. swprintf(WildCard, L"%s*.*", ObjectPrefix);
  2837. else
  2838. swprintf(WildCard, L"%s\\*.*", ObjectPrefix);
  2839. hFile = _wfindfirst(WildCard, &FileInfo);
  2840. ScepFree(WildCard);
  2841. WildCard = NULL;
  2842. if ( hFile != -1 &&
  2843. ( 0 == ( GetFileAttributes(ObjectPrefix) & // bug 635098: don't propagate permissions
  2844. FILE_ATTRIBUTE_REPARSE_POINT ))) // across junction points
  2845. {
  2846. do {
  2847. if ( wcscmp(L"..", FileInfo.name) == 0 ||
  2848. wcscmp(L".", FileInfo.name) == 0 )
  2849. continue;
  2850. FindIndex = -1;
  2851. rc = ScepAddItemToChildren(
  2852. NULL,
  2853. FileInfo.name,
  2854. 0,
  2855. (FileInfo.attrib & _A_SUBDIR) ? TRUE : FALSE,
  2856. NewStatus,
  2857. 0,
  2858. &pArrObject,
  2859. &arrCount,
  2860. &MaxCount,
  2861. &FindIndex
  2862. );
  2863. if ( rc == ERROR_DUP_NAME ) {
  2864. rc = ERROR_SUCCESS;
  2865. } else if ( rc != ERROR_SUCCESS ) {
  2866. ScepBuildErrorLogInfo( rc,
  2867. Errlog,
  2868. SCEERR_ADD,
  2869. FileInfo.name
  2870. );
  2871. //
  2872. // only the following two errors could be returned
  2873. //
  2874. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  2875. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2876. break;
  2877. } else
  2878. rc = SCESTATUS_INVALID_PARAMETER;
  2879. }
  2880. } while ( _wfindnext(hFile, &FileInfo) == 0 );
  2881. _findclose(hFile);
  2882. }
  2883. break;
  2884. case AREA_REGISTRY_SECURITY:
  2885. HKEY hKey;
  2886. DWORD index;
  2887. DWORD EnumRc;
  2888. //
  2889. // open the key (on a 64-bit platform, 64-bit
  2890. // registry only will be done if SCE_ENGINE_SAP)
  2891. //
  2892. rc = ScepOpenRegistryObject(
  2893. SE_REGISTRY_KEY,
  2894. ObjectPrefix,
  2895. KEY_READ,
  2896. &hKey
  2897. );
  2898. if ( rc == ERROR_SUCCESS ) {
  2899. index = 0;
  2900. //
  2901. // enumerate all subkeys of the key
  2902. //
  2903. do {
  2904. WildCard = (PWSTR)ScepAlloc(LMEM_ZEROINIT, MAX_PATH*sizeof(WCHAR));
  2905. if ( WildCard == NULL ) {
  2906. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2907. break;
  2908. }
  2909. BufSize = MAX_PATH;
  2910. EnumRc = RegEnumKeyEx(hKey,
  2911. index,
  2912. WildCard,
  2913. &BufSize,
  2914. NULL,
  2915. NULL,
  2916. NULL,
  2917. NULL);
  2918. if ( EnumRc == ERROR_SUCCESS ) {
  2919. index++;
  2920. //
  2921. // add the name to the object list
  2922. //
  2923. FindIndex = -1;
  2924. rc = ScepAddItemToChildren(
  2925. NULL,
  2926. WildCard,
  2927. BufSize,
  2928. TRUE,
  2929. NewStatus,
  2930. 0,
  2931. &pArrObject,
  2932. &arrCount,
  2933. &MaxCount,
  2934. &FindIndex
  2935. );
  2936. if ( rc == ERROR_DUP_NAME ) {
  2937. rc = ERROR_SUCCESS;
  2938. } else if ( rc != ERROR_SUCCESS ) {
  2939. ScepBuildErrorLogInfo( rc,
  2940. Errlog,
  2941. SCEERR_ADD,
  2942. WildCard
  2943. );
  2944. //
  2945. // only the following two errors could be returned
  2946. //
  2947. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  2948. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2949. break;
  2950. } else
  2951. rc = SCESTATUS_INVALID_PARAMETER;
  2952. }
  2953. }
  2954. ScepFree(WildCard);
  2955. WildCard = NULL;
  2956. } while ( EnumRc != ERROR_NO_MORE_ITEMS );
  2957. RegCloseKey(hKey);
  2958. } else {
  2959. rc = ScepDosErrorToSceStatus(rc);
  2960. }
  2961. break;
  2962. #if 0
  2963. case AREA_DS_OBJECTS:
  2964. PSCE_NAME_LIST pTemp, pList=NULL;
  2965. rc = ScepLdapOpen(NULL);
  2966. if ( rc == SCESTATUS_SUCCESS ) {
  2967. //
  2968. // detect if the Ds object exist
  2969. //
  2970. rc = ScepDsObjectExist(ObjectPrefix);
  2971. if ( rc == SCESTATUS_SUCCESS ) {
  2972. rc = ScepEnumerateDsOneLevel(ObjectPrefix, &pList);
  2973. //
  2974. // add each one to the object list
  2975. //
  2976. for (pTemp=pList; pTemp != NULL; pTemp = pTemp->Next ) {
  2977. //
  2978. // look for the first ldap component
  2979. //
  2980. WildCard = wcschr(pTemp->Name, L',');
  2981. if ( WildCard ) {
  2982. BufSize = (DWORD)(WildCard - pTemp->Name);
  2983. } else {
  2984. BufSize = 0;
  2985. }
  2986. rc = ScepAddItemToChildren(
  2987. NULL,
  2988. pTemp->Name,
  2989. BufSize,
  2990. TRUE,
  2991. NewStatus,
  2992. 0,
  2993. &pArrObject,
  2994. &arrCount,
  2995. &MaxCount,
  2996. &FindIndex
  2997. );
  2998. if ( rc != ERROR_SUCCESS ) {
  2999. ScepBuildErrorLogInfo( rc,
  3000. Errlog,
  3001. SCEERR_ADD,
  3002. pTemp->Name
  3003. );
  3004. //
  3005. // only the following two errors could be returned
  3006. //
  3007. if ( rc == ERROR_NOT_ENOUGH_MEMORY ) {
  3008. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3009. break;
  3010. } else
  3011. rc = SCESTATUS_INVALID_PARAMETER;
  3012. }
  3013. }
  3014. if ( pList ) {
  3015. //
  3016. // free the list
  3017. //
  3018. ScepFreeNameList(pList);
  3019. }
  3020. }
  3021. ScepLdapClose(NULL);
  3022. }
  3023. break;
  3024. #endif
  3025. }
  3026. //
  3027. // ignore other errors except out of memory
  3028. //
  3029. if ( rc != SCESTATUS_NOT_ENOUGH_RESOURCE ) {
  3030. rc = SCESTATUS_SUCCESS;
  3031. }
  3032. // }
  3033. }
  3034. /*
  3035. if ( *Buffer ) {
  3036. ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
  3037. ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
  3038. ((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject = pArrObject;
  3039. }
  3040. */
  3041. if ( pArrObject ) {
  3042. *Buffer = (PVOID)((PBYTE)pArrObject - 2*sizeof(DWORD));
  3043. ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
  3044. ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
  3045. }
  3046. if ( rc != SCESTATUS_SUCCESS ) {
  3047. //
  3048. // free Buffer
  3049. //
  3050. ScepFreeObjectChildren((PSCE_OBJECT_CHILDREN)(*Buffer));
  3051. *Buffer = NULL;
  3052. }
  3053. }
  3054. if ( (SCESTATUS_SUCCESS == rc) &&
  3055. (*Buffer == NULL) ) {
  3056. //
  3057. // get nothing
  3058. //
  3059. rc = SCESTATUS_RECORD_NOT_FOUND;
  3060. }
  3061. return(rc);
  3062. }
  3063. BYTE
  3064. ScepGetObjectStatusFlag(
  3065. IN PSCECONTEXT hProfile,
  3066. IN SCETYPE ProfileType,
  3067. IN AREA_INFORMATION Area,
  3068. IN PWSTR ObjectPrefix,
  3069. IN BOOL bLookForParent
  3070. )
  3071. /*
  3072. Routine Description:
  3073. To find the status for the closest parent node (immediate/non immediate)
  3074. for the Object in the table.
  3075. Arguments:
  3076. hProfile - the databaes handle
  3077. ProfileType - the table type
  3078. Area - the area information
  3079. ObjectPrefix - the object's full name
  3080. Return Value:
  3081. Byte - the status flag for the nearest parent if one is found
  3082. */
  3083. {
  3084. LPCTSTR SectionName;
  3085. PSCESECTION hSection=NULL;
  3086. WCHAR Delim;
  3087. BYTE Status=(BYTE)-1;
  3088. SCESTATUS rc;
  3089. PWSTR JetName=NULL;
  3090. switch ( Area) {
  3091. case AREA_FILE_SECURITY:
  3092. SectionName = szFileSecurity;
  3093. JetName = ObjectPrefix;
  3094. Delim = L'\\';
  3095. break;
  3096. case AREA_REGISTRY_SECURITY:
  3097. SectionName = szRegistryKeys;
  3098. JetName = ObjectPrefix;
  3099. Delim = L'\\';
  3100. break;
  3101. #if 0
  3102. case AREA_DS_OBJECTS:
  3103. SectionName = szDSSecurity;
  3104. Delim = L',';
  3105. rc = ScepConvertLdapToJetIndexName(
  3106. ObjectPrefix,
  3107. &JetName
  3108. );
  3109. if ( rc != SCESTATUS_SUCCESS ) {
  3110. return (BYTE)-1;
  3111. }
  3112. break;
  3113. #endif
  3114. default:
  3115. return (BYTE)-1;
  3116. }
  3117. rc = ScepOpenSectionForName(
  3118. hProfile,
  3119. ProfileType,
  3120. SectionName,
  3121. &hSection
  3122. );
  3123. if ( SCESTATUS_SUCCESS == rc ) {
  3124. Status = ScepGetObjectAnalysisStatus(hSection,
  3125. JetName,
  3126. bLookForParent
  3127. );
  3128. }
  3129. SceJetCloseSection(&hSection, TRUE);
  3130. if ( JetName != ObjectPrefix ) {
  3131. ScepFree(JetName);
  3132. }
  3133. if ( SCESTATUS_SUCCESS == rc ) {
  3134. return Status;
  3135. }
  3136. return (BYTE)-1;
  3137. }
  3138. SCESTATUS
  3139. ScepGetObjectChildrenFromOneTable(
  3140. IN PSCECONTEXT hProfile,
  3141. IN SCETYPE ProfileType,
  3142. IN AREA_INFORMATION Area,
  3143. IN PWSTR ObjectPrefix,
  3144. IN SCE_SUBOBJECT_TYPE Option,
  3145. OUT PVOID *Buffer,
  3146. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  3147. )
  3148. /* ++
  3149. Routine Description:
  3150. This routine is used for Registry and File Security ONLY.
  3151. This routine takes a object prefix ( e.g., a parent nodes full path name)
  3152. and outputs all files and sub directories under the object, or the immediate
  3153. children under the object, based on Option. When all files and sub
  3154. directories are outputted, the output information is in a n-tree structure
  3155. (SCE_OBJECT_TREE). If only the immediate children are outputted, the
  3156. output information is in a list structure (SCE_OBJECT_CHILDREN). The output buffer
  3157. must be freed by LocalFree after its use.
  3158. Arguments:
  3159. hProfile - The handle to the profile
  3160. ProifleType - The type of the profile to read
  3161. Area - The security area to read info
  3162. AREA_REGISTRY_SECURITY
  3163. AREA_FILE_SECURITY
  3164. ObjectPrefix- The parent nodes full path name (e.g., c:\winnt)
  3165. Option - The option for output information. Valid values are
  3166. SCE_ALL_CHILDREN
  3167. SCE_IMMEDIATE_CHILDREN
  3168. Buffer - The output buffer.
  3169. Errlog - The error log buffer.
  3170. Return Value:
  3171. SCESTATUS_SUCCESS
  3172. SCESTATUS_PROFILE_NOT_FOUND
  3173. SCESTATUS_NOT_ENOUGH_RESOURCE
  3174. SCESTATUS_INVALID_PARAMETER
  3175. SCESTATUS_BAD_FORMAT
  3176. SCESTATUS_INVALID_DATA
  3177. -- */
  3178. {
  3179. SCESTATUS rc = SCESTATUS_SUCCESS;
  3180. PCWSTR SectionName=NULL;
  3181. PWSTR JetName;
  3182. WCHAR Delim=L'\\';
  3183. if ( ObjectPrefix == NULL || ObjectPrefix[0] == L'\0' )
  3184. return(SCESTATUS_INVALID_PARAMETER);
  3185. if ( Option == SCE_ALL_CHILDREN &&
  3186. ProfileType == SCE_ENGINE_SAP )
  3187. return(SCESTATUS_INVALID_PARAMETER);
  3188. switch (Area) {
  3189. case AREA_REGISTRY_SECURITY:
  3190. SectionName = szRegistryKeys;
  3191. JetName = ObjectPrefix;
  3192. break;
  3193. case AREA_FILE_SECURITY:
  3194. SectionName = szFileSecurity;
  3195. JetName = ObjectPrefix;
  3196. break;
  3197. #if 0
  3198. case AREA_DS_OBJECTS:
  3199. SectionName = szDSSecurity;
  3200. Delim = L',';
  3201. rc = ScepConvertLdapToJetIndexName(
  3202. ObjectPrefix,
  3203. &JetName
  3204. );
  3205. if ( rc != SCESTATUS_SUCCESS )
  3206. return(rc);
  3207. *Buffer = NULL;
  3208. break;
  3209. #endif
  3210. default:
  3211. return(SCESTATUS_INVALID_PARAMETER);
  3212. }
  3213. DWORD PrefixLen;
  3214. PWSTR NewPrefix;
  3215. PWSTR ObjectName=NULL;
  3216. PWSTR Value=NULL;
  3217. DWORD ObjectLen, ValueLen;
  3218. PWSTR Buffer1=NULL;
  3219. //
  3220. // make a new prefix to force a Delim at the end
  3221. //
  3222. PrefixLen = wcslen(JetName);
  3223. if ( Option != SCE_ALL_CHILDREN ) {
  3224. if ( JetName[PrefixLen-1] != Delim )
  3225. PrefixLen++;
  3226. NewPrefix = (PWSTR)ScepAlloc(0, (PrefixLen+1)*sizeof(WCHAR));
  3227. if ( NewPrefix == NULL ) {
  3228. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3229. } else {
  3230. wcscpy(NewPrefix, JetName);
  3231. NewPrefix[PrefixLen-1] = Delim;
  3232. NewPrefix[PrefixLen] = L'\0';
  3233. }
  3234. } else
  3235. NewPrefix = JetName;
  3236. if ( rc != SCESTATUS_SUCCESS ) {
  3237. if ( Area == AREA_DS_OBJECTS )
  3238. ScepFree(JetName);
  3239. return(rc);
  3240. }
  3241. PSCESECTION hSection=NULL;
  3242. DWORD i;
  3243. PSCE_OBJECT_CHILDREN_NODE *pArrObject=NULL;
  3244. DWORD arrCount=0;
  3245. DWORD MaxCount=0;
  3246. LONG LastIndex=-1;
  3247. LONG FindIndex=-1;
  3248. //
  3249. // open the section
  3250. //
  3251. rc = ScepOpenSectionForName(
  3252. hProfile,
  3253. ProfileType,
  3254. SectionName,
  3255. &hSection
  3256. );
  3257. if ( rc == SCESTATUS_SUCCESS ) {
  3258. if ( ProfileType == SCE_ENGINE_SAP &&
  3259. Option != SCE_ALL_CHILDREN &&
  3260. PrefixLen > 2 ) {
  3261. //
  3262. // find if this drive support ACL
  3263. //
  3264. WCHAR StatusFlag=L'\0';
  3265. WCHAR SaveChr = NewPrefix[3];
  3266. NewPrefix[3] = L'\0';
  3267. rc = SceJetGetValue(
  3268. hSection,
  3269. SCEJET_EXACT_MATCH_NO_CASE,
  3270. NewPrefix,
  3271. NULL,
  3272. 0,
  3273. NULL,
  3274. (PWSTR)&StatusFlag, // two bytes buffer
  3275. 2,
  3276. &i
  3277. );
  3278. NewPrefix[3] = SaveChr;
  3279. if ( SCESTATUS_SUCCESS == rc ||
  3280. SCESTATUS_BUFFER_TOO_SMALL == rc ) {
  3281. i = *((BYTE *)&StatusFlag);
  3282. if ( i == (BYTE)SCE_STATUS_NO_ACL_SUPPORT ||
  3283. i == (DWORD)SCE_STATUS_NO_ACL_SUPPORT ) {
  3284. rc = SCESTATUS_SERVICE_NOT_SUPPORT;
  3285. } else {
  3286. rc = SCESTATUS_SUCCESS;
  3287. }
  3288. } else {
  3289. rc = SCESTATUS_SUCCESS;
  3290. }
  3291. }
  3292. } else {
  3293. ScepBuildErrorLogInfo( ERROR_INVALID_HANDLE,
  3294. Errlog,
  3295. SCEERR_OPEN,
  3296. SectionName
  3297. );
  3298. }
  3299. if ( rc == SCESTATUS_SUCCESS ) {
  3300. DWORD Level;
  3301. PWSTR pTemp;
  3302. DWORD SDsize=0;
  3303. pTemp = wcschr(JetName, Delim);
  3304. Level=1;
  3305. while ( pTemp ) {
  3306. pTemp++;
  3307. if ( pTemp[0] != 0 )
  3308. Level++;
  3309. pTemp = wcschr(pTemp, Delim);
  3310. }
  3311. Level++;
  3312. if ( Option == SCE_ALL_CHILDREN ) {
  3313. //
  3314. // find the first record in the section
  3315. //
  3316. rc = SceJetGetValue(
  3317. hSection,
  3318. SCEJET_PREFIX_MATCH_NO_CASE,
  3319. JetName,
  3320. NULL,
  3321. 0,
  3322. &SDsize, // temp use for ObjectLen,
  3323. NULL,
  3324. 0,
  3325. &i // temp use for ValueLen
  3326. );
  3327. } else {
  3328. //
  3329. // find the first record matching prefix in the section
  3330. //
  3331. rc = SceJetSeek(
  3332. hSection,
  3333. NewPrefix,
  3334. PrefixLen*sizeof(TCHAR),
  3335. SCEJET_SEEK_GE_NO_CASE
  3336. );
  3337. if ( rc == SCESTATUS_SUCCESS ) {
  3338. //
  3339. // start the Ldap server
  3340. //
  3341. if ( Area == AREA_DS_OBJECTS) {
  3342. rc = ScepLdapOpen(NULL);
  3343. if ( rc != SCESTATUS_SUCCESS ) {
  3344. ScepBuildErrorLogInfo( 0,
  3345. Errlog,
  3346. SCEERR_CONVERT_LDAP,
  3347. L""
  3348. );
  3349. }
  3350. }
  3351. if ( rc == SCESTATUS_SUCCESS ) {
  3352. rc = SceJetGetValue(
  3353. hSection,
  3354. SCEJET_CURRENT,
  3355. NULL,
  3356. NULL,
  3357. 0,
  3358. &SDsize, // temp use for ObjectLen,
  3359. NULL,
  3360. 0,
  3361. &i // temp use for ValueLen
  3362. );
  3363. }
  3364. }
  3365. }
  3366. DWORD Count=0;
  3367. BYTE Status;
  3368. BOOL IsContainer;
  3369. SCEJET_FIND_TYPE FindFlag;
  3370. while ( rc == SCESTATUS_SUCCESS ) {
  3371. //
  3372. // allocate memory for the group name and value string
  3373. //
  3374. ObjectName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, SDsize+2); // ObjectLen
  3375. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, i+2); //ValueLen
  3376. if ( ObjectName == NULL || Value == NULL ) {
  3377. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3378. goto Done;
  3379. }
  3380. //
  3381. // Get the group and its value
  3382. //
  3383. rc = SceJetGetValue(
  3384. hSection,
  3385. SCEJET_CURRENT,
  3386. NULL,
  3387. ObjectName,
  3388. SDsize,
  3389. &ObjectLen,
  3390. Value,
  3391. i,
  3392. &ValueLen
  3393. );
  3394. if ( rc != SCESTATUS_SUCCESS ) {
  3395. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  3396. Errlog,
  3397. SCEERR_QUERY_VALUE,
  3398. SectionName
  3399. );
  3400. goto Done;
  3401. }
  3402. //
  3403. // teminate the string
  3404. //
  3405. if ( ObjectLen > SDsize )
  3406. ObjectLen = SDsize;
  3407. if ( ValueLen > i )
  3408. ValueLen = i;
  3409. ObjectName[ObjectLen/2] = L'\0';
  3410. Value[ValueLen/2] = L'\0';
  3411. if ( Option == SCE_ALL_CHILDREN ) {
  3412. //
  3413. // add this object to the object tree
  3414. //
  3415. PSECURITY_DESCRIPTOR pTempSD=NULL;
  3416. SECURITY_INFORMATION SeInfo;
  3417. //
  3418. // use i temperatorily
  3419. //
  3420. i = ConvertTextSecurityDescriptor(
  3421. Value+1,
  3422. &pTempSD,
  3423. &SDsize,
  3424. &SeInfo
  3425. );
  3426. if ( i == NO_ERROR ) {
  3427. if ( Area != AREA_DS_OBJECTS ) {
  3428. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  3429. }
  3430. Status = *((BYTE *)Value);
  3431. IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
  3432. if ( Area == AREA_DS_OBJECTS && *Buffer == NULL ) {
  3433. //
  3434. // build the first node separately because the first node
  3435. // is always the domain name with its DNS name as full name
  3436. //
  3437. rc = ScepBuildDsTree(
  3438. (PSCE_OBJECT_CHILD_LIST *)Buffer,
  3439. Level-1,
  3440. Delim,
  3441. JetName
  3442. );
  3443. if ( rc == SCESTATUS_SUCCESS ) {
  3444. if ( _wcsicmp(ObjectName, JetName) == 0 ) {
  3445. //
  3446. // exact match
  3447. //
  3448. (*((PSCE_OBJECT_TREE *)Buffer))->IsContainer = IsContainer;
  3449. (*((PSCE_OBJECT_TREE *)Buffer))->Status = Status;
  3450. (*((PSCE_OBJECT_TREE *)Buffer))->pSecurityDescriptor = pTempSD;
  3451. (*((PSCE_OBJECT_TREE *)Buffer))->SeInfo = SeInfo;
  3452. } else {
  3453. rc = ScepBuildObjectTree(
  3454. NULL,
  3455. (PSCE_OBJECT_CHILD_LIST *)Buffer,
  3456. Level-1,
  3457. Delim,
  3458. ObjectName,
  3459. IsContainer,
  3460. Status,
  3461. pTempSD,
  3462. SeInfo
  3463. );
  3464. }
  3465. }
  3466. } else {
  3467. rc = ScepBuildObjectTree(
  3468. NULL,
  3469. (PSCE_OBJECT_CHILD_LIST *)Buffer,
  3470. (Area == AREA_DS_OBJECTS) ? Level : 1,
  3471. Delim,
  3472. ObjectName,
  3473. IsContainer,
  3474. Status,
  3475. pTempSD,
  3476. SeInfo
  3477. );
  3478. }
  3479. if ( rc != SCESTATUS_SUCCESS ) {
  3480. ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc),
  3481. Errlog,
  3482. SCEERR_BUILD_OBJECT
  3483. );
  3484. ScepFree(pTempSD);
  3485. }
  3486. } else {
  3487. ScepBuildErrorLogInfo( i,
  3488. Errlog,
  3489. SCEERR_BUILD_SD,
  3490. ObjectName // Value+1
  3491. );
  3492. rc = ScepDosErrorToSceStatus(i);
  3493. }
  3494. FindFlag = SCEJET_NEXT_LINE;
  3495. } else {
  3496. INT CompFlag;
  3497. DWORD ListHeadLen;
  3498. // verify it is within the right range
  3499. CompFlag = _wcsnicmp(ObjectName, NewPrefix, PrefixLen);
  3500. if ( pArrObject != NULL && LastIndex >= 0 && LastIndex < (LONG)arrCount ) {
  3501. ListHeadLen = wcslen(pArrObject[LastIndex]->Name);
  3502. } else
  3503. ListHeadLen = 0;
  3504. if ( (CompFlag == 0 && PrefixLen == ObjectLen/2) ||
  3505. CompFlag < 0 ) {
  3506. // CompFlag < 0 should be impossible!!!
  3507. // if it is the exact match with ObjectPrefix, ignore
  3508. //
  3509. // Every next level node is returned in the ObjectList
  3510. // with either
  3511. // Count=0 ( no sub children ), or
  3512. // Count > 0 && Status=SCE_STATUS_GOOD (this one is good)
  3513. // Status=mismatch/unknown/ignore/check
  3514. // should not count the object itself
  3515. //
  3516. rc = SceJetMoveNext(hSection);
  3517. } else if (CompFlag > 0 ) {
  3518. rc = SCESTATUS_RECORD_NOT_FOUND;
  3519. } else if (pArrObject != NULL && LastIndex >= 0 && LastIndex < (LONG)arrCount &&
  3520. PrefixLen+ListHeadLen < ObjectLen/2 &&
  3521. ObjectName[PrefixLen+ListHeadLen] == Delim &&
  3522. _wcsnicmp( pArrObject[LastIndex]->Name, ObjectName+PrefixLen,
  3523. ListHeadLen ) == 0 ) {
  3524. //
  3525. // if the list is not NULL, check the list head (new added item)
  3526. // to see if the ObjectName is already in. If yes, skip
  3527. //
  3528. Buffer1 = (PWSTR)ScepAlloc(0, (ListHeadLen+PrefixLen+2)*sizeof(WCHAR));
  3529. if ( Buffer1 == NULL ) {
  3530. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3531. } else {
  3532. swprintf(Buffer1, L"%s%s", NewPrefix, pArrObject[LastIndex]->Name);
  3533. Buffer1[PrefixLen+ListHeadLen] = (WCHAR) (Delim + 1);
  3534. Buffer1[PrefixLen+ListHeadLen+1] = L'\0';
  3535. //
  3536. // skip the block
  3537. //
  3538. rc = SceJetSeek(
  3539. hSection,
  3540. Buffer1,
  3541. (PrefixLen+ListHeadLen+1)*sizeof(TCHAR),
  3542. SCEJET_SEEK_GE_DONT_CARE //SCEJET_SEEK_GE_NO_CASE
  3543. );
  3544. ScepFree(Buffer1);
  3545. Buffer1 = NULL;
  3546. }
  3547. } else {
  3548. DWORD Len;
  3549. BOOL LastOne;
  3550. //
  3551. // searching for the right level component
  3552. //
  3553. PWSTR pStart = ObjectName;
  3554. for ( i=0; i<Level; i++) {
  3555. pTemp = wcschr(pStart, Delim);
  3556. if ( i == Level-1 ) {
  3557. //
  3558. // find the right level
  3559. //
  3560. if ( pTemp == NULL ) {
  3561. LastOne = TRUE;
  3562. Len = ObjectLen/2; // wcslen(pStart); from begining
  3563. } else {
  3564. Len = (DWORD)(pTemp - ObjectName); // pStart; from begining
  3565. if ( *(pTemp+1) == L'\0' )
  3566. LastOne = TRUE;
  3567. else
  3568. LastOne = FALSE;
  3569. }
  3570. SDsize = (DWORD)(pStart - ObjectName);
  3571. } else {
  3572. if ( pTemp == NULL ) {
  3573. rc = SCESTATUS_INVALID_PARAMETER;
  3574. break;
  3575. } else
  3576. pStart = pTemp + 1;
  3577. }
  3578. }
  3579. if ( rc == SCESTATUS_SUCCESS && Len > SDsize ) {
  3580. Buffer1 = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (Len+1)*sizeof(WCHAR));
  3581. if ( Buffer1 == NULL )
  3582. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3583. else {
  3584. // wcsncpy(Buffer1, pStart, Len );
  3585. wcsncpy(Buffer1, ObjectName, Len);
  3586. Count = 1;
  3587. if ( LastOne ) {
  3588. Count = 0;
  3589. Status = *((BYTE *)Value);
  3590. IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
  3591. } else {
  3592. IsContainer = TRUE;
  3593. if ( ProfileType == SCE_ENGINE_SAP )
  3594. Status = SCE_STATUS_GOOD;
  3595. else
  3596. Status = SCE_STATUS_CHECK;
  3597. }
  3598. }
  3599. }
  3600. if ( rc != SCESTATUS_SUCCESS ) {
  3601. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  3602. Errlog,
  3603. SCEERR_PROCESS_OBJECT,
  3604. ObjectName
  3605. );
  3606. } else if ( Buffer1 != NULL) {
  3607. //
  3608. // check to see if Buffer1 is already in the list
  3609. //
  3610. i=0; // temp. use of i for skip flag
  3611. if ( pArrObject && LastIndex >= 0 && LastIndex < (LONG)arrCount ) {
  3612. if ( ScepSearchItemInChildren(Buffer1+SDsize,
  3613. Len-SDsize,
  3614. pArrObject,
  3615. arrCount,
  3616. &FindIndex
  3617. )
  3618. ) {
  3619. //
  3620. // Buffer1 is already in the list, skip the block
  3621. // use pStart temporarily
  3622. //
  3623. pStart = (PWSTR)ScepAlloc(0, (Len+2)*sizeof(WCHAR));
  3624. if ( pStart == NULL ) {
  3625. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3626. } else {
  3627. //
  3628. // skip the block
  3629. //
  3630. wcscpy(pStart, Buffer1);
  3631. pStart[Len] = (WCHAR) ( Delim+1);
  3632. pStart[Len+1] = L'\0';
  3633. rc = SceJetSeek(
  3634. hSection,
  3635. pStart,
  3636. (Len+1)*sizeof(TCHAR),
  3637. SCEJET_SEEK_GE_DONT_CARE //cannot use GT cause it will skip the section
  3638. );
  3639. ScepFree(pStart);
  3640. pStart = NULL;
  3641. i=1;
  3642. LastIndex = FindIndex;
  3643. }
  3644. }
  3645. }
  3646. if ( 0 == i && SCESTATUS_SUCCESS == rc ) {
  3647. //
  3648. // get count
  3649. //
  3650. pStart = (PWSTR)ScepAlloc(0, (Len+2)*sizeof(WCHAR));
  3651. if ( pStart == NULL ) {
  3652. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3653. } else {
  3654. wcscpy(pStart, Buffer1);
  3655. pStart[Len] = Delim;
  3656. pStart[Len+1] = L'\0';
  3657. rc = SceJetGetLineCount(
  3658. hSection,
  3659. pStart,
  3660. FALSE,
  3661. &Count);
  3662. if ( rc == SCESTATUS_SUCCESS ||
  3663. rc == SCESTATUS_RECORD_NOT_FOUND ) {
  3664. if ( !IsContainer && Count > 0 ) {
  3665. IsContainer = TRUE;
  3666. }
  3667. //
  3668. // make buffer1 approprate case
  3669. //
  3670. switch (Area) {
  3671. case AREA_REGISTRY_SECURITY:
  3672. rc = ScepGetRegKeyCase(Buffer1, SDsize, Len-SDsize);
  3673. break;
  3674. case AREA_FILE_SECURITY:
  3675. rc = ScepGetFileCase(Buffer1, SDsize, Len-SDsize);
  3676. break;
  3677. case AREA_DS_OBJECTS:
  3678. //
  3679. // need convert name first from o=,dc=,cn= to cn=,dc=,o=
  3680. //
  3681. pTemp=NULL;
  3682. rc = ScepConvertJetNameToLdapCase(
  3683. Buffer1,
  3684. TRUE, // Last component only
  3685. SCE_CASE_PREFERED, // right case
  3686. &pTemp
  3687. );
  3688. if ( rc != ERROR_FILE_NOT_FOUND && pTemp != NULL ) {
  3689. rc = ScepAddItemToChildren(NULL,
  3690. pTemp,
  3691. wcslen(pTemp),
  3692. IsContainer,
  3693. Status,
  3694. Count,
  3695. &pArrObject,
  3696. &arrCount,
  3697. &MaxCount,
  3698. &FindIndex
  3699. );
  3700. if ( rc != ERROR_SUCCESS ) {
  3701. ScepBuildErrorLogInfo( rc,
  3702. Errlog,
  3703. SCEERR_ADD,
  3704. pTemp
  3705. );
  3706. } else {
  3707. LastIndex = FindIndex;
  3708. }
  3709. ScepFree(pTemp);
  3710. pTemp = NULL;
  3711. }
  3712. rc = ScepDosErrorToSceStatus(rc);
  3713. break;
  3714. }
  3715. /*
  3716. if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
  3717. //
  3718. // if the object does not exist, do not add
  3719. //
  3720. rc = SCESTATUS_SUCCESS;
  3721. } else if ( Area != AREA_DS_OBJECTS ) {
  3722. */
  3723. if ( rc != SCESTATUS_PROFILE_NOT_FOUND &&
  3724. Area != AREA_DS_OBJECTS ) {
  3725. rc = ScepAddItemToChildren(NULL,
  3726. Buffer1+SDsize,
  3727. Len-SDsize,
  3728. IsContainer,
  3729. Status,
  3730. Count,
  3731. &pArrObject,
  3732. &arrCount,
  3733. &MaxCount,
  3734. &FindIndex
  3735. );
  3736. if ( rc != ERROR_SUCCESS ) {
  3737. ScepBuildErrorLogInfo( rc,
  3738. Errlog,
  3739. SCEERR_ADD,
  3740. Buffer1
  3741. );
  3742. rc = ScepDosErrorToSceStatus(rc);
  3743. } else {
  3744. LastIndex = FindIndex;
  3745. }
  3746. }
  3747. }
  3748. if ( rc == SCESTATUS_SUCCESS ) {
  3749. //
  3750. // seek to the original one
  3751. //
  3752. // Buffer1[Len-1] = (WCHAR) (Buffer1[Len-1] + 1);
  3753. rc = SceJetSeek(
  3754. hSection,
  3755. Buffer1,
  3756. Len*sizeof(TCHAR),
  3757. SCEJET_SEEK_GE_NO_CASE
  3758. );
  3759. //
  3760. // should be success, move to next line
  3761. //
  3762. rc = SceJetMoveNext(hSection);
  3763. } else if ( rc == SCESTATUS_PROFILE_NOT_FOUND ) {
  3764. pStart[Len] = (WCHAR) ( Delim+1);
  3765. pStart[Len+1] = L'\0';
  3766. rc = SceJetSeek(
  3767. hSection,
  3768. pStart,
  3769. (Len+1)*sizeof(TCHAR),
  3770. SCEJET_SEEK_GE_DONT_CARE //cannot use GT cause it will skip the section
  3771. );
  3772. }
  3773. ScepFree(pStart);
  3774. pStart = NULL;
  3775. }
  3776. }
  3777. ScepFree(Buffer1);
  3778. Buffer1 = NULL;
  3779. } else
  3780. rc = SceJetMoveNext(hSection);
  3781. }
  3782. FindFlag = SCEJET_CURRENT;
  3783. }
  3784. ScepFree(ObjectName);
  3785. ObjectName = NULL;
  3786. ScepFree(Value);
  3787. Value = NULL;
  3788. if ( rc != SCESTATUS_SUCCESS )
  3789. break;
  3790. //
  3791. // read next line
  3792. //
  3793. rc = SceJetGetValue(
  3794. hSection,
  3795. FindFlag,
  3796. NULL,
  3797. NULL,
  3798. 0,
  3799. &SDsize, // temp use for ObjectLen
  3800. NULL,
  3801. 0,
  3802. &i // temp use for ValueLen
  3803. );
  3804. }
  3805. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  3806. rc = SCESTATUS_SUCCESS;
  3807. }
  3808. Done:
  3809. if ( Area == AREA_DS_OBJECTS ) {
  3810. if ( Area == AREA_DS_OBJECTS ) {
  3811. if ( JetName != NULL )
  3812. ScepFree(JetName);
  3813. }
  3814. ScepLdapClose(NULL);
  3815. }
  3816. if ( Option != SCE_ALL_CHILDREN ) {
  3817. ScepFree(NewPrefix);
  3818. }
  3819. if ( Buffer1 != NULL )
  3820. ScepFree(Buffer1);
  3821. if ( ObjectName != NULL )
  3822. ScepFree(ObjectName);
  3823. if ( Value != NULL )
  3824. ScepFree(Value);
  3825. //
  3826. // close the find index range
  3827. //
  3828. SceJetGetValue(
  3829. hSection,
  3830. SCEJET_CLOSE_VALUE,
  3831. NULL,
  3832. NULL,
  3833. 0,
  3834. NULL,
  3835. NULL,
  3836. 0,
  3837. NULL
  3838. );
  3839. SceJetCloseSection( &hSection, TRUE);
  3840. if ( ( rc == SCESTATUS_SUCCESS ) &&
  3841. ( Option != SCE_ALL_CHILDREN ) ) {
  3842. if ( pArrObject ) {
  3843. *Buffer = (PVOID)((PBYTE)pArrObject-sizeof(DWORD)*2);
  3844. ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
  3845. ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
  3846. } else {
  3847. *Buffer = NULL;
  3848. }
  3849. /*
  3850. *Buffer = ScepAlloc(0, sizeof(SCE_OBJECT_CHILDREN));
  3851. if ( *Buffer ) {
  3852. ((PSCE_OBJECT_CHILDREN)(*Buffer))->nCount = arrCount;
  3853. ((PSCE_OBJECT_CHILDREN)(*Buffer))->MaxCount = MaxCount;
  3854. ((PSCE_OBJECT_CHILDREN)(*Buffer))->arrObject = pArrObject;
  3855. } else {
  3856. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3857. }
  3858. */
  3859. }
  3860. if ( rc != SCESTATUS_SUCCESS ) {
  3861. //
  3862. // free (PVOID *)Buffer
  3863. //
  3864. if ( Option == SCE_ALL_CHILDREN ) {
  3865. // OBJECT_CHILD_LIST structure
  3866. ScepFreeObject2Security((PSCE_OBJECT_CHILD_LIST)(*Buffer), FALSE);
  3867. } else if ( pArrObject ) {
  3868. // OBJECT_CHILDREN structure
  3869. ScepFreeObjectChildren((PSCE_OBJECT_CHILDREN)((PBYTE)pArrObject-sizeof(DWORD)*2));
  3870. }
  3871. *Buffer = NULL;
  3872. }
  3873. return(rc);
  3874. }
  3875. SCESTATUS
  3876. ScepBuildDsTree(
  3877. OUT PSCE_OBJECT_CHILD_LIST *TreeRoot,
  3878. IN ULONG Level,
  3879. IN WCHAR Delim,
  3880. IN PCWSTR ObjectFullName
  3881. )
  3882. {
  3883. TCHAR Buffer[MAX_PATH];
  3884. BOOL LastOne=FALSE;
  3885. SCESTATUS rc;
  3886. if ( TreeRoot == NULL || ObjectFullName == NULL ) {
  3887. return(SCESTATUS_INVALID_PARAMETER);
  3888. }
  3889. memset(Buffer, '\0', MAX_PATH*sizeof(TCHAR));
  3890. rc = ScepGetNameInLevel(ObjectFullName,
  3891. Level,
  3892. Delim,
  3893. Buffer,
  3894. &LastOne);
  3895. if ( rc != SCESTATUS_SUCCESS )
  3896. return(rc);
  3897. *TreeRoot = (PSCE_OBJECT_CHILD_LIST)ScepAlloc(LPTR, sizeof(SCE_OBJECT_CHILD_LIST));
  3898. if ( *TreeRoot == NULL )
  3899. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3900. PSCE_OBJECT_TREE Node;
  3901. //
  3902. // allocate buffer for the node
  3903. //
  3904. Node = (PSCE_OBJECT_TREE)ScepAlloc((UINT)0, sizeof(SCE_OBJECT_TREE));
  3905. if ( Node == NULL ) {
  3906. ScepFree(*TreeRoot);
  3907. *TreeRoot = NULL;
  3908. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  3909. }
  3910. //
  3911. // allocate buffer for the object name
  3912. //
  3913. Node->Name = (PWSTR)ScepAlloc((UINT)0,
  3914. (wcslen(Buffer)+1) * sizeof(TCHAR));
  3915. if ( Node->Name != NULL ) {
  3916. Node->ObjectFullName = (PWSTR)ScepAlloc( 0, (wcslen(ObjectFullName)+1)*sizeof(TCHAR));
  3917. if ( Node->ObjectFullName != NULL ) {
  3918. //
  3919. // initialize
  3920. //
  3921. wcscpy(Node->Name, Buffer);
  3922. wcscpy(Node->ObjectFullName, ObjectFullName);
  3923. Node->ChildList = NULL;
  3924. Node->Parent = NULL;
  3925. Node->pApplySecurityDescriptor = NULL;
  3926. Node->pSecurityDescriptor = NULL;
  3927. Node->SeInfo = 0;
  3928. Node->IsContainer = TRUE;
  3929. Node->Status = SCE_STATUS_CHECK;
  3930. (*TreeRoot)->Node = Node;
  3931. } else {
  3932. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3933. ScepFree( Node->Name );
  3934. ScepFree( Node );
  3935. ScepFree( *TreeRoot );
  3936. *TreeRoot = NULL;
  3937. }
  3938. } else {
  3939. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  3940. ScepFree( Node );
  3941. ScepFree( *TreeRoot );
  3942. *TreeRoot = NULL;
  3943. }
  3944. return(rc);
  3945. }
  3946. SCESTATUS
  3947. ScepGetObjectSecurity(
  3948. IN PSCECONTEXT hProfile,
  3949. IN SCETYPE ProfileType,
  3950. IN AREA_INFORMATION Area,
  3951. IN PWSTR ObjectName,
  3952. OUT PSCE_OBJECT_SECURITY *ObjSecurity
  3953. )
  3954. /*
  3955. Get security for a single object
  3956. */
  3957. {
  3958. SCESTATUS rc;
  3959. PCWSTR SectionName=NULL;
  3960. PSCESECTION hSection=NULL;
  3961. PWSTR Value=NULL;
  3962. DWORD ValueLen;
  3963. PSECURITY_DESCRIPTOR pTempSD=NULL;
  3964. SECURITY_INFORMATION SeInfo;
  3965. DWORD SDsize, Win32Rc;
  3966. if ( hProfile == NULL || ObjectName == NULL ||
  3967. ObjSecurity == NULL ) {
  3968. return(SCESTATUS_INVALID_PARAMETER);
  3969. }
  3970. switch (Area) {
  3971. case AREA_REGISTRY_SECURITY:
  3972. SectionName = szRegistryKeys;
  3973. break;
  3974. case AREA_FILE_SECURITY:
  3975. SectionName = szFileSecurity;
  3976. break;
  3977. #if 0
  3978. case AREA_DS_OBJECTS:
  3979. SectionName = szDSSecurity;
  3980. break;
  3981. #endif
  3982. default:
  3983. return(SCESTATUS_INVALID_PARAMETER);
  3984. }
  3985. rc = ScepOpenSectionForName(
  3986. hProfile,
  3987. ProfileType,
  3988. SectionName,
  3989. &hSection
  3990. );
  3991. if ( rc == SCESTATUS_SUCCESS ) {
  3992. rc = SceJetGetValue(
  3993. hSection,
  3994. SCEJET_EXACT_MATCH_NO_CASE,
  3995. ObjectName,
  3996. NULL,
  3997. 0,
  3998. NULL,
  3999. NULL,
  4000. 0,
  4001. &ValueLen
  4002. );
  4003. if ( rc == SCESTATUS_SUCCESS ) {
  4004. //
  4005. // allocate memory for value string
  4006. //
  4007. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  4008. if ( Value == NULL ) {
  4009. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4010. goto Done;
  4011. }
  4012. //
  4013. // Get the value
  4014. //
  4015. rc = SceJetGetValue(
  4016. hSection,
  4017. SCEJET_CURRENT,
  4018. NULL,
  4019. NULL,
  4020. 0,
  4021. NULL,
  4022. Value,
  4023. ValueLen,
  4024. &ValueLen
  4025. );
  4026. if ( rc == SCESTATUS_SUCCESS ) {
  4027. //
  4028. // convert security descriptor
  4029. //
  4030. Win32Rc = ConvertTextSecurityDescriptor(
  4031. Value+1,
  4032. &pTempSD,
  4033. &SDsize,
  4034. &SeInfo
  4035. );
  4036. if ( Win32Rc == NO_ERROR ) {
  4037. if ( Area != AREA_DS_OBJECTS ) {
  4038. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  4039. }
  4040. //
  4041. // allocate output buffer (SCE_OBJECT_SECURITY)
  4042. //
  4043. *ObjSecurity = (PSCE_OBJECT_SECURITY)ScepAlloc(0, sizeof(SCE_OBJECT_SECURITY));
  4044. if ( *ObjSecurity == NULL ) {
  4045. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4046. goto Done;
  4047. }
  4048. (*ObjSecurity)->Name = (PWSTR)ScepAlloc(0, (wcslen(ObjectName)+1)*sizeof(TCHAR));
  4049. if ( (*ObjSecurity)->Name == NULL ) {
  4050. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4051. ScepFree(*ObjSecurity);
  4052. *ObjSecurity = NULL;
  4053. goto Done;
  4054. }
  4055. /*
  4056. (*ObjSecurity)->SDspec = (PWSTR)ScepAlloc(0, ValueLen);
  4057. if ( (*ObjSecurity)->SDspec == NULL ) {
  4058. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4059. ScepFree((*ObjSecurity)->Name);
  4060. ScepFree(*ObjSecurity);
  4061. *ObjSecurity = NULL;
  4062. goto Done;
  4063. }
  4064. */
  4065. //
  4066. // build the structure
  4067. //
  4068. (*ObjSecurity)->Status = *((BYTE *)Value);
  4069. (*ObjSecurity)->IsContainer = *((CHAR *)Value+1) != '0' ? TRUE : FALSE;
  4070. wcscpy( (*ObjSecurity)->Name, ObjectName);
  4071. (*ObjSecurity)->pSecurityDescriptor = pTempSD;
  4072. pTempSD = NULL;
  4073. (*ObjSecurity)->SeInfo = SeInfo;
  4074. // wcscpy( (*ObjSecurity)->SDspec, Value+1);
  4075. // (*ObjSecurity)->SDsize = ValueLen/2-1;
  4076. } else
  4077. rc = ScepDosErrorToSceStatus(Win32Rc);
  4078. }
  4079. }
  4080. }
  4081. Done:
  4082. SceJetCloseSection( &hSection, TRUE);
  4083. if ( pTempSD )
  4084. ScepFree(pTempSD);
  4085. if ( Value )
  4086. ScepFree(Value);
  4087. return(rc);
  4088. }
  4089. SCESTATUS
  4090. ScepGetSystemServices(
  4091. IN PSCECONTEXT hProfile,
  4092. IN SCETYPE ProfileType,
  4093. OUT PSCE_SERVICES *pServiceList,
  4094. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  4095. )
  4096. /*
  4097. Routine Description:
  4098. Read all services defined in the Jet table into the service list
  4099. Arguments:
  4100. hProfile - the jet profile handle
  4101. ProfileType - The table to read from
  4102. SCE_ENGINE_SCP
  4103. SCE_ENGINE_SAP
  4104. SCE_ENGINE_SMP
  4105. pServiceList - The service list to output
  4106. Errlog - the error messages to output
  4107. Return Value:
  4108. SCESTATUS_SUCCESS
  4109. SCESTATUS error codes
  4110. */
  4111. {
  4112. SCESTATUS rc;
  4113. DWORD Win32Rc;
  4114. PSCESECTION hSection=NULL;
  4115. DWORD ServiceLen=0, ValueLen=0;
  4116. PWSTR ServiceName=NULL,
  4117. Value=NULL;
  4118. PSECURITY_DESCRIPTOR pTempSD=NULL;
  4119. SECURITY_INFORMATION SeInfo;
  4120. DWORD SDsize;
  4121. PSCE_SERVICES ServiceNode;
  4122. PSCE_SERVICES pServices=NULL, pNode, pParent;
  4123. if ( hProfile == NULL ||
  4124. pServiceList == NULL ) {
  4125. return(SCESTATUS_INVALID_PARAMETER);
  4126. }
  4127. //
  4128. // open the section
  4129. //
  4130. rc = ScepOpenSectionForName(
  4131. hProfile,
  4132. ProfileType,
  4133. szServiceGeneral,
  4134. &hSection
  4135. );
  4136. if ( rc == SCESTATUS_RECORD_NOT_FOUND ) {
  4137. return(SCESTATUS_SUCCESS);
  4138. }
  4139. if ( rc != SCESTATUS_SUCCESS ) {
  4140. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  4141. Errlog,
  4142. SCEERR_OPEN,
  4143. szServiceGeneral
  4144. );
  4145. return(rc);
  4146. }
  4147. //
  4148. // enumerate all service names from the system.
  4149. // do not care the error code
  4150. //
  4151. SceEnumerateServices(&pServices, TRUE);
  4152. //
  4153. // goto the first line of this section
  4154. //
  4155. rc = SceJetGetValue(
  4156. hSection,
  4157. SCEJET_PREFIX_MATCH,
  4158. NULL,
  4159. NULL,
  4160. 0,
  4161. &ServiceLen,
  4162. NULL,
  4163. 0,
  4164. &ValueLen
  4165. );
  4166. while ( rc == SCESTATUS_SUCCESS ) {
  4167. //
  4168. // allocate memory for the service name and value string
  4169. //
  4170. ServiceName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ServiceLen+2);
  4171. if ( ServiceName != NULL ) {
  4172. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  4173. if ( Value != NULL ) {
  4174. //
  4175. // Get the service and its value
  4176. //
  4177. rc = SceJetGetValue(
  4178. hSection,
  4179. SCEJET_CURRENT,
  4180. NULL,
  4181. ServiceName,
  4182. ServiceLen,
  4183. &ServiceLen,
  4184. Value,
  4185. ValueLen,
  4186. &ValueLen
  4187. );
  4188. if ( rc == SCESTATUS_SUCCESS ) {
  4189. ServiceName[ServiceLen/2] = L'\0';
  4190. Value[ValueLen/2] = L'\0';
  4191. #ifdef SCE_DBG
  4192. wprintf(L"rc=%d, service: %s=%s\n", rc, ServiceName, Value);
  4193. #endif
  4194. //
  4195. // convert to security descriptor
  4196. //
  4197. Win32Rc = ConvertTextSecurityDescriptor(
  4198. Value+1,
  4199. &pTempSD,
  4200. &SDsize,
  4201. &SeInfo
  4202. );
  4203. if ( Win32Rc == NO_ERROR ) {
  4204. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  4205. //
  4206. // create this service node
  4207. //
  4208. ServiceNode = (PSCE_SERVICES)ScepAlloc( LMEM_FIXED, sizeof(SCE_SERVICES) );
  4209. if ( ServiceNode != NULL ) {
  4210. //
  4211. // find the right name for the service
  4212. //
  4213. for ( pNode=pServices, pParent=NULL; pNode != NULL;
  4214. pParent=pNode, pNode=pNode->Next ) {
  4215. if ( _wcsicmp(pNode->ServiceName, ServiceName) == 0 ) {
  4216. break;
  4217. }
  4218. }
  4219. if ( pNode != NULL ) {
  4220. //
  4221. // got it
  4222. //
  4223. ServiceNode->ServiceName = pNode->ServiceName;
  4224. ServiceNode->DisplayName = pNode->DisplayName;
  4225. //
  4226. // free the node
  4227. //
  4228. if ( pParent != NULL ) {
  4229. pParent->Next = pNode->Next;
  4230. } else {
  4231. pServices = pNode->Next;
  4232. }
  4233. // General is NULL becuase the enumerate call asks only for names
  4234. ScepFree(pNode);
  4235. pNode = NULL;
  4236. } else {
  4237. //
  4238. // did not find it
  4239. //
  4240. ServiceNode->ServiceName = ServiceName;
  4241. ServiceNode->DisplayName = NULL;
  4242. ServiceName = NULL;
  4243. }
  4244. ServiceNode->Status = *((BYTE *)Value);
  4245. ServiceNode->Startup = *((BYTE *)Value+1);
  4246. ServiceNode->General.pSecurityDescriptor = pTempSD;
  4247. ServiceNode->SeInfo = SeInfo;
  4248. ServiceNode->Next = *pServiceList;
  4249. *pServiceList = ServiceNode;
  4250. //
  4251. // DO NOT free the following buffers
  4252. //
  4253. pTempSD = NULL;
  4254. } else {
  4255. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4256. ScepFree(pTempSD);
  4257. }
  4258. } else {
  4259. ScepBuildErrorLogInfo( Win32Rc,
  4260. Errlog,
  4261. SCEERR_BUILD_SD,
  4262. ServiceName
  4263. );
  4264. rc = ScepDosErrorToSceStatus(Win32Rc);
  4265. }
  4266. }
  4267. ScepFree(Value);
  4268. } else
  4269. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4270. //
  4271. // ServiceName could be used in the service node
  4272. //
  4273. if ( ServiceName )
  4274. ScepFree(ServiceName);
  4275. } else
  4276. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4277. if ( rc == SCESTATUS_SUCCESS ) {
  4278. //
  4279. // read next line
  4280. //
  4281. rc = SceJetGetValue(
  4282. hSection,
  4283. SCEJET_NEXT_LINE,
  4284. NULL,
  4285. NULL,
  4286. 0,
  4287. &ServiceLen,
  4288. NULL,
  4289. 0,
  4290. &ValueLen
  4291. );
  4292. }
  4293. }
  4294. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  4295. rc = SCESTATUS_SUCCESS;
  4296. //
  4297. // close the find index range
  4298. //
  4299. SceJetGetValue(
  4300. hSection,
  4301. SCEJET_CLOSE_VALUE,
  4302. NULL,
  4303. NULL,
  4304. 0,
  4305. NULL,
  4306. NULL,
  4307. 0,
  4308. NULL
  4309. );
  4310. //
  4311. // close the section
  4312. //
  4313. SceJetCloseSection( &hSection, TRUE );
  4314. if ( rc != SCESTATUS_SUCCESS ) {
  4315. //
  4316. // free the service list
  4317. //
  4318. SceFreePSCE_SERVICES(*pServiceList);
  4319. *pServiceList = NULL;
  4320. }
  4321. SceFreePSCE_SERVICES(pServices);
  4322. return(rc);
  4323. }
  4324. SCESTATUS
  4325. ScepCopyObjects(
  4326. IN PSCECONTEXT hProfile,
  4327. IN SCETYPE ProfileType,
  4328. IN PWSTR InfFile,
  4329. IN PCWSTR SectionName,
  4330. IN AREA_INFORMATION Area,
  4331. IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  4332. )
  4333. /* ++
  4334. Routine Description:
  4335. This routine copies registry/file/ds/service object in SMP table to the specified
  4336. inf template.
  4337. Arguments:
  4338. hProfile - The handle to the profile
  4339. InfFile - The INF template name
  4340. SectionName - the section name where data is stored
  4341. Area - The security area to read info
  4342. AREA_REGISTRY_SECURITY
  4343. AREA_FILE_SECURITY
  4344. AREA_DS_OBJECTS
  4345. Errlog - The error log buffer.
  4346. Return Value:
  4347. SCESTATUS_SUCCESS
  4348. SCESTATUS_PROFILE_NOT_FOUND
  4349. SCESTATUS_NOT_ENOUGH_RESOURCE
  4350. SCESTATUS_INVALID_PARAMETER
  4351. SCESTATUS_BAD_FORMAT
  4352. SCESTATUS_INVALID_DATA
  4353. -- */
  4354. {
  4355. SCESTATUS rc = SCESTATUS_SUCCESS;
  4356. PSCESECTION hSection=NULL;
  4357. PWSTR ObjectName=NULL;
  4358. PWSTR Value=NULL;
  4359. DWORD ObjectLen, ValueLen;
  4360. BYTE Status;
  4361. PWSTR NewValue=NULL;
  4362. DWORD Count=0;
  4363. WCHAR KeyName[10];
  4364. if ( InfFile == NULL || hProfile == NULL )
  4365. return(SCESTATUS_INVALID_PARAMETER);
  4366. //
  4367. // open the section
  4368. //
  4369. rc = ScepOpenSectionForName(
  4370. hProfile,
  4371. ProfileType,
  4372. SectionName,
  4373. &hSection
  4374. );
  4375. if ( rc == SCESTATUS_SUCCESS ) {
  4376. //
  4377. // empty the section first.
  4378. //
  4379. WritePrivateProfileSection(
  4380. SectionName,
  4381. NULL,
  4382. (LPCTSTR)InfFile);
  4383. //
  4384. // find the first record in the section
  4385. //
  4386. rc = SceJetGetValue(
  4387. hSection,
  4388. SCEJET_PREFIX_MATCH,
  4389. NULL,
  4390. NULL,
  4391. 0,
  4392. &ObjectLen,
  4393. NULL,
  4394. 0,
  4395. &ValueLen
  4396. );
  4397. while ( rc == SCESTATUS_SUCCESS ) {
  4398. Count++;
  4399. //
  4400. // allocate memory for the group name and value string
  4401. //
  4402. ObjectName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ObjectLen+2);
  4403. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  4404. if ( ObjectName == NULL || Value == NULL ) {
  4405. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4406. goto Done;
  4407. }
  4408. //
  4409. // Get the group and its value
  4410. //
  4411. rc = SceJetGetValue(
  4412. hSection,
  4413. SCEJET_CURRENT,
  4414. NULL,
  4415. ObjectName,
  4416. ObjectLen,
  4417. &ObjectLen,
  4418. Value,
  4419. ValueLen,
  4420. &ValueLen
  4421. );
  4422. if ( rc != SCESTATUS_SUCCESS ) {
  4423. ScepBuildErrorLogInfo( ERROR_READ_FAULT,
  4424. Errlog,
  4425. SCEERR_QUERY_VALUE,
  4426. SectionName
  4427. );
  4428. goto Done;
  4429. }
  4430. #ifdef SCE_DBG
  4431. wprintf(L"Addr: %x %x, %s=%s\n", ObjectName, Value, ObjectName, Value+1);
  4432. #endif
  4433. if ( Area == AREA_SYSTEM_SERVICE )
  4434. Status = *((BYTE *)Value+1);
  4435. else
  4436. Status = *((BYTE *)Value);
  4437. if (0 == _wcsicmp(SectionName, szRegistryKeys) &&
  4438. Status != 1 &&
  4439. 0 == _wcsnicmp(L"machine\\system\\controlset",
  4440. ObjectName,
  4441. wcslen(L"machine\\system\\controlset"))) {
  4442. ObjectName = ScepSpecialCaseRegkeyCcs( ObjectName );
  4443. if ( ObjectName == NULL ) {
  4444. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4445. goto Done;
  4446. }
  4447. }
  4448. NewValue = (PWSTR)ScepAlloc(0, ObjectLen+ValueLen+40);
  4449. if ( NewValue == NULL ) {
  4450. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4451. goto Done;
  4452. }
  4453. //
  4454. // to represent "not configured"
  4455. // 0 is used in the database
  4456. // "" is used in the inf template
  4457. // so just generate "" instead of "0"
  4458. //
  4459. if ( Area == AREA_SYSTEM_SERVICE && Status == 0 ){
  4460. swprintf(NewValue, L"\"%s\",, \"%s\"\0", ObjectName, Value+1);
  4461. }
  4462. else {
  4463. swprintf(NewValue, L"\"%s\", %d, \"%s\"\0", ObjectName, Status, Value+1);
  4464. }
  4465. swprintf(KeyName, L"%x\0", Count);
  4466. //
  4467. // write this line to the inf file
  4468. //
  4469. if ( !WritePrivateProfileString(
  4470. SectionName,
  4471. KeyName,
  4472. NewValue,
  4473. InfFile
  4474. ) ) {
  4475. ScepBuildErrorLogInfo( GetLastError(),
  4476. Errlog,
  4477. SCEERR_WRITE_INFO,
  4478. ObjectName
  4479. );
  4480. rc = ScepDosErrorToSceStatus(GetLastError());
  4481. }
  4482. ScepFree(ObjectName);
  4483. ObjectName = NULL;
  4484. ScepFree(Value);
  4485. Value = NULL;
  4486. ScepFree(NewValue);
  4487. NewValue = NULL;
  4488. if ( rc != SCESTATUS_SUCCESS )
  4489. break;
  4490. //
  4491. // read next line
  4492. //
  4493. rc = SceJetGetValue(
  4494. hSection,
  4495. SCEJET_NEXT_LINE,
  4496. NULL,
  4497. NULL,
  4498. 0,
  4499. &ObjectLen,
  4500. NULL,
  4501. 0,
  4502. &ValueLen
  4503. );
  4504. }
  4505. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  4506. rc = SCESTATUS_SUCCESS;
  4507. } else
  4508. ScepBuildErrorLogInfo( ERROR_INVALID_HANDLE,
  4509. Errlog,
  4510. SCEERR_OPEN,
  4511. SectionName
  4512. );
  4513. Done:
  4514. if ( ObjectName != NULL )
  4515. ScepFree(ObjectName);
  4516. if ( Value != NULL )
  4517. ScepFree(Value);
  4518. if ( NewValue != NULL )
  4519. ScepFree(NewValue);
  4520. //
  4521. // close the find index range
  4522. //
  4523. SceJetGetValue(
  4524. hSection,
  4525. SCEJET_CLOSE_VALUE,
  4526. NULL,
  4527. NULL,
  4528. 0,
  4529. NULL,
  4530. NULL,
  4531. 0,
  4532. NULL
  4533. );
  4534. SceJetCloseSection( &hSection, TRUE);
  4535. return(rc);
  4536. }
  4537. PWSTR
  4538. ScepSpecialCaseRegkeyCcs(
  4539. IN OUT PWSTR ObjectName
  4540. )
  4541. /* ++
  4542. Routine Description:
  4543. When Status != 1 convert all currentcontrolsetxxx's to currentcontrolset
  4544. Arguments:
  4545. ObjectName - name of registry key to modify
  4546. Return Value:
  4547. none
  4548. -- */
  4549. {
  4550. PWSTR pszNewObjectName = NULL;
  4551. DWORD dwCcsLen = wcslen(L"machine\\system\\controlset");
  4552. if (0 == _wcsnicmp(L"machine\\system\\controlset",
  4553. ObjectName,
  4554. dwCcsLen)) {
  4555. pszNewObjectName = (PWSTR)ScepAlloc(0,
  4556. (wcslen(ObjectName) + wcslen(L"current") + 3) * sizeof(WCHAR));
  4557. if (NULL == pszNewObjectName) {
  4558. goto Done;
  4559. }
  4560. pszNewObjectName[0] = L'\0';
  4561. wcscat(pszNewObjectName, L"machine\\system\\currentcontrolset");
  4562. wchar_t *pSlash = NULL;
  4563. pSlash = wcsstr(ObjectName + dwCcsLen, L"\\");
  4564. if (pSlash != NULL) {
  4565. wcscat(pszNewObjectName, pSlash);
  4566. }
  4567. }
  4568. Done:
  4569. ScepFree(ObjectName);
  4570. return pszNewObjectName;
  4571. }
  4572. SCESTATUS
  4573. ScepGetAnalysisSummary(
  4574. IN PSCECONTEXT Context,
  4575. IN AREA_INFORMATION Area,
  4576. OUT PDWORD pCount
  4577. )
  4578. {
  4579. SCESTATUS rc=SCESTATUS_INVALID_PARAMETER;
  4580. DWORD count;
  4581. DWORD total=0;
  4582. PSCESECTION hSection=NULL;
  4583. if ( Context == NULL || pCount == NULL )
  4584. return(SCESTATUS_INVALID_PARAMETER);
  4585. *pCount = 0;
  4586. if ( Area & AREA_SECURITY_POLICY ) {
  4587. //
  4588. // system access
  4589. //
  4590. rc = ScepOpenSectionForName(
  4591. Context,
  4592. SCE_ENGINE_SAP,
  4593. szSystemAccess,
  4594. &hSection
  4595. );
  4596. if ( rc == SCESTATUS_SUCCESS ) {
  4597. rc = SceJetGetLineCount(
  4598. hSection,
  4599. NULL,
  4600. FALSE,
  4601. &count
  4602. );
  4603. }
  4604. SceJetCloseSection( &hSection, TRUE);
  4605. if ( rc != SCESTATUS_SUCCESS )
  4606. return(rc);
  4607. total += count;
  4608. //
  4609. // System Log
  4610. //
  4611. rc = ScepOpenSectionForName(
  4612. Context,
  4613. SCE_ENGINE_SAP,
  4614. szAuditSystemLog,
  4615. &hSection
  4616. );
  4617. if ( rc == SCESTATUS_SUCCESS ) {
  4618. rc = SceJetGetLineCount(
  4619. hSection,
  4620. NULL,
  4621. FALSE,
  4622. &count
  4623. );
  4624. }
  4625. SceJetCloseSection( &hSection, TRUE);
  4626. if ( rc != SCESTATUS_SUCCESS )
  4627. return(rc);
  4628. total += count;
  4629. //
  4630. // Security Log
  4631. //
  4632. rc = ScepOpenSectionForName(
  4633. Context,
  4634. SCE_ENGINE_SAP,
  4635. szAuditSecurityLog,
  4636. &hSection
  4637. );
  4638. if ( rc == SCESTATUS_SUCCESS ) {
  4639. rc = SceJetGetLineCount(
  4640. hSection,
  4641. NULL,
  4642. FALSE,
  4643. &count
  4644. );
  4645. }
  4646. SceJetCloseSection( &hSection, TRUE);
  4647. if ( rc != SCESTATUS_SUCCESS )
  4648. return(rc);
  4649. total += count;
  4650. //
  4651. // Application Log
  4652. //
  4653. rc = ScepOpenSectionForName(
  4654. Context,
  4655. SCE_ENGINE_SAP,
  4656. szAuditApplicationLog,
  4657. &hSection
  4658. );
  4659. if ( rc == SCESTATUS_SUCCESS ) {
  4660. rc = SceJetGetLineCount(
  4661. hSection,
  4662. NULL,
  4663. FALSE,
  4664. &count
  4665. );
  4666. }
  4667. SceJetCloseSection( &hSection, TRUE);
  4668. if ( rc != SCESTATUS_SUCCESS )
  4669. return(rc);
  4670. total += count;
  4671. //
  4672. // Event Audit
  4673. //
  4674. rc = ScepOpenSectionForName(
  4675. Context,
  4676. SCE_ENGINE_SAP,
  4677. szAuditEvent,
  4678. &hSection
  4679. );
  4680. if ( rc == SCESTATUS_SUCCESS ) {
  4681. rc = SceJetGetLineCount(
  4682. hSection,
  4683. NULL,
  4684. FALSE,
  4685. &count
  4686. );
  4687. }
  4688. SceJetCloseSection( &hSection, TRUE);
  4689. if ( rc != SCESTATUS_SUCCESS )
  4690. return(rc);
  4691. total += count;
  4692. }
  4693. if ( Area & AREA_PRIVILEGES ) {
  4694. //
  4695. // Privileges
  4696. //
  4697. rc = ScepOpenSectionForName(
  4698. Context,
  4699. SCE_ENGINE_SAP,
  4700. szPrivilegeRights,
  4701. &hSection
  4702. );
  4703. if ( rc == SCESTATUS_SUCCESS ) {
  4704. rc = SceJetGetLineCount(
  4705. hSection,
  4706. NULL,
  4707. FALSE,
  4708. &count
  4709. );
  4710. }
  4711. SceJetCloseSection( &hSection, TRUE);
  4712. if ( rc != SCESTATUS_SUCCESS )
  4713. return(rc);
  4714. total += count;
  4715. }
  4716. if ( Area & AREA_GROUP_MEMBERSHIP) {
  4717. //
  4718. // Group Membership
  4719. //
  4720. rc = ScepOpenSectionForName(
  4721. Context,
  4722. SCE_ENGINE_SAP,
  4723. szGroupMembership,
  4724. &hSection
  4725. );
  4726. if ( rc == SCESTATUS_SUCCESS ) {
  4727. rc = SceJetGetLineCount(
  4728. hSection,
  4729. NULL,
  4730. FALSE,
  4731. &count
  4732. );
  4733. }
  4734. SceJetCloseSection( &hSection, TRUE);
  4735. if ( rc != SCESTATUS_SUCCESS )
  4736. return(rc);
  4737. total += count;
  4738. }
  4739. if ( Area & AREA_SYSTEM_SERVICE ) {
  4740. //
  4741. // system service
  4742. //
  4743. rc = ScepOpenSectionForName(
  4744. Context,
  4745. SCE_ENGINE_SAP,
  4746. szServiceGeneral,
  4747. &hSection
  4748. );
  4749. if ( rc == SCESTATUS_SUCCESS ) {
  4750. rc = SceJetGetLineCount(
  4751. hSection,
  4752. NULL,
  4753. FALSE,
  4754. &count
  4755. );
  4756. }
  4757. SceJetCloseSection( &hSection, TRUE);
  4758. if ( rc != SCESTATUS_SUCCESS )
  4759. return(rc);
  4760. total += count;
  4761. }
  4762. if ( Area & AREA_REGISTRY_SECURITY ) {
  4763. //
  4764. // Registry security
  4765. //
  4766. rc = ScepOpenSectionForName(
  4767. Context,
  4768. SCE_ENGINE_SAP,
  4769. szRegistryKeys,
  4770. &hSection
  4771. );
  4772. if ( rc == SCESTATUS_SUCCESS ) {
  4773. rc = SceJetGetLineCount(
  4774. hSection,
  4775. NULL,
  4776. FALSE,
  4777. &count
  4778. );
  4779. }
  4780. SceJetCloseSection( &hSection, TRUE);
  4781. if ( rc != SCESTATUS_SUCCESS )
  4782. return(rc);
  4783. total += count;
  4784. }
  4785. if ( Area & AREA_FILE_SECURITY ) {
  4786. //
  4787. // File Security
  4788. //
  4789. rc = ScepOpenSectionForName(
  4790. Context,
  4791. SCE_ENGINE_SAP,
  4792. szFileSecurity,
  4793. &hSection
  4794. );
  4795. if ( rc == SCESTATUS_SUCCESS ) {
  4796. rc = SceJetGetLineCount(
  4797. hSection,
  4798. NULL,
  4799. FALSE,
  4800. &count
  4801. );
  4802. }
  4803. SceJetCloseSection( &hSection, TRUE);
  4804. if ( rc != SCESTATUS_SUCCESS )
  4805. return(rc);
  4806. total += count;
  4807. }
  4808. #if 0
  4809. #if _WIN32_WINNT>=0x0500
  4810. if ( Area & AREA_DS_OBJECTS &&
  4811. RtlGetNtProductType(&theType) ) {
  4812. if ( theType == NtProductLanManNt ) {
  4813. //
  4814. // DS object security
  4815. //
  4816. rc = ScepOpenSectionForName(
  4817. Context,
  4818. SCE_ENGINE_SAP,
  4819. szDSSecurity,
  4820. &hSection
  4821. );
  4822. if ( rc == SCESTATUS_SUCCESS ) {
  4823. rc = SceJetGetLineCount(
  4824. hSection,
  4825. NULL,
  4826. FALSE,
  4827. &count
  4828. );
  4829. }
  4830. SceJetCloseSection( &hSection, TRUE);
  4831. if ( rc != SCESTATUS_SUCCESS )
  4832. return(rc);
  4833. total += count;
  4834. }
  4835. }
  4836. #endif
  4837. #endif
  4838. *pCount = total;
  4839. return(rc);
  4840. }
  4841. SCESTATUS
  4842. ScepBrowseTableSection(
  4843. IN PSCECONTEXT hProfile,
  4844. IN SCETYPE ProfileType,
  4845. IN PCWSTR SectionName,
  4846. IN DWORD Options
  4847. )
  4848. {
  4849. SCESTATUS rc;
  4850. PSCESECTION hSection=NULL;
  4851. SceClientBrowseCallback(
  4852. 0,
  4853. (PWSTR)SectionName,
  4854. NULL,
  4855. NULL
  4856. );
  4857. rc = ScepOpenSectionForName(
  4858. hProfile,
  4859. ProfileType,
  4860. SectionName,
  4861. &hSection
  4862. );
  4863. if ( rc != SCESTATUS_SUCCESS ) {
  4864. return(rc);
  4865. }
  4866. JET_ERR JetErr;
  4867. //
  4868. // goto the first line of this section
  4869. //
  4870. DWORD KeyLen, ValueLen, Actual;
  4871. LONG GpoID=0;
  4872. PWSTR KeyName=NULL;
  4873. PWSTR Value=NULL;
  4874. TCHAR GpoName[MAX_PATH];
  4875. SCE_BROWSE_CALLBACK_VALUE ValBuf;
  4876. ValBuf.Len = 0;
  4877. ValBuf.Value = NULL;
  4878. rc = SceJetGetValue(
  4879. hSection,
  4880. SCEJET_PREFIX_MATCH,
  4881. NULL,
  4882. NULL,
  4883. 0,
  4884. &KeyLen,
  4885. NULL,
  4886. 0,
  4887. &ValueLen
  4888. );
  4889. while ( rc == SCESTATUS_SUCCESS ) {
  4890. //
  4891. // get GPO ID field from the current line
  4892. //
  4893. GpoID = 0;
  4894. if ( hSection->JetColumnGpoID > 0 ) {
  4895. JetErr = JetRetrieveColumn(
  4896. hSection->JetSessionID,
  4897. hSection->JetTableID,
  4898. hSection->JetColumnGpoID,
  4899. (void *)&GpoID,
  4900. 4,
  4901. &Actual,
  4902. 0,
  4903. NULL
  4904. );
  4905. }
  4906. if ( (Options & SCEBROWSE_DOMAIN_POLICY) &&
  4907. (GpoID <= 0) ) {
  4908. //
  4909. // do not need this line, continue to next line
  4910. //
  4911. } else {
  4912. KeyName = (PWSTR)ScepAlloc(LMEM_ZEROINIT, KeyLen+2);
  4913. //
  4914. // allocate memory for the group name and value string
  4915. //
  4916. Value = (PWSTR)ScepAlloc( LMEM_ZEROINIT, ValueLen+2);
  4917. if ( KeyName == NULL || Value == NULL ) {
  4918. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4919. goto Done;
  4920. }
  4921. //
  4922. // Get the key and value
  4923. //
  4924. DWORD NewKeyLen, NewValueLen;
  4925. rc = SceJetGetValue(
  4926. hSection,
  4927. SCEJET_CURRENT,
  4928. NULL,
  4929. KeyName,
  4930. KeyLen,
  4931. &NewKeyLen,
  4932. Value,
  4933. ValueLen,
  4934. &NewValueLen
  4935. );
  4936. if ( rc != SCESTATUS_SUCCESS )
  4937. goto Done;
  4938. //
  4939. // terminate the string
  4940. //
  4941. KeyName[KeyLen/2] = L'\0';
  4942. Value[ValueLen/2] = L'\0';
  4943. GpoName[0] = L'\0';
  4944. if ( hSection->JetColumnGpoID > 0 && GpoID > 0 ) {
  4945. Actual = MAX_PATH;
  4946. SceJetGetGpoNameByID(
  4947. hProfile,
  4948. GpoID,
  4949. GpoName,
  4950. &Actual,
  4951. NULL,
  4952. NULL
  4953. );
  4954. }
  4955. if ( Value && Value[0] != L'\0' &&
  4956. ( Options & SCEBROWSE_MULTI_SZ) ) {
  4957. if (0 == _wcsicmp( KeyName, szLegalNoticeTextKeyName) ) {
  4958. //
  4959. // check for commas and escape them with ","
  4960. // k=7,a",",b,c
  4961. // pValueStr will be a,\0b\0c\0\0 which we should make
  4962. // a","\0b\0c\0\0
  4963. //
  4964. DWORD dwCommaCount = 0;
  4965. for ( DWORD dwIndex = 1; dwIndex < ValueLen/2 ; dwIndex++) {
  4966. if ( Value[dwIndex] == L',' )
  4967. dwCommaCount++;
  4968. }
  4969. if ( dwCommaCount > 0 ) {
  4970. //
  4971. // in this case we have to escape commas
  4972. //
  4973. PWSTR pszValueEscaped;
  4974. DWORD dwBytes = (ValueLen/2 + 1 + (dwCommaCount*2))*sizeof(WCHAR);
  4975. pszValueEscaped = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwBytes);
  4976. if (pszValueEscaped) {
  4977. memset(pszValueEscaped, '\0', dwBytes);
  4978. ValueLen = 2 * ScepEscapeString(Value,
  4979. ValueLen/2,
  4980. L',',
  4981. L'"',
  4982. pszValueEscaped
  4983. );
  4984. ScepFree(Value);
  4985. Value = pszValueEscaped;
  4986. } else {
  4987. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  4988. goto Done;
  4989. }
  4990. }
  4991. }
  4992. ScepConvertMultiSzToDelim(Value+1, ValueLen/2-1, L'\0', L',');
  4993. }
  4994. __try {
  4995. ValBuf.Len = Value ? (ValueLen+2) : 0 ;
  4996. ValBuf.Value = (UCHAR *)Value;
  4997. SceClientBrowseCallback(
  4998. GpoID,
  4999. KeyName,
  5000. GpoName,
  5001. (SCEPR_SR_SECURITY_DESCRIPTOR *)&ValBuf
  5002. );
  5003. } __except(EXCEPTION_EXECUTE_HANDLER) {
  5004. }
  5005. ScepFree(Value);
  5006. Value = NULL;
  5007. ScepFree(KeyName);
  5008. KeyName = NULL;
  5009. }
  5010. //
  5011. // read next line
  5012. //
  5013. rc = SceJetGetValue(
  5014. hSection,
  5015. SCEJET_NEXT_LINE,
  5016. NULL,
  5017. NULL,
  5018. 0,
  5019. &KeyLen,
  5020. NULL,
  5021. 0,
  5022. &ValueLen
  5023. );
  5024. }
  5025. if ( rc == SCESTATUS_RECORD_NOT_FOUND )
  5026. rc = SCESTATUS_SUCCESS;
  5027. Done:
  5028. //
  5029. // close the find index range
  5030. //
  5031. SceJetGetValue(
  5032. hSection,
  5033. SCEJET_CLOSE_VALUE,
  5034. NULL,
  5035. NULL,
  5036. 0,
  5037. NULL,
  5038. NULL,
  5039. 0,
  5040. NULL
  5041. );
  5042. if ( Value != NULL )
  5043. ScepFree(Value);
  5044. if ( KeyName != NULL )
  5045. ScepFree(KeyName);
  5046. //
  5047. // close the section
  5048. //
  5049. SceJetCloseSection( &hSection, TRUE );
  5050. return(rc);
  5051. }
  5052. BOOL
  5053. ScepSearchItemInChildren(
  5054. IN PWSTR ItemName,
  5055. IN DWORD NameLen,
  5056. IN PSCE_OBJECT_CHILDREN_NODE *pArrObject,
  5057. IN DWORD arrCount,
  5058. OUT LONG *pFindIndex
  5059. )
  5060. /*
  5061. Routine Description:
  5062. Search the item name in the array specified. If found, the index to the
  5063. array is returned in pFindIndex.
  5064. Return Value:
  5065. TRUE - find it
  5066. FALSE - doesn't find it
  5067. */
  5068. {
  5069. if ( pFindIndex == NULL ) {
  5070. return(FALSE);
  5071. }
  5072. //
  5073. // note pFindIndex stores the closest node, not necessary mean
  5074. // the index is the match.
  5075. //
  5076. *pFindIndex = -1;
  5077. if ( ItemName == NULL ||
  5078. pArrObject == NULL ||
  5079. arrCount == 0 ) {
  5080. return(FALSE);
  5081. }
  5082. DWORD idxStart=0;
  5083. DWORD idxEnd=arrCount-1;
  5084. DWORD theIndex;
  5085. INT CompFlag=-1;
  5086. do {
  5087. //
  5088. // choose the middle
  5089. //
  5090. theIndex = (idxStart + idxEnd)/2;
  5091. if ( pArrObject[theIndex] == NULL ||
  5092. pArrObject[theIndex]->Name == NULL ) {
  5093. //
  5094. // this is a bad node, check the start node
  5095. //
  5096. while ( (pArrObject[idxStart] == NULL ||
  5097. pArrObject[idxStart]->Name == NULL) &&
  5098. idxStart <= idxEnd ) {
  5099. idxStart++;
  5100. }
  5101. if ( idxStart <= idxEnd ) {
  5102. //
  5103. // check the start node
  5104. //
  5105. CompFlag = _wcsicmp(ItemName, pArrObject[idxStart]->Name);
  5106. *pFindIndex = idxStart;
  5107. if ( CompFlag == 0 ) {
  5108. // find it
  5109. break;
  5110. } else if ( CompFlag < 0 ) {
  5111. //
  5112. // the item is less than idxStart - no match
  5113. //
  5114. break;
  5115. } else {
  5116. //
  5117. // the item is between theStart and idxEnd
  5118. //
  5119. if ( idxStart == idxEnd ) {
  5120. // empty now. quit
  5121. break;
  5122. } else {
  5123. idxStart++;
  5124. }
  5125. }
  5126. }
  5127. } else {
  5128. CompFlag = _wcsicmp(ItemName, pArrObject[theIndex]->Name);
  5129. *pFindIndex = theIndex;
  5130. if ( CompFlag == 0 ) {
  5131. // find it
  5132. break;
  5133. } else if ( CompFlag < 0 ) {
  5134. //
  5135. // the item is between index idxStart and theIndex
  5136. //
  5137. if ( theIndex == idxStart ) {
  5138. // empty now. quit
  5139. break;
  5140. } else {
  5141. idxEnd = theIndex-1;
  5142. }
  5143. } else {
  5144. //
  5145. // the item is between theIndex and idxEnd
  5146. //
  5147. if ( theIndex == idxEnd ) {
  5148. // empty now. quit
  5149. break;
  5150. } else {
  5151. idxStart = theIndex+1;
  5152. }
  5153. }
  5154. }
  5155. } while ( idxStart <= idxEnd );
  5156. if ( CompFlag == 0 ) {
  5157. return(TRUE);
  5158. } else {
  5159. return(FALSE);
  5160. }
  5161. }
  5162. DWORD
  5163. ScepAddItemToChildren(
  5164. IN PSCE_OBJECT_CHILDREN_NODE ThisNode OPTIONAL,
  5165. IN PWSTR ItemName,
  5166. IN DWORD NameLen,
  5167. IN BOOL IsContainer,
  5168. IN BYTE Status,
  5169. IN DWORD ChildCount,
  5170. IN OUT PSCE_OBJECT_CHILDREN_NODE **ppArrObject,
  5171. IN OUT DWORD *pArrCount,
  5172. IN OUT DWORD *pMaxCount,
  5173. IN OUT LONG *pFindIndex
  5174. )
  5175. /*
  5176. Routine Description:
  5177. Add a node to the children array. If the node is allocated, the pointer
  5178. will be added to the array; otherwise, a new allocation is made for the
  5179. new node.
  5180. The node's name will be first checked in the array for duplicate. If
  5181. pFindIndex is specified (not -1), the index will be first used to locate
  5182. the node. If the new node's name is found in the array, it won't be
  5183. added.
  5184. Return Value:
  5185. ERROR_DUP_NAME duplicate node name is found, node is not added to the array
  5186. ERROR_SUCCESS succeed
  5187. other errors
  5188. */
  5189. {
  5190. if ( ItemName == NULL ||
  5191. ppArrObject == NULL ||
  5192. pArrCount == NULL ||
  5193. pMaxCount == NULL ||
  5194. pFindIndex == NULL ) {
  5195. return(ERROR_INVALID_PARAMETER);
  5196. }
  5197. DWORD rc=ERROR_SUCCESS;
  5198. if ( *ppArrObject == NULL ||
  5199. *pArrCount == 0 ) {
  5200. *pArrCount = 0;
  5201. *pMaxCount = 0;
  5202. *pFindIndex = -1;
  5203. } else if ( ( *pFindIndex < 0 ) ||
  5204. ( *pFindIndex >= (LONG)(*pArrCount) ) ||
  5205. ( (*ppArrObject)[*pFindIndex] == NULL ) ||
  5206. ( (*ppArrObject)[*pFindIndex]->Name == NULL) ) {
  5207. //
  5208. // should search for the closest node
  5209. //
  5210. if ( ScepSearchItemInChildren(
  5211. ItemName,
  5212. NameLen,
  5213. *ppArrObject,
  5214. *pArrCount,
  5215. pFindIndex
  5216. ) ) {
  5217. return(ERROR_DUP_NAME);
  5218. }
  5219. }
  5220. INT CompFlag=-1;
  5221. if ( *pFindIndex >= 0 ) {
  5222. //
  5223. // check if the closest node matches the new node
  5224. //
  5225. CompFlag = _wcsicmp( ItemName, (*ppArrObject)[*pFindIndex]->Name );
  5226. if ( CompFlag == 0 ) {
  5227. return(ERROR_DUP_NAME);
  5228. }
  5229. }
  5230. PSCE_OBJECT_CHILDREN_NODE pNodeToAdd;
  5231. if ( ThisNode == NULL ) {
  5232. //
  5233. // allocate a new node
  5234. //
  5235. pNodeToAdd = (PSCE_OBJECT_CHILDREN_NODE)ScepAlloc(0, sizeof(SCE_OBJECT_CHILDREN_NODE));
  5236. if ( NameLen == 0 ) {
  5237. NameLen = wcslen(ItemName);
  5238. }
  5239. if ( pNodeToAdd ) {
  5240. pNodeToAdd->Name = (PWSTR)ScepAlloc(0, (NameLen+1)*sizeof(WCHAR));
  5241. if ( pNodeToAdd->Name ) {
  5242. wcscpy(pNodeToAdd->Name, ItemName);
  5243. pNodeToAdd->IsContainer = IsContainer;
  5244. pNodeToAdd->Status = Status;
  5245. pNodeToAdd->Count = ChildCount;
  5246. } else {
  5247. rc = ERROR_NOT_ENOUGH_MEMORY;
  5248. ScepFree(pNodeToAdd);
  5249. pNodeToAdd = NULL;
  5250. }
  5251. } else {
  5252. rc = ERROR_NOT_ENOUGH_MEMORY;
  5253. }
  5254. } else {
  5255. pNodeToAdd = ThisNode;
  5256. }
  5257. if ( ERROR_SUCCESS == rc ) {
  5258. LONG idxAdd, i;
  5259. if ( *pFindIndex >= 0 ) {
  5260. if ( CompFlag < 0 ) {
  5261. //
  5262. // add the new node before pFindIndex
  5263. //
  5264. idxAdd = *pFindIndex;
  5265. } else {
  5266. //
  5267. // add the new node after pFindIndex
  5268. //
  5269. idxAdd = *pFindIndex+1;
  5270. }
  5271. } else {
  5272. idxAdd = 0;
  5273. }
  5274. if ( *pArrCount >= *pMaxCount ) {
  5275. //
  5276. // there is not enough array nodes to hold the new node
  5277. //
  5278. PSCE_OBJECT_CHILDREN_NODE *pNewArray;
  5279. PBYTE pTmpBuffer;
  5280. pTmpBuffer = (PBYTE)ScepAlloc(0, 2*sizeof(DWORD)+(*pMaxCount+SCE_ALLOC_MAX_NODE)*sizeof(PSCE_OBJECT_CHILDREN_NODE));
  5281. if ( pTmpBuffer == NULL ) {
  5282. rc = ERROR_NOT_ENOUGH_MEMORY;
  5283. } else {
  5284. //
  5285. // need to shift two DWORDs for the array start
  5286. //
  5287. pNewArray = (PSCE_OBJECT_CHILDREN_NODE *)(pTmpBuffer + 2*sizeof(DWORD));
  5288. LONG idxStart1, idxEnd1, idxStart2, idxEnd2;
  5289. if ( *pFindIndex >= 0 ) {
  5290. if ( CompFlag < 0 ) {
  5291. //
  5292. // add the new node before pFindIndex
  5293. //
  5294. idxEnd1 = *pFindIndex-1;
  5295. idxStart2 = *pFindIndex;
  5296. } else {
  5297. //
  5298. // add the new node after pFindIndex
  5299. //
  5300. idxEnd1 = *pFindIndex;
  5301. idxStart2 = *pFindIndex+1;
  5302. }
  5303. idxStart1 = 0;
  5304. idxEnd2 = *pArrCount-1;
  5305. } else {
  5306. idxStart1 = -1;
  5307. idxEnd1 = -1;
  5308. idxStart2 = 0;
  5309. idxEnd2 = *pArrCount-1;
  5310. }
  5311. //
  5312. // make the copy
  5313. //
  5314. LONG j=0;
  5315. for ( i=idxStart1; i<=idxEnd1 && i>=0; i++ ) {
  5316. pNewArray[j++] = (*ppArrObject)[i];
  5317. }
  5318. pNewArray[idxAdd] = pNodeToAdd;
  5319. j = idxAdd+1;
  5320. for ( i=idxStart2; i<=idxEnd2 && i>=0; i++ ) {
  5321. pNewArray[j++] = (*ppArrObject)[i];
  5322. }
  5323. (*pMaxCount) += SCE_ALLOC_MAX_NODE;
  5324. (*pArrCount)++;
  5325. //
  5326. // free the old list
  5327. //
  5328. if ( *ppArrObject ) {
  5329. ScepFree((PBYTE)(*ppArrObject)-2*sizeof(DWORD));
  5330. }
  5331. *ppArrObject = pNewArray;
  5332. *pFindIndex = idxAdd;
  5333. }
  5334. } else {
  5335. //
  5336. // the buffer is big enough, just add the node to the buffer
  5337. //
  5338. //
  5339. // make the copy
  5340. //
  5341. for ( i=*pArrCount-1; i>=idxAdd && i>=0; i-- ) {
  5342. (*ppArrObject)[i+1] = (*ppArrObject)[i];
  5343. }
  5344. (*ppArrObject)[idxAdd] = pNodeToAdd;
  5345. (*pArrCount)++;
  5346. *pFindIndex = idxAdd;
  5347. }
  5348. }
  5349. //
  5350. // release memory if it fails
  5351. //
  5352. if ( ERROR_SUCCESS != rc &&
  5353. pNodeToAdd &&
  5354. pNodeToAdd != ThisNode ) {
  5355. ScepFree(pNodeToAdd->Name);
  5356. ScepFree(pNodeToAdd);
  5357. }
  5358. return(rc);
  5359. }