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

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