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.

2883 lines
90 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. infget.c
  5. Abstract:
  6. Routines to get information from security profiles (INF layout).
  7. Functions from setupapi.lib (setupapi.h), syssetup.lib (syssetup.h),
  8. netlib.lib (netlib.h) for parsing the INF layout are referenced
  9. besides ntdll, ntrtl, and etc.
  10. Author:
  11. Jin Huang (jinhuang) 28-Oct-1996
  12. Revision History:
  13. --*/
  14. #include "headers.h"
  15. #include "scedllrc.h"
  16. #include "infp.h"
  17. #include "sceutil.h"
  18. #include <sddl.h>
  19. #pragma hdrstop
  20. //#define INF_DBG 1
  21. #define SCEINF_OBJECT_FLAG_DSOBJECT 1
  22. #define SCEINF_OBJECT_FLAG_OLDSDDL 2
  23. #define SCEINF_OBJECT_FLAG_UNKNOWN_VERSION 4
  24. //
  25. // Forward references
  26. //
  27. SCESTATUS
  28. SceInfpGetSystemAccess(
  29. IN HINF hInf,
  30. IN DWORD ObjectFlag,
  31. OUT PSCE_PROFILE_INFO pSCEinfo,
  32. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  33. );
  34. SCESTATUS
  35. SceInfpGetUserSettings(
  36. IN HINF hInf,
  37. OUT PSCE_NAME_LIST *pProfileList,
  38. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  39. );
  40. SCESTATUS
  41. SceInfpGetGroupMembership(
  42. IN HINF hInf,
  43. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  44. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  45. );
  46. SCESTATUS
  47. SceInfpGetObjects(
  48. IN HINF hInf,
  49. IN PCWSTR SectionName,
  50. IN DWORD ObjectFlag,
  51. OUT PSCE_OBJECT_ARRAY *pAllNodes,
  52. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  53. );
  54. SCESTATUS
  55. SceInfpGetOneObjectSecurity(
  56. IN PINFCONTEXT pInfLine,
  57. IN DWORD ObjectFlag,
  58. OUT PSCE_OBJECT_SECURITY *pObject,
  59. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  60. );
  61. SCESTATUS
  62. SceInfpGetAuditLogSetting(
  63. IN HINF hInf,
  64. IN PCWSTR SectionName,
  65. IN DWORD ObjectFlag,
  66. OUT PDWORD LogSize,
  67. OUT PDWORD Periods,
  68. OUT PDWORD RetentionDays,
  69. OUT PDWORD RestrictGuest,
  70. IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  71. );
  72. SCESTATUS
  73. SceInfpGetAuditing(
  74. IN HINF hInf,
  75. IN DWORD ObjectFlag,
  76. OUT PSCE_PROFILE_INFO pSCEinfo,
  77. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  78. );
  79. SCESTATUS
  80. SceInfpGetKerberosPolicy(
  81. IN HINF hInf,
  82. IN DWORD ObjectFlag,
  83. OUT PSCE_KERBEROS_TICKET_INFO * ppKerberosInfo,
  84. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  85. );
  86. SCESTATUS
  87. SceInfpGetRegistryValues(
  88. IN HINF hInf,
  89. IN DWORD ObjectFlag,
  90. OUT PSCE_REGISTRY_VALUE_INFO * ppRegValues,
  91. OUT LPDWORD pValueCount,
  92. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  93. );
  94. SCESTATUS
  95. SceInfpGetOneRegistryValue(
  96. IN PINFCONTEXT pInfLine,
  97. IN DWORD ObjectFlag,
  98. OUT PSCE_REGISTRY_VALUE_INFO pValues,
  99. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  100. );
  101. SCESTATUS
  102. SceInfpGetSystemServices(
  103. IN HINF hInf,
  104. IN DWORD ObjectFlag,
  105. OUT PSCE_SERVICES *pServiceList,
  106. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  107. );
  108. //
  109. // function definitions
  110. //
  111. SCESTATUS
  112. SceInfpGetSecurityProfileInfo(
  113. IN HINF hInf,
  114. IN AREA_INFORMATION Area,
  115. OUT PSCE_PROFILE_INFO *ppInfoBuffer,
  116. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  117. )
  118. /**++
  119. Function Description:
  120. This function reads all or part of information from a SCP file in INF
  121. format into the InfoBuffer.
  122. The memory related to the area(s) will be reset/freed before loading
  123. information from the INF file. If the return code is SCESTATUS_SUCCESS,
  124. then the output InfoBuffer contains the requested information. Otherwise,
  125. InfoBuffer contains nothing for the area(s) specified.
  126. Arguments:
  127. hInf - The INF handle to read from.
  128. Area - area(s) for which to get information from
  129. AREA_SECURITY_POLICY
  130. AREA_PRIVILEGES
  131. AREA_USER_SETTINGS
  132. AREA_GROUP_MEMBERSHIP
  133. AREA_REGISTRY_SECURITY
  134. AREA_SYSTEM_SERVICE
  135. AREA_FILE_SECURITY
  136. ppInfoBuffer - The address of SCP profile buffers. If it is NULL, a buffer
  137. will be created which must be freed by SceFreeMemory. The
  138. output is the information requested if successful, or nothing
  139. if fail.
  140. Errlog - A buffer to hold all error codes/text encountered when
  141. parsing the INF file. If Errlog is NULL, no further error
  142. information is returned except the return DWORD
  143. Return Value:
  144. SCESTATUS_SUCCESS
  145. SCESTATUS_PROFILE_NOT_FOUND
  146. SCESTATUS_NOT_ENOUGH_RESOURCE
  147. SCESTATUS_INVALID_PARAMETER
  148. SCESTATUS_BAD_FORMAT
  149. SCESTATUS_INVALID_DATA
  150. -- **/
  151. {
  152. SCESTATUS rc=SCESTATUS_SUCCESS;
  153. UINT Len;
  154. BOOL bFreeMem=FALSE;
  155. DWORD ObjectFlag=0;
  156. //
  157. // if the INF file is not loaded (hInf = 0), then return
  158. //
  159. if ( !hInf ) {
  160. return( SCESTATUS_INVALID_PARAMETER );
  161. }
  162. //
  163. // address for InfoBuffer cannot be NULL
  164. //
  165. if ( ppInfoBuffer == NULL ) {
  166. return( SCESTATUS_INVALID_PARAMETER );
  167. }
  168. //
  169. // if the Area is not valid, then return
  170. //
  171. if ( Area & ~AREA_ALL) {
  172. return( SCESTATUS_INVALID_PARAMETER );
  173. }
  174. if ( *ppInfoBuffer == NULL) {
  175. //
  176. // allocate memory
  177. //
  178. Len = sizeof(SCE_PROFILE_INFO);
  179. *ppInfoBuffer = (PSCE_PROFILE_INFO)ScepAlloc( (UINT)0, Len );
  180. if ( *ppInfoBuffer == NULL ) {
  181. return( SCESTATUS_NOT_ENOUGH_RESOURCE );
  182. }
  183. memset(*ppInfoBuffer, '\0', Len);
  184. (*ppInfoBuffer)->Type = SCE_STRUCT_INF;
  185. ScepResetSecurityPolicyArea(*ppInfoBuffer);
  186. bFreeMem = TRUE;
  187. }
  188. //
  189. // Free related memory and reset the buffer before parsing
  190. // there is a problem here for now. it clears the handle and
  191. // filename too. So comment it out.
  192. SceFreeMemory( (PVOID)(*ppInfoBuffer), Area );
  193. //
  194. // system access
  195. //
  196. INT Revision = 0;
  197. INFCONTEXT InfLine;
  198. if ( SetupFindFirstLine(hInf,L"Version",L"Revision",&InfLine) ) {
  199. if ( !SetupGetIntField(&InfLine, 1, (INT *)&Revision) ) {
  200. Revision = 0;
  201. }
  202. }
  203. if ( Revision == 0) {
  204. ObjectFlag = SCEINF_OBJECT_FLAG_OLDSDDL;
  205. }
  206. if ( Revision > SCE_TEMPLATE_MAX_SUPPORTED_VERSION ) {
  207. ObjectFlag |= SCEINF_OBJECT_FLAG_UNKNOWN_VERSION;
  208. }
  209. if ( Area & AREA_SECURITY_POLICY ) {
  210. rc = SceInfpGetSystemAccess(
  211. hInf,
  212. ObjectFlag,
  213. *ppInfoBuffer,
  214. Errlog
  215. );
  216. if( rc != SCESTATUS_SUCCESS )
  217. goto Done;
  218. //
  219. // system auditing
  220. //
  221. rc = SceInfpGetAuditing(
  222. hInf,
  223. ObjectFlag,
  224. *ppInfoBuffer,
  225. Errlog
  226. );
  227. if( rc != SCESTATUS_SUCCESS )
  228. goto Done;
  229. //
  230. // kerberos policy
  231. //
  232. rc = SceInfpGetKerberosPolicy(
  233. hInf,
  234. ObjectFlag,
  235. &((*ppInfoBuffer)->pKerberosInfo),
  236. Errlog
  237. );
  238. if( rc != SCESTATUS_SUCCESS )
  239. goto Done;
  240. //
  241. // registry values
  242. //
  243. rc = SceInfpGetRegistryValues(
  244. hInf,
  245. ObjectFlag,
  246. &((*ppInfoBuffer)->aRegValues),
  247. &((*ppInfoBuffer)->RegValueCount),
  248. Errlog
  249. );
  250. if( rc != SCESTATUS_SUCCESS )
  251. goto Done;
  252. }
  253. //
  254. // privilege/rights
  255. //
  256. if ( Area & AREA_PRIVILEGES ) {
  257. rc = SceInfpGetPrivileges(
  258. hInf,
  259. TRUE,
  260. &( (*ppInfoBuffer)->OtherInfo.scp.u.pInfPrivilegeAssignedTo ),
  261. Errlog
  262. );
  263. if( rc != SCESTATUS_SUCCESS )
  264. goto Done;
  265. }
  266. //
  267. // account profiles list
  268. //
  269. if ( Area & AREA_USER_SETTINGS ) {
  270. rc = SceInfpGetUserSettings(
  271. hInf,
  272. &( (*ppInfoBuffer)->OtherInfo.scp.pAccountProfiles ),
  273. Errlog
  274. );
  275. if( rc != SCESTATUS_SUCCESS )
  276. goto Done;
  277. }
  278. //
  279. // group memberships
  280. //
  281. if ( Area & AREA_GROUP_MEMBERSHIP ) {
  282. rc = SceInfpGetGroupMembership(
  283. hInf,
  284. &((*ppInfoBuffer)->pGroupMembership),
  285. Errlog
  286. );
  287. if( rc != SCESTATUS_SUCCESS )
  288. goto Done;
  289. }
  290. //
  291. // registry keys security
  292. //
  293. if ( Area & AREA_REGISTRY_SECURITY ) {
  294. rc = SceInfpGetObjects(
  295. hInf,
  296. szRegistryKeys,
  297. ObjectFlag,
  298. &((*ppInfoBuffer)->pRegistryKeys.pAllNodes),
  299. Errlog
  300. );
  301. if ( rc != SCESTATUS_SUCCESS )
  302. goto Done;
  303. }
  304. //
  305. // system services
  306. //
  307. if ( Area & AREA_SYSTEM_SERVICE ) {
  308. rc = SceInfpGetSystemServices(
  309. hInf,
  310. ObjectFlag,
  311. &((*ppInfoBuffer)->pServices),
  312. Errlog
  313. );
  314. if( rc != SCESTATUS_SUCCESS )
  315. goto Done;
  316. }
  317. //
  318. // file security
  319. //
  320. if ( Area & AREA_FILE_SECURITY ) {
  321. rc = SceInfpGetObjects(
  322. hInf,
  323. szFileSecurity,
  324. ObjectFlag,
  325. &((*ppInfoBuffer)->pFiles.pAllNodes),
  326. Errlog
  327. );
  328. if ( rc != SCESTATUS_SUCCESS )
  329. goto Done;
  330. }
  331. #if 0
  332. if ( Area & AREA_DS_OBJECTS ) {
  333. rc = SceInfpGetObjects(
  334. hInf,
  335. szDSSecurity,
  336. ObjectFlag | SCEINF_OBJECT_FLAG_DSOBJECT,
  337. &((*ppInfoBuffer)->pDsObjects.pAllNodes),
  338. Errlog
  339. );
  340. if ( rc != SCESTATUS_SUCCESS )
  341. goto Done;
  342. }
  343. #endif
  344. Done:
  345. if ( rc != SCESTATUS_SUCCESS ) {
  346. //
  347. // need free memory because some fatal error happened
  348. //
  349. SceFreeMemory( (PVOID)(*ppInfoBuffer), Area );
  350. if ( bFreeMem ) {
  351. ScepFree(*ppInfoBuffer);
  352. *ppInfoBuffer = NULL;
  353. }
  354. }
  355. return(rc);
  356. }
  357. SCESTATUS
  358. SceInfpGetSystemAccess(
  359. IN HINF hInf,
  360. IN DWORD ObjectFlag,
  361. OUT PSCE_PROFILE_INFO pSCEinfo,
  362. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  363. )
  364. /*++
  365. Routine Description:
  366. This routine retrieves system access area information from the SCP INF
  367. file and stores in the output buffer pSCEinfo. System access information
  368. includes information in [System Access] section.
  369. Arguments:
  370. hInf - INF handle to the profile
  371. pSCEinfo - the output buffer to hold profile info.
  372. Errlog - A buffer to hold all error codes/text encountered when
  373. parsing the INF file. If Errlog is NULL, no further error
  374. information is returned except the return DWORD
  375. Return value:
  376. SCESTATUS - SCESTATUS_SUCCESS
  377. SCESTATUS_NOT_ENOUGH_RESOURCE
  378. SCESTATUS_INVALID_PARAMETER
  379. SCESTATUS_BAD_FORMAT
  380. SCESTATUS_INVALID_DATA
  381. --*/
  382. {
  383. INFCONTEXT InfLine;
  384. SCESTATUS rc=SCESTATUS_SUCCESS;
  385. DWORD Keyvalue=0;
  386. DWORD DataSize=0;
  387. PWSTR Strvalue=NULL;
  388. SCE_KEY_LOOKUP AccessSCPLookup[] = {
  389. {(PWSTR)TEXT("MinimumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordAge), 'D'},
  390. {(PWSTR)TEXT("MaximumPasswordAge"), offsetof(struct _SCE_PROFILE_INFO, MaximumPasswordAge), 'D'},
  391. {(PWSTR)TEXT("MinimumPasswordLength"), offsetof(struct _SCE_PROFILE_INFO, MinimumPasswordLength), 'D'},
  392. {(PWSTR)TEXT("PasswordComplexity"), offsetof(struct _SCE_PROFILE_INFO, PasswordComplexity), 'D'},
  393. {(PWSTR)TEXT("PasswordHistorySize"), offsetof(struct _SCE_PROFILE_INFO, PasswordHistorySize), 'D'},
  394. {(PWSTR)TEXT("LockoutBadCount"), offsetof(struct _SCE_PROFILE_INFO, LockoutBadCount), 'D'},
  395. {(PWSTR)TEXT("ResetLockoutCount"), offsetof(struct _SCE_PROFILE_INFO, ResetLockoutCount), 'D'},
  396. {(PWSTR)TEXT("LockoutDuration"), offsetof(struct _SCE_PROFILE_INFO, LockoutDuration), 'D'},
  397. {(PWSTR)TEXT("RequireLogonToChangePassword"), offsetof(struct _SCE_PROFILE_INFO, RequireLogonToChangePassword), 'D'},
  398. {(PWSTR)TEXT("ForceLogoffWhenHourExpire"), offsetof(struct _SCE_PROFILE_INFO, ForceLogoffWhenHourExpire), 'D'},
  399. {(PWSTR)TEXT("NewAdministratorName"), 0, 'A'},
  400. {(PWSTR)TEXT("NewGuestName"), 0, 'G'},
  401. {(PWSTR)TEXT("SecureSystemPartition"), offsetof(struct _SCE_PROFILE_INFO, SecureSystemPartition), 'D'},
  402. {(PWSTR)TEXT("ClearTextPassword"), offsetof(struct _SCE_PROFILE_INFO, ClearTextPassword), 'D'},
  403. {(PWSTR)TEXT("LSAAnonymousNameLookup"), offsetof(struct _SCE_PROFILE_INFO, LSAAnonymousNameLookup), 'D'},
  404. {(PWSTR)TEXT("EnableAdminAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableAdminAccount), 'D'},
  405. {(PWSTR)TEXT("EnableGuestAccount"), offsetof(struct _SCE_PROFILE_INFO, EnableGuestAccount), 'D'}
  406. };
  407. DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  408. DWORD i;
  409. UINT Offset;
  410. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  411. //
  412. // Initialize to SCE_NO_VALUE
  413. //
  414. for ( i=0; i<cAccess; i++) {
  415. if ( AccessSCPLookup[i].BufferType == 'D' )
  416. *((DWORD *)((CHAR *)pSCEinfo+AccessSCPLookup[i].Offset)) = SCE_NO_VALUE;
  417. }
  418. //
  419. // Locate the [System Access] section.
  420. //
  421. if(SetupFindFirstLine(hInf,szSystemAccess,NULL,&InfLine)) {
  422. do {
  423. //
  424. // Get key names and its setting.
  425. //
  426. rc = SCESTATUS_SUCCESS;
  427. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  428. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  429. for ( i=0; i<cAccess; i++) {
  430. //
  431. // get settings in AccessLookup table
  432. //
  433. Offset = AccessSCPLookup[i].Offset;
  434. if (_wcsicmp(Keyname, AccessSCPLookup[i].KeyString ) == 0) {
  435. switch ( AccessSCPLookup[i].BufferType ) {
  436. case 'B':
  437. //
  438. // Int Field
  439. //
  440. Keyvalue = 0;
  441. SetupGetIntField( &InfLine, 1, (INT *)&Keyvalue );
  442. *((BOOL *)((CHAR *)pSCEinfo+Offset)) = Keyvalue ? TRUE : FALSE;
  443. break;
  444. case 'D':
  445. //
  446. // Int Field
  447. //
  448. if (SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue ) )
  449. *((DWORD *)((CHAR *)pSCEinfo+Offset)) = (DWORD)Keyvalue;
  450. break;
  451. default:
  452. //
  453. // String Field - NewAdministratorName, or NewGuestName
  454. //
  455. if(SetupGetStringField(&InfLine,1,NULL,0,&DataSize) && DataSize > 0) {
  456. Strvalue = (PWSTR)ScepAlloc( 0, (DataSize+1)*sizeof(WCHAR));
  457. if( Strvalue == NULL ) {
  458. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  459. } else {
  460. Strvalue[DataSize] = L'\0';
  461. if(SetupGetStringField(&InfLine,1,Strvalue,DataSize, NULL)) {
  462. if ( Strvalue[0] != L'\0' && Strvalue[0] != L' ') {
  463. if (AccessSCPLookup[i].BufferType == 'A') // administrator
  464. pSCEinfo->NewAdministratorName = Strvalue;
  465. else // guest
  466. pSCEinfo->NewGuestName = Strvalue;
  467. } else
  468. ScepFree(Strvalue);
  469. Strvalue = NULL;
  470. } else {
  471. ScepFree( Strvalue );
  472. rc = SCESTATUS_BAD_FORMAT;
  473. }
  474. }
  475. } else
  476. rc = SCESTATUS_BAD_FORMAT;
  477. break;
  478. }
  479. break; // for loop
  480. }
  481. }
  482. if ( i >= cAccess &&
  483. !(ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION) ) {
  484. //
  485. // Did not find a match in the lookup table
  486. //
  487. ScepBuildErrorLogInfo( NO_ERROR,
  488. Errlog,
  489. SCEERR_NOT_EXPECTED,
  490. Keyname,szSystemAccess );
  491. }
  492. if ( rc != SCESTATUS_SUCCESS ) {
  493. ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc),
  494. Errlog,
  495. SCEERR_QUERY_INFO,
  496. Keyname );
  497. }
  498. } else {
  499. rc = SCESTATUS_INVALID_DATA;
  500. ScepBuildErrorLogInfo( ERROR_INVALID_DATA, Errlog,
  501. SCEERR_QUERY_INFO,
  502. szSystemAccess);
  503. }
  504. //
  505. // if error happens, get out
  506. //
  507. if ( rc != SCESTATUS_SUCCESS )
  508. return(rc);
  509. } while(SetupFindNextLine(&InfLine,&InfLine));
  510. }
  511. return(rc);
  512. }
  513. SCESTATUS
  514. SceInfpGetUserSettings(
  515. IN HINF hInf,
  516. OUT PSCE_NAME_LIST *pProfileList,
  517. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  518. )
  519. /* ++
  520. Routine Description:
  521. This routine retrieves account profile list from the INF file (SCP) and
  522. stores in the output buffer pProfileList.
  523. Arguments:
  524. hInf - INF handle to the profile
  525. pProfileList - the output buffer to hold account profile list.
  526. Errlog - The error list encountered inside inf processing.
  527. Return value:
  528. SCESTATUS - SCESTATUS_SUCCESS
  529. SCESTATUS_NOT_ENOUGH_RESOURCE
  530. SCESTATUS_INVALID_PARAMETER
  531. SCESTATUS_BAD_FORMAT
  532. SCESTATUS_INVALID_DATA
  533. -- */
  534. {
  535. INFCONTEXT InfLine;
  536. SCESTATUS rc=SCESTATUS_SUCCESS;
  537. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  538. //
  539. // [Account Profiles] section
  540. //
  541. if(SetupFindFirstLine(hInf,szAccountProfiles,NULL,&InfLine)) {
  542. do {
  543. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  544. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  545. //
  546. // find a key name which is a profile name.
  547. //
  548. rc = ScepAddToNameList(pProfileList, Keyname, 0);
  549. if ( rc != SCESTATUS_SUCCESS ) {
  550. ScepBuildErrorLogInfo(ERROR_INVALID_DATA,
  551. Errlog,
  552. SCEERR_ADD,
  553. Keyname );
  554. }
  555. } else {
  556. ScepBuildErrorLogInfo(ERROR_BAD_FORMAT,
  557. Errlog,
  558. SCEERR_QUERY_INFO,
  559. L"profile name"
  560. );
  561. rc = SCESTATUS_BAD_FORMAT;
  562. }
  563. } while( rc == SCESTATUS_SUCCESS &&
  564. SetupFindNextLine(&InfLine,&InfLine));
  565. }
  566. return(rc);
  567. }
  568. SCESTATUS
  569. SceInfpGetGroupMembership(
  570. IN HINF hInf,
  571. OUT PSCE_GROUP_MEMBERSHIP *pGroupMembership,
  572. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  573. )
  574. /* ++
  575. Routine Description:
  576. This routine retrieves group membership information from the SCP INF file
  577. and stores in the output buffer pGroupMembership. Group membership info is
  578. in [Group Membership] section.
  579. Arguments:
  580. hInf - INF handle to the profile
  581. pGroupMembership - the output buffer to hold group membersip information.
  582. Errlog - the error list for errors encountered in this routine.
  583. Return value:
  584. SCESTATUS - SCESTATUS_SUCCESS
  585. SCESTATUS_NOT_ENOUGH_RESOURCE
  586. SCESTATUS_INVALID_PARAMETER
  587. SCESTATUS_BAD_FORMAT
  588. SCESTATUS_INVALID_DATA
  589. -- */
  590. {
  591. INFCONTEXT InfLine;
  592. PSCE_NAME_LIST pMembers=NULL;
  593. SCESTATUS rc=SCESTATUS_SUCCESS;
  594. PWSTR Keyname=NULL;
  595. DWORD KeyLen;
  596. DWORD ValueType;
  597. PWSTR pTemp;
  598. DWORD i;
  599. DWORD cFields;
  600. DWORD DataSize;
  601. PWSTR Strvalue=NULL;
  602. PWSTR GroupName=NULL;
  603. DWORD GroupLen;
  604. if ( pGroupMembership == NULL )
  605. return(SCESTATUS_INVALID_PARAMETER);
  606. LSA_HANDLE LsaHandle=NULL;
  607. //
  608. // Locate the [Group MemberShip] section.
  609. //
  610. if ( SetupFindFirstLine(hInf,szGroupMembership,NULL,&InfLine) ) {
  611. //
  612. // open lsa policy handle for sid/name lookup
  613. //
  614. rc = RtlNtStatusToDosError(
  615. ScepOpenLsaPolicy(
  616. POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION,
  617. &LsaHandle,
  618. TRUE
  619. ));
  620. if ( ERROR_SUCCESS != rc ) {
  621. ScepBuildErrorLogInfo(
  622. rc,
  623. Errlog,
  624. SCEERR_ADD,
  625. TEXT("LSA")
  626. );
  627. return(ScepDosErrorToSceStatus(rc));
  628. }
  629. PSID pSid=NULL;
  630. do {
  631. //
  632. // Get group names.
  633. //
  634. rc = SCESTATUS_BAD_FORMAT;
  635. if ( SetupGetStringField(&InfLine, 0, NULL, 0, &KeyLen) ) {
  636. Keyname = (PWSTR)ScepAlloc( 0, (KeyLen+1)*sizeof(WCHAR));
  637. if ( Keyname == NULL ) {
  638. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  639. goto Done;
  640. }
  641. Keyname[KeyLen] = L'\0';
  642. if ( SetupGetStringField(&InfLine, 0, Keyname, KeyLen, NULL) ) {
  643. //
  644. // look for what kind of value this line is
  645. //
  646. pTemp = ScepWcstrr(Keyname, szMembers);
  647. ValueType = 0;
  648. if ( pTemp == NULL ) {
  649. pTemp = ScepWcstrr(Keyname, szMemberof);
  650. ValueType = 1;
  651. }
  652. if ( pTemp == NULL ) {
  653. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  654. Errlog,
  655. SCEERR_CANT_FIND_KEYWORD,
  656. Keyname
  657. );
  658. rc = SCESTATUS_SUCCESS;
  659. goto NextLine;
  660. }
  661. // terminiate Keyname for the group name only
  662. *pTemp = L'\0';
  663. if ( Keyname[0] == L'*' ) {
  664. //
  665. // *SID format, convert it into group name
  666. //
  667. if ( ConvertStringSidToSid( Keyname+1, &pSid) ) {
  668. //
  669. // if failed to convert from sid string to sid,
  670. // treat it as any name
  671. //
  672. ScepConvertSidToName(
  673. LsaHandle,
  674. pSid,
  675. TRUE,
  676. &GroupName,
  677. &GroupLen
  678. );
  679. LocalFree(pSid);
  680. pSid = NULL;
  681. }
  682. }
  683. if ( GroupName == NULL ) {
  684. GroupLen = (DWORD) (pTemp - Keyname);
  685. }
  686. //
  687. // String fields. Each string respresents a member or memberof name.
  688. //
  689. cFields = SetupGetFieldCount( &InfLine );
  690. for ( i=0; i<cFields; i++) {
  691. if(SetupGetStringField(&InfLine,i+1,NULL,0,&DataSize) && DataSize > 0 ) {
  692. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  693. (DataSize+1)*sizeof(WCHAR) );
  694. if( Strvalue == NULL ) {
  695. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  696. } else {
  697. if(SetupGetStringField(&InfLine,i+1,Strvalue,DataSize,NULL)) {
  698. //
  699. // Get a member name and save in the list
  700. //
  701. if ( Strvalue[0] == L'*' && DataSize > 0 ) {
  702. //
  703. // this is a SID format, should look it up
  704. //
  705. rc = ScepLookupSidStringAndAddToNameList(
  706. LsaHandle,
  707. &pMembers,
  708. Strvalue, // +1,
  709. DataSize // -1
  710. );
  711. } else {
  712. rc = ScepAddToNameList(&pMembers,
  713. Strvalue,
  714. DataSize+1
  715. );
  716. }
  717. }
  718. ScepFree( Strvalue );
  719. Strvalue = NULL;
  720. }
  721. }
  722. if ( rc != SCESTATUS_SUCCESS)
  723. break; // for loop
  724. } // end of for loop
  725. if ( rc == SCESTATUS_SUCCESS ) { // && pMembers != NULL ) {
  726. //
  727. // add this list to the group
  728. //
  729. rc = ScepAddToGroupMembership(
  730. pGroupMembership,
  731. GroupName ? GroupName : Keyname,
  732. GroupLen, // wcslen(Keyname),
  733. pMembers,
  734. ValueType,
  735. TRUE,
  736. TRUE
  737. );
  738. if ( rc == SCESTATUS_SUCCESS )
  739. pMembers = NULL;
  740. }
  741. // restore the character
  742. *pTemp = L'_';
  743. }
  744. }
  745. if ( rc != SCESTATUS_SUCCESS ) {
  746. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT,
  747. Errlog,
  748. SCEERR_QUERY_INFO,
  749. szGroupMembership
  750. );
  751. goto Done;
  752. }
  753. NextLine:
  754. //
  755. // Free pMembers, Keyname
  756. //
  757. ScepFreeNameList(pMembers);
  758. pMembers = NULL;
  759. ScepFree(Keyname);
  760. Keyname = NULL;
  761. if ( GroupName ) {
  762. LocalFree(GroupName);
  763. GroupName = NULL;
  764. }
  765. } while(SetupFindNextLine(&InfLine,&InfLine));
  766. }
  767. Done:
  768. //
  769. // Free pMembers, Keyname
  770. //
  771. ScepFreeNameList(pMembers);
  772. if ( Keyname != NULL )
  773. ScepFree(Keyname);
  774. if ( Strvalue != NULL )
  775. ScepFree( Strvalue );
  776. if ( LsaHandle ) {
  777. LsaClose(LsaHandle);
  778. }
  779. if ( GroupName ) {
  780. LocalFree(GroupName);
  781. }
  782. return(rc);
  783. }
  784. SCESTATUS
  785. SceInfpGetObjects(
  786. IN HINF hInf,
  787. IN PCWSTR SectionName,
  788. IN DWORD ObjectFlag,
  789. OUT PSCE_OBJECT_ARRAY *pAllNodes,
  790. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  791. )
  792. /* ++
  793. Routine Description:
  794. This routine retrieves registry or files security information (names and
  795. security descriptors) from the INF file (SCP and SAP) and stores in the
  796. output buffer pSCEinfo. Registry information is in [SCRegistryKeysSecurity]
  797. section. Files information is in [SSFileSecurity], [SCIntel86Only], and
  798. [SCRISCOnly] sections. These sections have the same format, namely, 3 fields
  799. on each line - name, workstaiton setting, and server setting.
  800. Arguments:
  801. hInf - INF handle to the profile
  802. SectionName - the section name to retrieve.
  803. pAllNodes - the output buffer to hold all objects in the section.
  804. Errlog - the cummulative error list to hold errors encountered in this routine.
  805. Return value:
  806. SCESTATUS - SCESTATUS_SUCCESS
  807. SCESTATUS_NOT_ENOUGH_RESOURCE
  808. SCESTATUS_INVALID_PARAMETER
  809. SCESTATUS_BAD_FORMAT
  810. SCESTATUS_INVALID_DATA
  811. -- */
  812. {
  813. INFCONTEXT InfLine;
  814. SCESTATUS rc=SCESTATUS_SUCCESS;
  815. LONG i;
  816. LONG nLines;
  817. DWORD cFields;
  818. if ( pAllNodes == NULL || SectionName == NULL )
  819. return(SCESTATUS_INVALID_PARAMETER);
  820. //
  821. // count how many objects
  822. //
  823. nLines = SetupGetLineCount(hInf, SectionName );
  824. if ( nLines == -1 ) {
  825. // section not found
  826. return(SCESTATUS_SUCCESS);
  827. }
  828. *pAllNodes = (PSCE_OBJECT_ARRAY)ScepAlloc(0, sizeof(SCE_OBJECT_ARRAY));
  829. if ( *pAllNodes == NULL )
  830. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  831. (*pAllNodes)->Count = nLines;
  832. (*pAllNodes)->pObjectArray = NULL;
  833. if ( nLines == 0 )
  834. return(SCESTATUS_SUCCESS);
  835. //
  836. // allocate memory for all objects
  837. //
  838. (*pAllNodes)->pObjectArray = (PSCE_OBJECT_SECURITY *)ScepAlloc( LMEM_ZEROINIT,
  839. nLines*sizeof(PSCE_OBJECT_SECURITY) );
  840. if ( (*pAllNodes)->pObjectArray == NULL ) {
  841. ScepFree(*pAllNodes);
  842. *pAllNodes = NULL;
  843. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  844. }
  845. //
  846. // Locate the section.
  847. //
  848. if ( SetupFindFirstLine(hInf,SectionName,NULL,&InfLine) ) {
  849. i = 0;
  850. TCHAR tmpBuf[MAX_PATH];
  851. do {
  852. //
  853. // Get string fields. Don't care the key name or if it exist.
  854. // Must have 3 fields each line for supported versions.
  855. //
  856. cFields = SetupGetFieldCount( &InfLine );
  857. if ( cFields < 3 ) {
  858. tmpBuf[0] = L'\0';
  859. SetupGetStringField(&InfLine,1,tmpBuf,MAX_PATH,NULL);
  860. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  861. Errlog,
  862. SCEERR_OBJECT_FIELDS,
  863. tmpBuf);
  864. if (ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION) {
  865. //
  866. // maybe a new format for object,
  867. // ignore this line
  868. //
  869. rc = SCESTATUS_SUCCESS;
  870. goto NextLine;
  871. } else {
  872. rc = SCESTATUS_INVALID_DATA;
  873. }
  874. }
  875. if ( SCESTATUS_SUCCESS == rc ) {
  876. rc = SceInfpGetOneObjectSecurity(
  877. &InfLine,
  878. ObjectFlag,
  879. ( (*pAllNodes)->pObjectArray + i ),
  880. Errlog
  881. );
  882. }
  883. if ( rc != SCESTATUS_SUCCESS ) {
  884. if ( rc == SCESTATUS_BAD_FORMAT ) {
  885. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT,
  886. Errlog,
  887. SCEERR_QUERY_INFO,
  888. SectionName);
  889. }
  890. break; // do..while loop
  891. }
  892. i++;
  893. NextLine:
  894. if ( i > nLines ) {
  895. // more lines than allocated
  896. rc = SCESTATUS_INVALID_DATA;
  897. ScepBuildErrorLogInfo(ERROR_INVALID_DATA,
  898. Errlog,
  899. SCEERR_MORE_OBJECTS,
  900. nLines
  901. );
  902. break;
  903. }
  904. } while(SetupFindNextLine(&InfLine,&InfLine));
  905. }
  906. if ( rc != SCESTATUS_SUCCESS ) {
  907. // free memory
  908. ScepFreeObjectSecurity( *pAllNodes );
  909. // ScepFree( *pAllNodes );
  910. *pAllNodes = NULL;
  911. } else if ( ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION ) {
  912. //
  913. // reset the count because some lines may be skipped
  914. //
  915. (*pAllNodes)->Count = i;
  916. }
  917. return(rc);
  918. }
  919. SCESTATUS
  920. SceInfpGetOneObjectSecurity(
  921. IN PINFCONTEXT pInfLine,
  922. IN DWORD ObjectFlag,
  923. OUT PSCE_OBJECT_SECURITY *ppObject,
  924. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  925. )
  926. /* ++
  927. Routine Description:
  928. This routine retrieves security setting for one object (a registry key,
  929. or a file) from the INF file (SCP type). Each object in these sections
  930. is represented by one line. Each object has 3 fields, a name, a status
  931. flag, and security setting. This routine stores the output in buffer
  932. ppObject.
  933. Arguments:
  934. pInfLine - Current line context from the INF file for one object
  935. ppObject - Output buffer (tree root ) to hold the security settings for this line
  936. Errlog - The cummulative error list for errors encountered in this routine
  937. Return value:
  938. SCESTATUS - SCESTATUS_SUCCESS
  939. SCESTATUS_NOT_ENOUGH_RESOURCE
  940. SCESTATUS_INVALID_PARAMETER
  941. SCESTATUS_BAD_FORMAT
  942. SCESTATUS_INVALID_DATA
  943. -- */
  944. {
  945. DWORD cFields;
  946. DWORD DataSize;
  947. PWSTR Strvalue=NULL;
  948. PWSTR SDspec=NULL;
  949. DWORD SDsize;
  950. DWORD Status=0;
  951. PSECURITY_DESCRIPTOR pTempSD=NULL;
  952. SECURITY_INFORMATION SeInfo;
  953. SCESTATUS rc=SCESTATUS_SUCCESS;
  954. //
  955. // The Registry/File INF layout must have 3 fields for each line.
  956. // The first field is the key/file name, the 2nd field is status flag -
  957. // ignore, or check, and the 3rd field is the security descriptor text
  958. //
  959. if ( ppObject == NULL )
  960. return(SCESTATUS_INVALID_PARAMETER);
  961. cFields = SetupGetFieldCount( pInfLine );
  962. if ( cFields < 3 ) {
  963. return(SCESTATUS_INVALID_DATA);
  964. } else if(SetupGetStringField(pInfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
  965. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  966. (DataSize+1)*sizeof(WCHAR) );
  967. if( Strvalue == NULL ) {
  968. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  969. } else {
  970. //
  971. // the first field is the key/file name.
  972. // The 2nd is a status flag.
  973. // The 3rd field is the security descriptor text
  974. //
  975. if( SetupGetStringField(pInfLine,1,Strvalue,DataSize,NULL) &&
  976. SetupGetIntField( pInfLine, 2, (INT *)&Status ) &&
  977. // SetupGetStringField(pInfLine,3,NULL,0,&SDsize) ) {
  978. SetupGetMultiSzField(pInfLine,3,NULL,0,&SDsize) ) {
  979. SDspec = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  980. (SDsize+1)*sizeof(WCHAR)
  981. );
  982. if( SDspec == NULL ) {
  983. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  984. goto Done;
  985. }
  986. // if(SetupGetStringField(pInfLine,3,SDspec,SDsize,NULL)) {
  987. if(SetupGetMultiSzField(pInfLine,3,SDspec,SDsize,NULL)) {
  988. //
  989. // convert the multi-sz delimiter to space, if there is any
  990. //
  991. if ( cFields > 3 ) {
  992. ScepConvertMultiSzToDelim(SDspec, SDsize, L'\0', L' ');
  993. }
  994. if ( ObjectFlag & SCEINF_OBJECT_FLAG_OLDSDDL ) {
  995. ScepConvertToSDDLFormat(SDspec, SDsize);
  996. }
  997. //
  998. // Convert the text to real security descriptors
  999. //
  1000. rc = ConvertTextSecurityDescriptor(
  1001. SDspec,
  1002. &pTempSD,
  1003. &SDsize,
  1004. &SeInfo
  1005. );
  1006. if (rc == NO_ERROR) {
  1007. // create a new object node to hold these info.
  1008. if ( !(ObjectFlag & SCEINF_OBJECT_FLAG_DSOBJECT) ) {
  1009. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  1010. }
  1011. *ppObject = (PSCE_OBJECT_SECURITY)ScepAlloc(0, sizeof(SCE_OBJECT_SECURITY));
  1012. if ( *ppObject == NULL )
  1013. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1014. else {
  1015. (*ppObject)->Name = Strvalue;
  1016. (*ppObject)->Status = (BYTE)Status;
  1017. (*ppObject)->IsContainer = TRUE; // always default to TRUE
  1018. (*ppObject)->pSecurityDescriptor = pTempSD;
  1019. (*ppObject)->SeInfo = SeInfo;
  1020. pTempSD = NULL;
  1021. // (*ppObject)->SDspec = SDspec;
  1022. // (*ppObject)->SDsize = SDsize;
  1023. Strvalue = NULL;
  1024. // SDspec = NULL;
  1025. rc = SCESTATUS_SUCCESS;
  1026. }
  1027. } else {
  1028. ScepBuildErrorLogInfo(rc,
  1029. Errlog,
  1030. SCEERR_BUILD_SD,
  1031. Strvalue);
  1032. rc = ScepDosErrorToSceStatus(rc);
  1033. }
  1034. } else
  1035. rc = SCESTATUS_BAD_FORMAT;
  1036. } else
  1037. rc = SCESTATUS_BAD_FORMAT;
  1038. }
  1039. } else
  1040. rc = SCESTATUS_BAD_FORMAT;
  1041. Done:
  1042. if ( Strvalue != NULL )
  1043. ScepFree( Strvalue );
  1044. if ( SDspec != NULL )
  1045. ScepFree( SDspec );
  1046. if ( pTempSD != NULL )
  1047. ScepFree( pTempSD );
  1048. return(rc);
  1049. }
  1050. SCESTATUS
  1051. SceInfpGetAuditing(
  1052. IN HINF hInf,
  1053. IN DWORD ObjectFlag,
  1054. OUT PSCE_PROFILE_INFO pSCEinfo,
  1055. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1056. )
  1057. /* ++
  1058. Routine Description:
  1059. This routine retrieves system auditing information from the INF file and
  1060. storesin the output buffer pSCEinfo. The auditing information is stored in
  1061. [System Log], [Security Log], [Application Log], [Event Audit],
  1062. [Registry Audit], and [File Audit] sections.
  1063. Arguments:
  1064. hInf - INF handle to the profile
  1065. pSCEinfo - the output buffer to hold SCP profile info.
  1066. Errlog - The cummulative error list to hold errors encountered in this routine.
  1067. Return value:
  1068. SCESTATUS - SCESTATUS_SUCCESS
  1069. SCESTATUS_NOT_ENOUGH_RESOURCE
  1070. SCESTATUS_INVALID_PARAMETER
  1071. SCESTATUS_BAD_FORMAT
  1072. SCESTATUS_INVALID_DATA
  1073. -- */
  1074. {
  1075. INFCONTEXT InfLine;
  1076. SCESTATUS rc=SCESTATUS_SUCCESS;
  1077. DWORD Keyvalue;
  1078. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  1079. DWORD LogSize;
  1080. DWORD Periods;
  1081. DWORD RetentionDays;
  1082. DWORD RestrictGuest;
  1083. PCWSTR szAuditLog;
  1084. DWORD i;
  1085. for ( i=0; i<3; i++ ) {
  1086. //
  1087. // Get Event Log setting for system log, security log and application log
  1088. //
  1089. switch (i) {
  1090. case 0:
  1091. szAuditLog = szAuditSystemLog;
  1092. break;
  1093. case 1:
  1094. szAuditLog = szAuditSecurityLog;
  1095. break;
  1096. default:
  1097. szAuditLog = szAuditApplicationLog;
  1098. break;
  1099. }
  1100. LogSize=SCE_NO_VALUE;
  1101. Periods=SCE_NO_VALUE;
  1102. RetentionDays=SCE_NO_VALUE;
  1103. RestrictGuest=SCE_NO_VALUE;
  1104. rc = SceInfpGetAuditLogSetting(
  1105. hInf,
  1106. szAuditLog,
  1107. ObjectFlag,
  1108. &LogSize,
  1109. &Periods,
  1110. &RetentionDays,
  1111. &RestrictGuest,
  1112. Errlog
  1113. );
  1114. if ( rc != SCESTATUS_SUCCESS )
  1115. return(rc);
  1116. pSCEinfo->MaximumLogSize[i] = LogSize;
  1117. pSCEinfo->AuditLogRetentionPeriod[i] = Periods;
  1118. pSCEinfo->RetentionDays[i] = RetentionDays;
  1119. pSCEinfo->RestrictGuestAccess[i] = RestrictGuest;
  1120. }
  1121. //
  1122. // Get Audit Event info
  1123. //
  1124. if ( SetupFindFirstLine(hInf,szAuditEvent,NULL,&InfLine) ) {
  1125. do {
  1126. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  1127. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) &&
  1128. SetupGetIntField( &InfLine, 1, (INT *)&Keyvalue )
  1129. ) {
  1130. if ( _wcsicmp(Keyname, TEXT("AuditSystemEvents")) == 0 ) {
  1131. pSCEinfo->AuditSystemEvents = Keyvalue;
  1132. } else if ( _wcsicmp(Keyname, TEXT("AuditLogonEvents")) == 0 ) {
  1133. pSCEinfo->AuditLogonEvents = Keyvalue;
  1134. } else if ( _wcsicmp(Keyname, TEXT("AuditObjectAccess")) == 0 ) {
  1135. pSCEinfo->AuditObjectAccess = Keyvalue;
  1136. } else if ( _wcsicmp(Keyname, TEXT("AuditPrivilegeUse")) == 0 ) {
  1137. pSCEinfo->AuditPrivilegeUse = Keyvalue;
  1138. } else if ( _wcsicmp(Keyname, TEXT("AuditPolicyChange")) == 0 ) {
  1139. pSCEinfo->AuditPolicyChange = Keyvalue;
  1140. } else if ( _wcsicmp(Keyname, TEXT("AuditAccountManage")) == 0 ) {
  1141. pSCEinfo->AuditAccountManage = Keyvalue;
  1142. } else if ( _wcsicmp(Keyname, TEXT("AuditProcessTracking")) == 0 ) {
  1143. pSCEinfo->AuditProcessTracking = Keyvalue;
  1144. } else if ( _wcsicmp(Keyname, TEXT("AuditDSAccess")) == 0 ) {
  1145. pSCEinfo->AuditDSAccess = Keyvalue;
  1146. } else if ( _wcsicmp(Keyname, TEXT("AuditAccountLogon")) == 0 ) {
  1147. pSCEinfo->AuditAccountLogon = Keyvalue;
  1148. } else if ( _wcsicmp(Keyname, TEXT("CrashOnAuditFull")) == 0 ) {
  1149. pSCEinfo->CrashOnAuditFull = Keyvalue;
  1150. } else if ( !(ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION) ) {
  1151. ScepBuildErrorLogInfo(0, Errlog,
  1152. SCEERR_NOT_EXPECTED,
  1153. Keyname, szAuditEvent);
  1154. }
  1155. } else {
  1156. rc = SCESTATUS_BAD_FORMAT;
  1157. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT,
  1158. Errlog,
  1159. SCEERR_QUERY_INFO,
  1160. szAuditEvent
  1161. );
  1162. return(rc);
  1163. }
  1164. } while(SetupFindNextLine(&InfLine, &InfLine));
  1165. }
  1166. return(rc);
  1167. }
  1168. SCESTATUS
  1169. SceInfpGetAuditLogSetting(
  1170. IN HINF hInf,
  1171. IN PCWSTR SectionName,
  1172. IN DWORD ObjectFlag,
  1173. OUT PDWORD LogSize,
  1174. OUT PDWORD Periods,
  1175. OUT PDWORD RetentionDays,
  1176. OUT PDWORD RestrictGuest,
  1177. IN OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1178. )
  1179. /* ++
  1180. Routine Description:
  1181. This routine retrieves audit log setting from the INF file based on the
  1182. SectionName passed in. The audit log settings include MaximumSize,
  1183. RetentionPeriod and RetentionDays. There are 3 different logs (system,
  1184. security, and application) which all have the same setting. The information
  1185. returned in in LogSize, Periods, RetentionDays. These 3 output arguments will
  1186. be reset to SCE_NO_VALUE at the begining of the routine. So if error
  1187. occurs after the reset, the original values won't be set back.
  1188. Arguments:
  1189. hInf - INF handle to the profile
  1190. SectionName - Log section name (SAdtSystemLog, SAdtSecurityLog, SAdtApplicationLog)
  1191. LogSize - The maximum size of the log
  1192. Periods - The retention period of the log
  1193. RetentionDays - The number of days for log retention
  1194. Return value:
  1195. SCESTATUS - SCESTATUS_SUCCESS
  1196. SCESTATUS_NOT_ENOUGH_RESOURCE
  1197. SCESTATUS_INVALID_PARAMETER
  1198. SCESTATUS_BAD_FORMAT
  1199. SCESTATUS_INVALID_DATA
  1200. -- */
  1201. {
  1202. INFCONTEXT InfLine;
  1203. SCESTATUS rc=SCESTATUS_SUCCESS;
  1204. DWORD Keyvalue;
  1205. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  1206. *LogSize = SCE_NO_VALUE;
  1207. *Periods = SCE_NO_VALUE;
  1208. *RetentionDays = SCE_NO_VALUE;
  1209. if ( SetupFindFirstLine(hInf,SectionName,NULL,&InfLine) ) {
  1210. do {
  1211. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  1212. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) &&
  1213. SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue)
  1214. ) {
  1215. if ( _wcsicmp(Keyname, TEXT("MaximumLogSize")) == 0 )
  1216. *LogSize = Keyvalue;
  1217. else if (_wcsicmp(Keyname, TEXT("AuditLogRetentionPeriod")) == 0 )
  1218. *Periods = Keyvalue;
  1219. else if (_wcsicmp(Keyname, TEXT("RetentionDays")) == 0 )
  1220. *RetentionDays = Keyvalue;
  1221. else if (_wcsicmp(Keyname, TEXT("RestrictGuestAccess")) == 0 )
  1222. *RestrictGuest = Keyvalue;
  1223. else if ( !(ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION) ) {
  1224. ScepBuildErrorLogInfo(0, Errlog,
  1225. SCEERR_NOT_EXPECTED,
  1226. Keyname, SectionName);
  1227. }
  1228. } else {
  1229. rc = SCESTATUS_BAD_FORMAT;
  1230. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT, Errlog,
  1231. SCEERR_QUERY_INFO,
  1232. SectionName
  1233. );
  1234. }
  1235. if ( rc != SCESTATUS_SUCCESS )
  1236. break;
  1237. } while(SetupFindNextLine(&InfLine, &InfLine));
  1238. }
  1239. return(rc);
  1240. }
  1241. SCESTATUS
  1242. SceInfpGetUserSection(
  1243. IN HINF hInf,
  1244. IN PWSTR Name,
  1245. OUT PSCE_USER_PROFILE *pOneProfile,
  1246. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1247. )
  1248. {
  1249. INFCONTEXT InfLine;
  1250. SCESTATUS rc=SCESTATUS_SUCCESS;
  1251. PSCE_LOGON_HOUR pLogonHour=NULL;
  1252. PWSTR SectionName=NULL;
  1253. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  1254. DWORD Keyvalue;
  1255. DWORD Keyvalue2;
  1256. PWSTR Strvalue=NULL;
  1257. DWORD DataSize;
  1258. DWORD i, cFields;
  1259. LONG i1,i2;
  1260. PSECURITY_DESCRIPTOR pTempSD=NULL;
  1261. SECURITY_INFORMATION SeInfo;
  1262. if ( hInf == NULL || Name == NULL || pOneProfile == NULL )
  1263. return(SCESTATUS_INVALID_PARAMETER);
  1264. SectionName = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (wcslen(Name)+9)*sizeof(WCHAR));
  1265. if ( SectionName == NULL )
  1266. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  1267. swprintf(SectionName, L"UserProfile %s", Name );
  1268. if ( SetupFindFirstLine(hInf, SectionName, NULL, &InfLine) ) {
  1269. //
  1270. // find the detail profile section. Allocate memory
  1271. //
  1272. *pOneProfile = (PSCE_USER_PROFILE)ScepAlloc( 0, sizeof(SCE_USER_PROFILE));
  1273. if ( *pOneProfile == NULL ) {
  1274. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1275. goto Done;
  1276. }
  1277. //
  1278. // initialize
  1279. //
  1280. (*pOneProfile)->Type = SCE_STRUCT_PROFILE;
  1281. (*pOneProfile)->ForcePasswordChange = SCE_NO_VALUE;
  1282. (*pOneProfile)->DisallowPasswordChange = SCE_NO_VALUE;
  1283. (*pOneProfile)->NeverExpirePassword = SCE_NO_VALUE;
  1284. (*pOneProfile)->AccountDisabled = SCE_NO_VALUE;
  1285. (*pOneProfile)->UserProfile = NULL;
  1286. (*pOneProfile)->LogonScript = NULL;
  1287. (*pOneProfile)->HomeDir = NULL;
  1288. (*pOneProfile)->pLogonHours = NULL;
  1289. (*pOneProfile)->pWorkstations.Length = 0;
  1290. (*pOneProfile)->pWorkstations.MaximumLength = 0;
  1291. (*pOneProfile)->pWorkstations.Buffer = NULL;
  1292. (*pOneProfile)->pGroupsBelongsTo = NULL;
  1293. (*pOneProfile)->pAssignToUsers = NULL;
  1294. (*pOneProfile)->pHomeDirSecurity = NULL;
  1295. (*pOneProfile)->HomeSeInfo = 0;
  1296. (*pOneProfile)->pTempDirSecurity = NULL;
  1297. (*pOneProfile)->TempSeInfo = 0;
  1298. do {
  1299. rc = SCESTATUS_BAD_FORMAT;
  1300. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  1301. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  1302. if ( _wcsicmp(Keyname, TEXT("DisallowPasswordChange")) == 0 ) {
  1303. //
  1304. // Int Field
  1305. //
  1306. if ( SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue ) ) {
  1307. (*pOneProfile)->DisallowPasswordChange = Keyvalue;
  1308. rc = SCESTATUS_SUCCESS;
  1309. }
  1310. goto NextLine;
  1311. }
  1312. if ( _wcsicmp(Keyname, TEXT("PasswordChangeStyle")) == 0 ) {
  1313. //
  1314. // Int Field
  1315. //
  1316. if ( SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue ) ) {
  1317. rc = SCESTATUS_SUCCESS;
  1318. switch (Keyvalue ) {
  1319. case 1:
  1320. (*pOneProfile)->NeverExpirePassword = 1;
  1321. (*pOneProfile)->ForcePasswordChange = 0;
  1322. break;
  1323. case 2:
  1324. (*pOneProfile)->NeverExpirePassword = 0;
  1325. (*pOneProfile)->ForcePasswordChange = 1;
  1326. break;
  1327. case 0:
  1328. // SCE_NO_VALUE for both. same as initialization
  1329. break;
  1330. default:
  1331. rc = SCESTATUS_INVALID_DATA;
  1332. break;
  1333. }
  1334. }
  1335. goto NextLine;
  1336. }
  1337. if ( _wcsicmp(Keyname, TEXT("AccountDisabled")) == 0 ) {
  1338. //
  1339. // Int Field
  1340. //
  1341. if ( SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue ) ) {
  1342. (*pOneProfile)->AccountDisabled = Keyvalue == 0 ? 0 : 1;
  1343. rc = SCESTATUS_SUCCESS;
  1344. }
  1345. goto NextLine;
  1346. }
  1347. if ( _wcsicmp(Keyname, TEXT("UserProfile")) == 0 ) {
  1348. //
  1349. // String Field
  1350. //
  1351. if( SetupGetStringField(&InfLine,1,NULL,0,&DataSize) ) {
  1352. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1353. (DataSize+1)*sizeof(WCHAR));
  1354. if( Strvalue == NULL ) {
  1355. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1356. } else {
  1357. if(SetupGetStringField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1358. (*pOneProfile)->UserProfile = Strvalue;
  1359. rc = SCESTATUS_SUCCESS;
  1360. } else
  1361. ScepFree( Strvalue );
  1362. }
  1363. }
  1364. goto NextLine;
  1365. }
  1366. if ( _wcsicmp(Keyname, TEXT("LogonScript")) == 0 ) {
  1367. //
  1368. // String Field
  1369. //
  1370. if(SetupGetStringField(&InfLine,1,NULL,0,&DataSize) ) {
  1371. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1372. (DataSize+1)*sizeof(WCHAR));
  1373. if( Strvalue == NULL ) {
  1374. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1375. } else {
  1376. if(SetupGetStringField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1377. (*pOneProfile)->LogonScript = Strvalue;
  1378. rc = SCESTATUS_SUCCESS;
  1379. } else
  1380. ScepFree( Strvalue );
  1381. }
  1382. }
  1383. goto NextLine;
  1384. }
  1385. if ( _wcsicmp(Keyname, TEXT("HomeDir")) == 0 ) {
  1386. //
  1387. // String Field
  1388. //
  1389. if(SetupGetStringField(&InfLine,1,NULL,0,&DataSize) ) {
  1390. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1391. (DataSize+1)*sizeof(WCHAR));
  1392. if( Strvalue == NULL ) {
  1393. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1394. } else {
  1395. if(SetupGetStringField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1396. (*pOneProfile)->HomeDir = Strvalue;
  1397. rc = SCESTATUS_SUCCESS;
  1398. } else
  1399. ScepFree( Strvalue );
  1400. }
  1401. }
  1402. goto NextLine;
  1403. }
  1404. if ( _wcsicmp(Keyname, TEXT("LogonHours")) == 0 ) {
  1405. //
  1406. // Int fields (in pairs). Each pair represents a logon hour range
  1407. //
  1408. cFields = SetupGetFieldCount( &InfLine );
  1409. //
  1410. // The first field is the key. Logon hour ranges must be in pairs
  1411. //
  1412. if ( cFields < 2 ) {
  1413. pLogonHour = (PSCE_LOGON_HOUR)ScepAlloc( LMEM_ZEROINIT,
  1414. sizeof(SCE_LOGON_HOUR) );
  1415. if ( pLogonHour == NULL ) {
  1416. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1417. goto NextLine;
  1418. }
  1419. pLogonHour->Start = SCE_NO_VALUE;
  1420. pLogonHour->End = SCE_NO_VALUE;
  1421. pLogonHour->Next = (*pOneProfile)->pLogonHours;
  1422. (*pOneProfile)->pLogonHours = pLogonHour;
  1423. rc = SCESTATUS_SUCCESS;
  1424. goto NextLine;
  1425. }
  1426. for ( i=0; i<cFields; i+=2) {
  1427. if ( SetupGetIntField( &InfLine, i+1, (INT *)&Keyvalue ) &&
  1428. SetupGetIntField( &InfLine, i+2, (INT *)&Keyvalue2 ) ) {
  1429. //
  1430. // find a pair of logon hours.
  1431. //
  1432. pLogonHour = (PSCE_LOGON_HOUR)ScepAlloc( LMEM_ZEROINIT,
  1433. sizeof(SCE_LOGON_HOUR) );
  1434. if ( pLogonHour == NULL ) {
  1435. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1436. goto NextLine;
  1437. }
  1438. pLogonHour->Start = Keyvalue;
  1439. pLogonHour->End = Keyvalue2;
  1440. pLogonHour->Next = (*pOneProfile)->pLogonHours;
  1441. (*pOneProfile)->pLogonHours = pLogonHour;
  1442. rc = SCESTATUS_SUCCESS;
  1443. } else
  1444. rc = SCESTATUS_INVALID_DATA;
  1445. }
  1446. goto NextLine;
  1447. }
  1448. if ( _wcsicmp(Keyname, TEXT("Workstations")) == 0 ) {
  1449. if( SetupGetMultiSzField(&InfLine,1,NULL,0,&DataSize) ) {
  1450. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1451. (DataSize+1)*sizeof(WCHAR));
  1452. if( Strvalue == NULL ) {
  1453. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1454. } else {
  1455. if(SetupGetMultiSzField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1456. (*pOneProfile)->pWorkstations.Length = (USHORT)(DataSize*sizeof(WCHAR));
  1457. (*pOneProfile)->pWorkstations.Buffer = Strvalue;
  1458. Strvalue = NULL;
  1459. rc = SCESTATUS_SUCCESS;
  1460. } else {
  1461. rc = SCESTATUS_INVALID_DATA;
  1462. ScepFree(Strvalue);
  1463. }
  1464. }
  1465. }
  1466. goto NextLine;
  1467. }
  1468. i1 = i2 = 0;
  1469. if ( (i1=_wcsicmp(Keyname, TEXT("GroupsBelongsTo"))) == 0 ||
  1470. (i2=_wcsicmp(Keyname, TEXT("AssignToUsers"))) == 0 ) {
  1471. //
  1472. // String fields. Each string respresents a workstation name,
  1473. // a group name, or a user name. These names are saved in PSCE_NAME_LIST
  1474. //
  1475. cFields = SetupGetFieldCount( &InfLine );
  1476. for ( i=0; i<cFields; i++) {
  1477. if( SetupGetStringField(&InfLine,i+1,NULL,0,&DataSize) && DataSize > 0 ) {
  1478. if ( DataSize <= 1) {
  1479. rc = SCESTATUS_SUCCESS;
  1480. continue;
  1481. }
  1482. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1483. (DataSize+1)*sizeof(WCHAR));
  1484. if( Strvalue == NULL ) {
  1485. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1486. } else {
  1487. if(SetupGetStringField(&InfLine,i+1,Strvalue,DataSize,NULL)) {
  1488. //
  1489. // Save information in a name list
  1490. //
  1491. if ( i1 == 0) {
  1492. rc = ScepAddToNameList(&((*pOneProfile)->pGroupsBelongsTo),
  1493. Strvalue,
  1494. DataSize+1
  1495. );
  1496. } else {
  1497. rc = ScepAddToNameList(&((*pOneProfile)->pAssignToUsers),
  1498. Strvalue,
  1499. DataSize+1
  1500. );
  1501. }
  1502. if ( rc != NO_ERROR )
  1503. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1504. }
  1505. ScepFree( Strvalue );
  1506. }
  1507. }
  1508. if ( rc != SCESTATUS_SUCCESS)
  1509. break; // for loop
  1510. }
  1511. goto NextLine;
  1512. }
  1513. i1 = i2 = 0;
  1514. if ( (i1=_wcsicmp(Keyname, TEXT("HomeDirSecurity"))) == 0 ||
  1515. (i2=_wcsicmp(Keyname, TEXT("TempDirSecurity"))) == 0 ) {
  1516. // if(SetupGetStringField(&InfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
  1517. if(SetupGetMultiSzField(&InfLine,1,NULL,0,&DataSize) && DataSize > 0 ) {
  1518. Strvalue = (PWSTR)ScepAlloc( 0, (DataSize+1)*sizeof(WCHAR));
  1519. if ( Strvalue == NULL )
  1520. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1521. else {
  1522. // if(SetupGetStringField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1523. if(SetupGetMultiSzField(&InfLine,1,Strvalue,DataSize,NULL)) {
  1524. //
  1525. // convert multi-sz to space
  1526. //
  1527. if ( SetupGetFieldCount( &InfLine ) > 1 ) {
  1528. ScepConvertMultiSzToDelim(Strvalue, DataSize, L'\0', L' ');
  1529. }
  1530. //
  1531. // Convert the text to real security descriptors
  1532. //
  1533. rc = ConvertTextSecurityDescriptor(
  1534. Strvalue,
  1535. &pTempSD,
  1536. &Keyvalue2,
  1537. &SeInfo
  1538. );
  1539. if (rc == NO_ERROR) {
  1540. ScepChangeAclRevision(pTempSD, ACL_REVISION);
  1541. if ( i1 == 0 ) {
  1542. (*pOneProfile)->pHomeDirSecurity = pTempSD;
  1543. (*pOneProfile)->HomeSeInfo = SeInfo;
  1544. } else {
  1545. (*pOneProfile)->pTempDirSecurity = pTempSD;
  1546. (*pOneProfile)->TempSeInfo = SeInfo;
  1547. }
  1548. pTempSD = NULL;
  1549. } else {
  1550. ScepBuildErrorLogInfo(
  1551. rc,
  1552. Errlog,
  1553. SCEERR_BUILD_SD,
  1554. Keyname //Strvalue
  1555. );
  1556. rc = ScepDosErrorToSceStatus(rc);
  1557. }
  1558. } else
  1559. rc = SCESTATUS_INVALID_DATA;
  1560. ScepFree(Strvalue);
  1561. }
  1562. }
  1563. goto NextLine;
  1564. }
  1565. //
  1566. // no string matched. ignore
  1567. //
  1568. ScepBuildErrorLogInfo(
  1569. NO_ERROR,
  1570. Errlog,
  1571. SCEERR_NOT_EXPECTED,
  1572. Keyname, SectionName);
  1573. rc = SCESTATUS_SUCCESS;
  1574. }
  1575. NextLine:
  1576. if ( rc != SCESTATUS_SUCCESS ) {
  1577. ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc),
  1578. Errlog,
  1579. SCEERR_QUERY_INFO,
  1580. SectionName
  1581. );
  1582. goto Done;
  1583. }
  1584. } while(SetupFindNextLine(&InfLine,&InfLine));
  1585. }
  1586. Done:
  1587. // free memory
  1588. if ( SectionName != NULL )
  1589. ScepFree(SectionName);
  1590. if ( pTempSD != NULL )
  1591. ScepFree( pTempSD );
  1592. if ( rc != SCESTATUS_SUCCESS ) {
  1593. // free pOneProfile memory
  1594. SceFreeMemory( *pOneProfile, 0 );
  1595. *pOneProfile = NULL;
  1596. }
  1597. return(rc);
  1598. }
  1599. SCESTATUS
  1600. SceInfpGetDescription(
  1601. IN HINF hInf,
  1602. OUT PWSTR *Description
  1603. )
  1604. {
  1605. INFCONTEXT InfLine;
  1606. SCESTATUS rc=SCESTATUS_SUCCESS;
  1607. DWORD LineLen, Len;
  1608. DWORD TotalLen=0;
  1609. DWORD i, cFields;
  1610. if(SetupFindFirstLine(hInf,szDescription,NULL,&InfLine)) {
  1611. do {
  1612. cFields = SetupGetFieldCount( &InfLine );
  1613. for ( i=0; i<cFields && rc==SCESTATUS_SUCCESS; i++) {
  1614. //
  1615. // count the total length of the description.
  1616. //
  1617. if ( !SetupGetStringField(&InfLine, i+1, NULL, 0, &LineLen) ) {
  1618. rc = SCESTATUS_BAD_FORMAT;
  1619. }
  1620. TotalLen += LineLen+1;
  1621. LineLen = 0;
  1622. }
  1623. if ( rc != SCESTATUS_SUCCESS )
  1624. break;
  1625. } while ( SetupFindNextLine(&InfLine,&InfLine) );
  1626. if ( rc == SCESTATUS_SUCCESS && TotalLen > 0 ) {
  1627. //
  1628. // allocate memory for the return buffer
  1629. //
  1630. *Description = (PWSTR)ScepAlloc( LMEM_ZEROINIT, (TotalLen+1)*sizeof(WCHAR));
  1631. if ( *Description == NULL )
  1632. return( SCESTATUS_NOT_ENOUGH_RESOURCE );
  1633. // re-position to the first line
  1634. SetupFindFirstLine(hInf,szDescription,NULL,&InfLine);
  1635. Len = 0;
  1636. LineLen = 0;
  1637. do {
  1638. //
  1639. // read each line in the section and append to the end of the buffer
  1640. // note: the required size returned from SetupGetStringField already
  1641. // has one more character space.
  1642. //
  1643. cFields = SetupGetFieldCount( &InfLine );
  1644. for ( i=0; i<cFields && rc==SCESTATUS_SUCCESS; i++) {
  1645. if ( !SetupGetStringField(&InfLine, i+1,
  1646. *Description+Len, TotalLen-Len, &LineLen) ) {
  1647. rc = SCESTATUS_INVALID_DATA;
  1648. }
  1649. if ( i == cFields-1)
  1650. *(*Description+Len+LineLen-1) = L' ';
  1651. else
  1652. *(*Description+Len+LineLen-1) = L',';
  1653. Len += LineLen;
  1654. }
  1655. if ( rc != SCESTATUS_SUCCESS )
  1656. break;
  1657. } while ( SetupFindNextLine(&InfLine,&InfLine) );
  1658. }
  1659. if ( rc != SCESTATUS_SUCCESS ) {
  1660. // if error occurs, free memory
  1661. ScepFree(*Description);
  1662. *Description = NULL;
  1663. }
  1664. } else {
  1665. rc = SCESTATUS_RECORD_NOT_FOUND;
  1666. }
  1667. return(rc);
  1668. }
  1669. SCESTATUS
  1670. SceInfpGetSystemServices(
  1671. IN HINF hInf,
  1672. IN DWORD ObjectFlag,
  1673. OUT PSCE_SERVICES *pServiceList,
  1674. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1675. )
  1676. /*
  1677. Routine Description:
  1678. Get the list of services with startup status and security descriptors
  1679. in the inf file
  1680. Arguments:
  1681. Return Value:
  1682. */
  1683. {
  1684. INFCONTEXT InfLine;
  1685. SCESTATUS rc=SCESTATUS_SUCCESS;
  1686. PWSTR Keyname=NULL;
  1687. DWORD KeyLen;
  1688. DWORD Status;
  1689. DWORD DataSize;
  1690. PWSTR Strvalue=NULL;
  1691. SECURITY_INFORMATION SeInfo;
  1692. PSECURITY_DESCRIPTOR pSecurityDescriptor=NULL;
  1693. DWORD cFields=0;
  1694. if ( pServiceList == NULL )
  1695. return(SCESTATUS_INVALID_PARAMETER);
  1696. //
  1697. // Locate the [Service General Setting] section.
  1698. //
  1699. if ( SetupFindFirstLine(hInf,szServiceGeneral,NULL,&InfLine) ) {
  1700. TCHAR tmpBuf[MAX_PATH];
  1701. do {
  1702. //
  1703. // Get service names.
  1704. //
  1705. rc = SCESTATUS_BAD_FORMAT;
  1706. cFields = SetupGetFieldCount( &InfLine );
  1707. if ( cFields < 3 ) {
  1708. tmpBuf[0] = L'\0';
  1709. SetupGetStringField(&InfLine,1,tmpBuf,MAX_PATH,NULL);
  1710. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  1711. Errlog,
  1712. SCEERR_OBJECT_FIELDS,
  1713. tmpBuf);
  1714. if ( ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION ) {
  1715. //
  1716. // a newer version of template, ignore this line
  1717. //
  1718. rc = SCESTATUS_SUCCESS;
  1719. goto NextLine;
  1720. } else {
  1721. //
  1722. // bad format, quit
  1723. //
  1724. break;
  1725. }
  1726. }
  1727. if ( SetupGetStringField(&InfLine, 1, NULL, 0, &KeyLen) ) {
  1728. Keyname = (PWSTR)ScepAlloc( 0, (KeyLen+1)*sizeof(WCHAR));
  1729. if ( Keyname != NULL ) {
  1730. Keyname[KeyLen] = L'\0';
  1731. if ( SetupGetStringField(&InfLine, 1, Keyname, KeyLen, NULL) ) {
  1732. //
  1733. // Get value (startup status, security descriptor SDDL)
  1734. //
  1735. if ( SetupGetIntField(&InfLine, 2, (INT *)&Status) &&
  1736. // SetupGetStringField(&InfLine,3,NULL,0,&DataSize) && DataSize > 0 ) {
  1737. SetupGetMultiSzField(&InfLine,3,NULL,0,&DataSize) && DataSize > 0 ) {
  1738. Strvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  1739. (DataSize+1)*sizeof(WCHAR) );
  1740. if( Strvalue != NULL ) {
  1741. // if(SetupGetStringField(&InfLine,3,Strvalue,DataSize,NULL)) {
  1742. if(SetupGetMultiSzField(&InfLine,3,Strvalue,DataSize,NULL)) {
  1743. //
  1744. // convert multi-sz to space
  1745. //
  1746. if ( cFields > 3 ) {
  1747. ScepConvertMultiSzToDelim(Strvalue, DataSize, L'\0', L' ');
  1748. }
  1749. if ( ObjectFlag & SCEINF_OBJECT_FLAG_OLDSDDL ) {
  1750. ScepConvertToSDDLFormat(Strvalue, DataSize);
  1751. }
  1752. //
  1753. // Convert to security descriptor
  1754. //
  1755. rc = ConvertTextSecurityDescriptor(
  1756. Strvalue,
  1757. &pSecurityDescriptor,
  1758. &DataSize,
  1759. &SeInfo
  1760. );
  1761. if ( rc == SCESTATUS_SUCCESS ) {
  1762. ScepChangeAclRevision(pSecurityDescriptor, ACL_REVISION);
  1763. //
  1764. // add to the service list
  1765. //
  1766. rc = ScepAddOneServiceToList(
  1767. Keyname,
  1768. NULL,
  1769. Status,
  1770. (PVOID)pSecurityDescriptor,
  1771. SeInfo,
  1772. TRUE,
  1773. pServiceList
  1774. );
  1775. if ( rc != ERROR_SUCCESS) {
  1776. LocalFree(pSecurityDescriptor);
  1777. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1778. }
  1779. }
  1780. }
  1781. ScepFree( Strvalue );
  1782. Strvalue = NULL;
  1783. } else
  1784. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1785. }
  1786. }
  1787. //
  1788. // Free Keyname
  1789. //
  1790. ScepFree(Keyname);
  1791. Keyname = NULL;
  1792. } else
  1793. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  1794. }
  1795. if ( rc != SCESTATUS_SUCCESS ) {
  1796. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT,
  1797. Errlog,
  1798. SCEERR_QUERY_INFO,
  1799. szServiceGeneral
  1800. );
  1801. break;
  1802. }
  1803. NextLine:
  1804. ;
  1805. } while(SetupFindNextLine(&InfLine,&InfLine));
  1806. }
  1807. if ( rc != SCESTATUS_SUCCESS ) {
  1808. //
  1809. // free the service list
  1810. //
  1811. SceFreePSCE_SERVICES(*pServiceList);
  1812. *pServiceList = NULL;
  1813. }
  1814. return(rc);
  1815. }
  1816. SCESTATUS
  1817. SceInfpGetKerberosPolicy(
  1818. IN HINF hInf,
  1819. IN DWORD ObjectFlag,
  1820. OUT PSCE_KERBEROS_TICKET_INFO * ppKerberosInfo,
  1821. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1822. )
  1823. /*++
  1824. Routine Description:
  1825. This routine retrieves kerberos policy information from the SCP INF
  1826. file and stores in the output buffer ppKerberosInfo.
  1827. Arguments:
  1828. hInf - INF handle to the profile
  1829. ppKerberosInfo - the output buffer to hold kerberos info.
  1830. Errlog - A buffer to hold all error codes/text encountered when
  1831. parsing the INF file. If Errlog is NULL, no further error
  1832. information is returned except the return DWORD
  1833. Return value:
  1834. SCESTATUS - SCESTATUS_SUCCESS
  1835. SCESTATUS_NOT_ENOUGH_RESOURCE
  1836. SCESTATUS_INVALID_PARAMETER
  1837. SCESTATUS_BAD_FORMAT
  1838. SCESTATUS_INVALID_DATA
  1839. --*/
  1840. {
  1841. INFCONTEXT InfLine;
  1842. SCESTATUS rc=SCESTATUS_SUCCESS;
  1843. SCE_KEY_LOOKUP AccessSCPLookup[] = {
  1844. {(PWSTR)TEXT("MaxTicketAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxTicketAge), 'D'},
  1845. {(PWSTR)TEXT("MaxRenewAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxRenewAge), 'D'},
  1846. {(PWSTR)TEXT("MaxServiceAge"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxServiceAge), 'D'},
  1847. {(PWSTR)TEXT("MaxClockSkew"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, MaxClockSkew), 'D'},
  1848. {(PWSTR)TEXT("TicketValidateClient"), offsetof(struct _SCE_KERBEROS_TICKET_INFO_, TicketValidateClient), 'D'}
  1849. };
  1850. DWORD cAccess = sizeof(AccessSCPLookup) / sizeof(SCE_KEY_LOOKUP);
  1851. //
  1852. // check arguments
  1853. //
  1854. if ( !hInf || !ppKerberosInfo ) {
  1855. return (SCESTATUS_INVALID_PARAMETER);
  1856. }
  1857. BOOL bAllocated = FALSE;
  1858. //
  1859. // Locate the [Kerberos Policy] section.
  1860. //
  1861. if(SetupFindFirstLine(hInf,szKerberosPolicy,NULL,&InfLine)) {
  1862. //
  1863. // allocate the output buffer if it is NULL
  1864. //
  1865. if ( NULL == *ppKerberosInfo ) {
  1866. *ppKerberosInfo = (PSCE_KERBEROS_TICKET_INFO)ScepAlloc(0, sizeof(SCE_KERBEROS_TICKET_INFO));
  1867. if ( NULL == *ppKerberosInfo ) {
  1868. return (SCESTATUS_NOT_ENOUGH_RESOURCE);
  1869. }
  1870. bAllocated = TRUE;
  1871. }
  1872. //
  1873. // Initialize to SCE_NO_VALUE
  1874. //
  1875. for ( DWORD i=0; i<cAccess; i++) {
  1876. if ( AccessSCPLookup[i].BufferType == 'D' ) {
  1877. *((DWORD *)((CHAR *)(*ppKerberosInfo)+AccessSCPLookup[i].Offset)) = SCE_NO_VALUE;
  1878. }
  1879. }
  1880. UINT Offset;
  1881. WCHAR Keyname[SCE_KEY_MAX_LENGTH];
  1882. int Keyvalue=0;
  1883. do {
  1884. //
  1885. // Get key names and its setting.
  1886. //
  1887. rc = SCESTATUS_SUCCESS;
  1888. memset(Keyname, '\0', SCE_KEY_MAX_LENGTH*sizeof(WCHAR));
  1889. if ( SetupGetStringField(&InfLine, 0, Keyname, SCE_KEY_MAX_LENGTH, NULL) ) {
  1890. for ( i=0; i<cAccess; i++) {
  1891. //
  1892. // get settings in AccessLookup table
  1893. //
  1894. Offset = AccessSCPLookup[i].Offset;
  1895. if (_wcsicmp(Keyname, AccessSCPLookup[i].KeyString ) == 0) {
  1896. switch ( AccessSCPLookup[i].BufferType ) {
  1897. case 'D':
  1898. //
  1899. // Int Field
  1900. //
  1901. if (SetupGetIntField(&InfLine, 1, (INT *)&Keyvalue ) ) {
  1902. *((DWORD *)((CHAR *)(*ppKerberosInfo)+Offset)) = (DWORD)Keyvalue;
  1903. } else {
  1904. rc = SCESTATUS_INVALID_DATA;
  1905. }
  1906. break;
  1907. default:
  1908. //
  1909. // should not occur
  1910. //
  1911. break;
  1912. }
  1913. break; // for loop
  1914. }
  1915. }
  1916. if ( i >= cAccess &&
  1917. !(ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION) ) {
  1918. //
  1919. // Did not find a match in the lookup table
  1920. //
  1921. ScepBuildErrorLogInfo( NO_ERROR,
  1922. Errlog,
  1923. SCEERR_NOT_EXPECTED,
  1924. Keyname,szKerberosPolicy );
  1925. }
  1926. if ( rc != SCESTATUS_SUCCESS ) {
  1927. ScepBuildErrorLogInfo( ScepSceStatusToDosError(rc),
  1928. Errlog,
  1929. SCEERR_QUERY_INFO,
  1930. Keyname );
  1931. }
  1932. } else {
  1933. rc = SCESTATUS_BAD_FORMAT;
  1934. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT, Errlog,
  1935. SCEERR_QUERY_INFO,
  1936. szKerberosPolicy);
  1937. }
  1938. //
  1939. // if error happens, get out
  1940. //
  1941. if ( rc != SCESTATUS_SUCCESS ) {
  1942. break;
  1943. }
  1944. } while(SetupFindNextLine(&InfLine,&InfLine));
  1945. }
  1946. if ( SCESTATUS_SUCCESS != rc && bAllocated && *ppKerberosInfo ) {
  1947. //
  1948. // free allocated memory if error occurs
  1949. //
  1950. ScepFree(*ppKerberosInfo);
  1951. *ppKerberosInfo = NULL;
  1952. }
  1953. return(rc);
  1954. }
  1955. SCESTATUS
  1956. SceInfpGetRegistryValues(
  1957. IN HINF hInf,
  1958. IN DWORD ObjectFlag,
  1959. OUT PSCE_REGISTRY_VALUE_INFO * ppRegValues,
  1960. OUT LPDWORD pValueCount,
  1961. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  1962. )
  1963. /*++
  1964. Routine Description:
  1965. This routine retrieves kerberos policy information from the SCP INF
  1966. file and stores in the output buffer ppKerberosInfo.
  1967. Arguments:
  1968. hInf - INF handle to the profile
  1969. ppRegValues - the output array to hold registry values.
  1970. pValueCount - the buffer to hold number of registry values in the array
  1971. Errlog - A buffer to hold all error codes/text encountered when
  1972. parsing the INF file. If Errlog is NULL, no further error
  1973. information is returned except the return DWORD
  1974. Return value:
  1975. SCESTATUS - SCESTATUS_SUCCESS
  1976. SCESTATUS_NOT_ENOUGH_RESOURCE
  1977. SCESTATUS_INVALID_PARAMETER
  1978. SCESTATUS_BAD_FORMAT
  1979. SCESTATUS_INVALID_DATA
  1980. --*/
  1981. {
  1982. INFCONTEXT InfLine;
  1983. SCESTATUS rc=SCESTATUS_SUCCESS;
  1984. LONG i;
  1985. LONG nLines;
  1986. //
  1987. // check arguments
  1988. //
  1989. if ( !hInf || !ppRegValues || !pValueCount ) {
  1990. return (SCESTATUS_INVALID_PARAMETER);
  1991. }
  1992. //
  1993. // count how many objects
  1994. //
  1995. nLines = SetupGetLineCount(hInf, szRegistryValues );
  1996. if ( nLines == -1 ) {
  1997. //
  1998. // section not found
  1999. //
  2000. return(SCESTATUS_SUCCESS);
  2001. }
  2002. *pValueCount = nLines;
  2003. *ppRegValues = NULL;
  2004. if ( nLines == 0 ) {
  2005. //
  2006. // no value is to be secured
  2007. //
  2008. return(SCESTATUS_SUCCESS);
  2009. }
  2010. //
  2011. // allocate memory for all objects
  2012. //
  2013. *ppRegValues = (PSCE_REGISTRY_VALUE_INFO)ScepAlloc( LMEM_ZEROINIT,
  2014. nLines*sizeof(SCE_REGISTRY_VALUE_INFO) );
  2015. if ( *ppRegValues == NULL ) {
  2016. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2017. }
  2018. //
  2019. // Locate the section.
  2020. //
  2021. if ( SetupFindFirstLine(hInf,szRegistryValues,NULL,&InfLine) ) {
  2022. i = 0;
  2023. do {
  2024. //
  2025. // Get string key and a int value.
  2026. //
  2027. if ( i >= nLines ) {
  2028. //
  2029. // more lines than allocated
  2030. //
  2031. rc = SCESTATUS_INVALID_DATA;
  2032. ScepBuildErrorLogInfo(ERROR_INVALID_DATA,
  2033. Errlog,
  2034. SCEERR_MORE_OBJECTS,
  2035. nLines
  2036. );
  2037. break;
  2038. }
  2039. rc = SceInfpGetOneRegistryValue(
  2040. &InfLine,
  2041. ObjectFlag,
  2042. &((*ppRegValues)[i]),
  2043. Errlog
  2044. );
  2045. if ( SCESTATUS_SUCCESS == rc ) {
  2046. i++;
  2047. } else if ( ERROR_PRODUCT_VERSION == rc ) {
  2048. //
  2049. // a newer version, should ignore this line
  2050. //
  2051. rc = SCESTATUS_SUCCESS;
  2052. } else {
  2053. break; // do..while loop
  2054. }
  2055. } while(SetupFindNextLine(&InfLine,&InfLine));
  2056. }
  2057. if ( rc != SCESTATUS_SUCCESS ) {
  2058. //
  2059. // free memory
  2060. //
  2061. ScepFreeRegistryValues( ppRegValues, *pValueCount );
  2062. *ppRegValues = NULL;
  2063. } else {
  2064. *pValueCount = i;
  2065. }
  2066. return(rc);
  2067. }
  2068. SCESTATUS
  2069. SceInfpGetOneRegistryValue(
  2070. IN PINFCONTEXT pInfLine,
  2071. IN DWORD ObjectFlag,
  2072. OUT PSCE_REGISTRY_VALUE_INFO pValues,
  2073. OUT PSCE_ERROR_LOG_INFO *Errlog OPTIONAL
  2074. )
  2075. /* ++
  2076. Routine Description:
  2077. This routine retrieves one registry value from the INF file (SCP type).
  2078. Each registry value in these sections is represented by one line.
  2079. Arguments:
  2080. pInfLine - Current line context from the INF file for one object
  2081. pValues- Output buffer to hold the regitry value name and value
  2082. Errlog - The cummulative error list for errors encountered in this routine
  2083. Return value:
  2084. SCESTATUS - SCESTATUS_SUCCESS
  2085. SCESTATUS_NOT_ENOUGH_RESOURCE
  2086. SCESTATUS_INVALID_PARAMETER
  2087. SCESTATUS_BAD_FORMAT
  2088. SCESTATUS_INVALID_DATA
  2089. -- */
  2090. {
  2091. DWORD KeySize;
  2092. PWSTR Keyvalue=NULL;
  2093. SCESTATUS rc=SCESTATUS_SUCCESS;
  2094. INT dType;
  2095. PWSTR pValueStr=NULL;
  2096. DWORD nLen;
  2097. if ( !pInfLine || !pValues )
  2098. return(SCESTATUS_INVALID_PARAMETER);
  2099. nLen = SetupGetFieldCount( pInfLine );
  2100. if ( nLen < 2 ) {
  2101. TCHAR tmpBuf[MAX_PATH];
  2102. tmpBuf[0] = L'\0';
  2103. SetupGetStringField(pInfLine,0,tmpBuf,MAX_PATH,NULL);
  2104. ScepBuildErrorLogInfo( ERROR_INVALID_DATA,
  2105. Errlog,
  2106. SCEERR_REGVALUE_FIELDS,
  2107. tmpBuf);
  2108. //
  2109. // if it's a newer version template, should ignore this line
  2110. //
  2111. if ( ObjectFlag & SCEINF_OBJECT_FLAG_UNKNOWN_VERSION )
  2112. return(ERROR_PRODUCT_VERSION);
  2113. else
  2114. return(SCESTATUS_INVALID_DATA);
  2115. }
  2116. //
  2117. // get the key field (string)
  2118. //
  2119. if(SetupGetStringField(pInfLine,0,NULL,0,&KeySize) && KeySize > 0 ) {
  2120. Keyvalue = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  2121. (KeySize+1)*sizeof(WCHAR) );
  2122. if( Keyvalue == NULL ) {
  2123. return(SCESTATUS_NOT_ENOUGH_RESOURCE);
  2124. } else {
  2125. //
  2126. // get key
  2127. //
  2128. if( SetupGetStringField(pInfLine,0,Keyvalue,KeySize,NULL) ) {
  2129. //
  2130. // get the data type, if error, assume REG_DWORD type
  2131. //
  2132. if ( !SetupGetIntField( pInfLine, 1, (INT *)&dType ) ) {
  2133. dType = REG_DWORD;
  2134. }
  2135. if ( SetupGetMultiSzField(pInfLine,2,NULL,0,&nLen) ) {
  2136. pValueStr = (PWSTR)ScepAlloc( LMEM_ZEROINIT,
  2137. (nLen+1)*sizeof(WCHAR)
  2138. );
  2139. if( pValueStr == NULL ) {
  2140. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2141. } else if ( !SetupGetMultiSzField(pInfLine,2,pValueStr,nLen,NULL) ) {
  2142. rc = SCESTATUS_BAD_FORMAT;
  2143. } else {
  2144. if ( dType == REG_MULTI_SZ &&
  2145. (0 == _wcsicmp( Keyvalue, szLegalNoticeTextKeyName))) {
  2146. //
  2147. // check for commas and escape them with "," so the UI etc.
  2148. // understands this, since, here, for lines such as
  2149. // k=7,a",",b,c
  2150. // pValueStr will be a,\0b\0c\0\0 which we should make
  2151. // a","\0b\0c\0\0
  2152. //
  2153. DWORD dwCommaCount = 0;
  2154. for ( DWORD dwIndex = 0; dwIndex < nLen; dwIndex++) {
  2155. if ( pValueStr[dwIndex] == L',' )
  2156. dwCommaCount++;
  2157. }
  2158. if ( dwCommaCount > 0 ) {
  2159. PWSTR pValueStrEscaped;
  2160. DWORD dwNumBytes;
  2161. dwNumBytes = (nLen + 1 + dwCommaCount * 2) * sizeof(WCHAR);
  2162. pValueStrEscaped = (PWSTR)ScepAlloc(LMEM_ZEROINIT, dwNumBytes);
  2163. if (pValueStrEscaped) {
  2164. memset(pValueStrEscaped, '\0', dwNumBytes);
  2165. nLen = ScepEscapeString(pValueStr,
  2166. nLen+1,
  2167. L',',
  2168. L'"',
  2169. pValueStrEscaped
  2170. );
  2171. ScepFree(pValueStr);
  2172. pValueStr = pValueStrEscaped;
  2173. }
  2174. else {
  2175. rc = SCESTATUS_NOT_ENOUGH_RESOURCE;
  2176. }
  2177. }
  2178. }
  2179. if ( SCESTATUS_SUCCESS == rc)
  2180. rc = ScepConvertMultiSzToDelim(pValueStr, nLen, L'\0', L',');
  2181. if ( SCESTATUS_SUCCESS == rc) {
  2182. //
  2183. // assign them to the output buffer
  2184. //
  2185. pValues->FullValueName = Keyvalue;
  2186. Keyvalue = NULL;
  2187. pValues->ValueType = (DWORD)dType;
  2188. pValues->Value = pValueStr;
  2189. pValueStr = NULL;
  2190. }
  2191. }
  2192. } else {
  2193. rc = SCESTATUS_BAD_FORMAT;
  2194. }
  2195. } else
  2196. rc = SCESTATUS_BAD_FORMAT;
  2197. }
  2198. } else
  2199. rc = SCESTATUS_BAD_FORMAT;
  2200. if ( rc == SCESTATUS_BAD_FORMAT ) {
  2201. ScepBuildErrorLogInfo( ERROR_BAD_FORMAT,
  2202. Errlog,
  2203. SCEERR_QUERY_INFO,
  2204. szRegistryValues);
  2205. }
  2206. if ( Keyvalue != NULL )
  2207. ScepFree( Keyvalue );
  2208. if ( pValueStr != NULL ) {
  2209. ScepFree(pValueStr);
  2210. }
  2211. return(rc);
  2212. }
  2213. SCESTATUS
  2214. WINAPI
  2215. SceSvcGetInformationTemplate(
  2216. IN PCWSTR TemplateName,
  2217. IN PCWSTR ServiceName,
  2218. IN PCWSTR Key OPTIONAL,
  2219. OUT PSCESVC_CONFIGURATION_INFO *ServiceInfo
  2220. )
  2221. /*
  2222. Routine Description:
  2223. Read information from the service's section in the template (inf format) into
  2224. the ServiceInfo buffer. If Key is specified, only one key's information is read.
  2225. Arguments:
  2226. Template - The template's name (inf format)
  2227. ServiceName - The service's name as used in service control manager, is also the
  2228. section name used in the template
  2229. Key - if specified, it is the key information to match in the template;
  2230. if it is NULL, all information from the section is read
  2231. ServiceInfo - output buffer of a array of Key/Value pairs
  2232. Return Value:
  2233. */
  2234. {
  2235. HINF hInf;
  2236. SCESTATUS rc;
  2237. if ( TemplateName == NULL || ServiceName == NULL || ServiceInfo == NULL ) {
  2238. return(SCESTATUS_INVALID_PARAMETER);
  2239. }
  2240. //
  2241. // open the template
  2242. //
  2243. rc = SceInfpOpenProfile(
  2244. TemplateName,
  2245. &hInf
  2246. );
  2247. if ( rc != SCESTATUS_SUCCESS )
  2248. return(rc);
  2249. //
  2250. // call private API to read information.
  2251. //
  2252. rc = SceSvcpGetInformationTemplate(hInf,
  2253. ServiceName,
  2254. Key,
  2255. ServiceInfo );
  2256. //
  2257. // close the template
  2258. //
  2259. SceInfpCloseProfile(hInf);
  2260. return(rc);
  2261. }