Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

888 lines
28 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (c) Microsoft Corporation. All rights reserved.
  4. File: DEVWMI.C
  5. Contents:
  6. The purpose of this file is to establish security on driver while it is
  7. being installed on the system. The function SetupConfigureWmiFromInfSection
  8. is the external call that will establish security for a device when passed
  9. the [DDInstall.WMI] section and the appropriate INF and flags.
  10. Notes:
  11. To configure WMI security for downlevel platforms where the [DDInstall.WMI]
  12. section isn't natively supported by setupapi, a redistributable co-installer
  13. is supplied in the DDK for use on those platforms.
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include <sddl.h>
  18. #include <aclapi.h>
  19. #include <strsafe.h>
  20. //
  21. // ** Function Prototypes **
  22. //
  23. ULONG
  24. ParseSection(
  25. IN INFCONTEXT InfLineContext,
  26. IN OUT PTCHAR *GuidString,
  27. IN OUT ULONG *GuidStringLen,
  28. IN OUT PDWORD Flags,
  29. IN OUT PTCHAR *SectionNameString,
  30. IN OUT ULONG *SectionNameStringLen
  31. );
  32. ULONG
  33. EstablishGuidSecurity(
  34. IN PTCHAR GuidString,
  35. IN PTCHAR SDDLString,
  36. IN DWORD Flags
  37. );
  38. ULONG
  39. GetSecurityKeyword(
  40. IN HINF InfFile,
  41. IN LPCTSTR WMIINterfaceSection,
  42. IN OUT PTCHAR *SDDLString,
  43. IN OUT ULONG *SDDLStringLen
  44. );
  45. ULONG
  46. ParseSecurityDescriptor(
  47. IN PSECURITY_DESCRIPTOR SD,
  48. OUT PSECURITY_INFORMATION SecurityInformation,
  49. OUT PSID *Owner,
  50. OUT PSID *Group,
  51. OUT PACL *Dacl,
  52. OUT PACL *Sacl
  53. );
  54. //
  55. // these are keywords introduced by this co-installer
  56. // note that the names are not case sensitive
  57. //
  58. #define WMIINTERFACE_KEY TEXT("WmiInterface")
  59. #define WMIGUIDSECURITYSECTION_KEY TEXT("security")
  60. //
  61. // ANSI version
  62. //
  63. WINSETUPAPI
  64. BOOL
  65. WINAPI
  66. SetupConfigureWmiFromInfSectionA(
  67. IN HINF InfHandle,
  68. IN PCSTR SectionName,
  69. IN DWORD Flags
  70. )
  71. {
  72. DWORD rc;
  73. PWSTR UnicodeSectionName = NULL;
  74. try {
  75. //
  76. // For this API, only the SectionName needs to be converted to Unicode since it
  77. // is the only string passed in as a parameter.
  78. //
  79. rc = pSetupCaptureAndConvertAnsiArg(SectionName,&UnicodeSectionName);
  80. if(rc != NO_ERROR) {
  81. leave;
  82. }
  83. rc = GLE_FN_CALL(FALSE,
  84. SetupConfigureWmiFromInfSection(InfHandle,
  85. UnicodeSectionName,
  86. Flags)
  87. );
  88. } except(pSetupExceptionFilter(GetExceptionCode())) {
  89. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &rc);
  90. }
  91. if(UnicodeSectionName) {
  92. MyFree(UnicodeSectionName);
  93. }
  94. SetLastError(rc);
  95. return (rc == NO_ERROR);
  96. }
  97. //
  98. // UNICODE version
  99. //
  100. WINSETUPAPI
  101. BOOL
  102. WINAPI
  103. SetupConfigureWmiFromInfSection(
  104. IN HINF InfHandle,
  105. IN PCTSTR SectionName,
  106. IN DWORD Flags
  107. )
  108. /*++
  109. Routine Description:
  110. Process all WmiInterface lines from the WMI install sections, by parsing
  111. the directives to obatins the GUID and SDDL strings. For each corresponding
  112. SDDL for GUID, then establish the appropriate security descriptors.
  113. Arguments:
  114. InfHandle [in] - handle to INF file
  115. SectionName [in] - name of the WMI install section [DDInstall.WMI]
  116. Flags [in] - SCWMI_CLOBBER_SECURITY flag only (this flag will override any
  117. flag specified in the INF).
  118. Return Value:
  119. TRUE if successful, otherwise FALSE>
  120. Win32 error code retrieved via GetLastError(), or ERROR_UNIDENTIFIED_ERROR
  121. if GetLastError() returned NO_ERROR.
  122. --*/
  123. {
  124. PTCHAR GuidString, SDDLString, SectionNameString, InterfaceName;
  125. ULONG GuidStringLen, SDDLStringLen, SectionNameStringLen, InterfaceNameLen;
  126. INFCONTEXT InfLineContext;
  127. PLOADED_INF pInf;
  128. DWORD Status;
  129. INT count;
  130. //
  131. // Initialize all of the variables
  132. //
  133. Status = NO_ERROR;
  134. GuidString = NULL;
  135. GuidStringLen = 0;
  136. SectionNameString = NULL;
  137. SectionNameStringLen = 0;
  138. SDDLString = NULL;
  139. SDDLStringLen = 0;
  140. InterfaceName = NULL;
  141. count = 0;
  142. pInf = NULL;
  143. try {
  144. if((InfHandle == INVALID_HANDLE_VALUE) ||
  145. (InfHandle == NULL)) {
  146. Status = ERROR_INVALID_HANDLE;
  147. leave;
  148. } else if(LockInf((PLOADED_INF)InfHandle)) {
  149. pInf = (PLOADED_INF)InfHandle;
  150. } else {
  151. Status = ERROR_INVALID_HANDLE;
  152. leave;
  153. }
  154. InterfaceNameLen = MAX_INF_STRING_LENGTH;
  155. InterfaceName = MyMalloc(InterfaceNameLen * sizeof(TCHAR));
  156. //
  157. // If the memory wasn't allocated, then return an error
  158. //
  159. if(!InterfaceName) {
  160. Status = ERROR_NOT_ENOUGH_MEMORY;
  161. leave;
  162. }
  163. //
  164. // we look for keyword "WmiInterface" in the CompSectionName section
  165. //
  166. if(SetupFindFirstLine(InfHandle,
  167. SectionName,
  168. NULL,
  169. &InfLineContext)) {
  170. do {
  171. count++;
  172. Status = GLE_FN_CALL(FALSE,
  173. SetupGetStringField(&InfLineContext,
  174. 0,
  175. (PTSTR)InterfaceName,
  176. InterfaceNameLen,
  177. NULL));
  178. if((Status == NO_ERROR) && !(lstrcmpi(WMIINTERFACE_KEY, InterfaceName))) {
  179. //
  180. // WMIInterface = GUID, flags, SectionName
  181. // The GUID should be at index 1, flags at index 2, and section
  182. // name at index 3
  183. //
  184. Status = ParseSection(InfLineContext,
  185. &GuidString,
  186. &GuidStringLen,
  187. &Flags,
  188. &SectionNameString,
  189. &SectionNameStringLen
  190. );
  191. if(Status != NO_ERROR) {
  192. WriteLogEntry(pInf->LogContext,
  193. SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
  194. MSG_FAILED_PARSESECTION,
  195. NULL,
  196. count,
  197. SectionName,
  198. pInf->VersionBlock.Filename
  199. );
  200. WriteLogError(pInf->LogContext,
  201. SETUP_LOG_ERROR,
  202. Status
  203. );
  204. leave;
  205. }
  206. //
  207. // Get SDDL string from the section specified by the interface
  208. //
  209. Status = GetSecurityKeyword(InfHandle,
  210. SectionNameString,
  211. &SDDLString,
  212. &SDDLStringLen
  213. );
  214. if(Status != NO_ERROR) {
  215. WriteLogEntry(pInf->LogContext,
  216. SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
  217. MSG_FAILED_GET_SECURITY,
  218. NULL,
  219. SectionName,
  220. pInf->VersionBlock.Filename
  221. );
  222. WriteLogError(pInf->LogContext,
  223. SETUP_LOG_ERROR,
  224. Status
  225. );
  226. break;
  227. }
  228. Status = EstablishGuidSecurity(GuidString, SDDLString, Flags);
  229. if(Status != NO_ERROR) {
  230. WriteLogEntry(pInf->LogContext,
  231. SETUP_LOG_ERROR | SETUP_LOG_BUFFER,
  232. MSG_FAILED_SET_SECURITY,
  233. NULL,
  234. SectionName,
  235. pInf->VersionBlock.Filename
  236. );
  237. WriteLogError(pInf->LogContext,
  238. SETUP_LOG_ERROR,
  239. Status
  240. );
  241. break;
  242. }
  243. }
  244. } while(SetupFindNextLine(&InfLineContext, &InfLineContext));
  245. }
  246. } except(pSetupExceptionFilter(GetExceptionCode())) {
  247. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Status);
  248. }
  249. //
  250. // Clean up temporary allocated resources
  251. //
  252. if(GuidString){
  253. MyFree(GuidString);
  254. }
  255. if(SectionNameString){
  256. MyFree(SectionNameString);
  257. }
  258. if(SDDLString) {
  259. MyFree(SDDLString);
  260. }
  261. if(InterfaceName) {
  262. MyFree(InterfaceName);
  263. }
  264. if(pInf) {
  265. UnlockInf((PLOADED_INF)InfHandle);
  266. }
  267. SetLastError(Status);
  268. return(Status == NO_ERROR);
  269. }
  270. ULONG
  271. ParseSecurityDescriptor(
  272. IN PSECURITY_DESCRIPTOR SD,
  273. OUT PSECURITY_INFORMATION SecurityInformation,
  274. OUT PSID *Owner,
  275. OUT PSID *Group,
  276. OUT PACL *Dacl,
  277. OUT PACL *Sacl
  278. )
  279. /*++
  280. Routine Description:
  281. Checks information provided in the security descriptor to make sure that
  282. at least the dacl, sacl, owner or group security was specified. Otherwise
  283. it will return an error.
  284. Arguments:
  285. SD [in] - security descriptor data structure
  286. already allocated and where security info is
  287. SecurityInformation [out] - indicates which security information is present
  288. Owner [out] - variable that receives a pointer to the owner
  289. SID in the security descriptor
  290. Group [out] - variable that receives a pointer to the group
  291. SID in the security descriptor
  292. Dacl [out] - variable that receives a pointer to the DACL
  293. in the returned security descriptor
  294. Sacl [out] - variable that receives a pointer to the SACL
  295. in the returned security descriptor
  296. Returns:
  297. NO_ERROR or an error code.
  298. --*/
  299. {
  300. BOOL Ok, Present, Defaulted;
  301. *SecurityInformation = 0;
  302. *Dacl = NULL;
  303. *Sacl = NULL;
  304. *Owner = NULL;
  305. *Group = NULL;
  306. Ok = GetSecurityDescriptorOwner(SD,
  307. Owner,
  308. &Defaulted
  309. );
  310. if(Ok && (Owner != NULL)) {
  311. *SecurityInformation |= OWNER_SECURITY_INFORMATION;
  312. }
  313. Ok = GetSecurityDescriptorGroup(SD,
  314. Group,
  315. &Defaulted
  316. );
  317. if(Ok && (Group != NULL)) {
  318. *SecurityInformation |= GROUP_SECURITY_INFORMATION;
  319. }
  320. Ok = GetSecurityDescriptorDacl(SD,
  321. &Present,
  322. Dacl,
  323. &Defaulted
  324. );
  325. if(Ok && Present) {
  326. *SecurityInformation |= DACL_SECURITY_INFORMATION;
  327. }
  328. Ok = GetSecurityDescriptorSacl(SD,
  329. &Present,
  330. Sacl,
  331. &Defaulted
  332. );
  333. if(Ok && Present) {
  334. *SecurityInformation |= SACL_SECURITY_INFORMATION;
  335. }
  336. //
  337. // If no security info in the security descriptor then it is an
  338. // error
  339. //
  340. return((*SecurityInformation == 0) ?
  341. ERROR_INVALID_PARAMETER :
  342. NO_ERROR);
  343. }
  344. ULONG
  345. EstablishGuidSecurity(
  346. IN PTCHAR GuidString,
  347. IN PTCHAR SDDLString,
  348. IN DWORD Flags
  349. )
  350. /*++
  351. Routine Description:
  352. Writes security information to registry key (specified by WMIGUIDSECURITYKEY in
  353. regstr.w). Makes sure that the DACL is not null. Function will only write
  354. security information if it is not specified or the SCWMI_OVERWRITE_SECURITY flag is set.
  355. Arguments:
  356. GuidString [in] - GUID String taken from the INF file for the WMI interface
  357. SDDLString [in] - The security description string for the corresponding GUID (also
  358. taken from the INF) that indicates what to set the security to.
  359. Flags [in] - SCWMI_CLOBBER_SECURITY flag only
  360. Returns:
  361. Status, normally NO_ERROR
  362. --*/
  363. {
  364. HKEY Key;
  365. PACL Dacl, Sacl;
  366. PSID Owner, Group;
  367. SECURITY_INFORMATION SecurityInformation;
  368. PSECURITY_DESCRIPTOR SD;
  369. ULONG Status;
  370. ULONG SizeNeeded;
  371. BOOL Present, Ok;
  372. Key = INVALID_HANDLE_VALUE;
  373. SD = NULL;
  374. try {
  375. //
  376. // First check if security has already been set for this guid. If
  377. // so then we don't want to overwrite it.
  378. //
  379. Status = RegOpenKey(HKEY_LOCAL_MACHINE,
  380. REGSTR_PATH_WMI_SECURITY,
  381. &Key
  382. );
  383. if(Status != ERROR_SUCCESS) {
  384. //
  385. // Ensure key remains INVALID_HANDLE_VALUE so we don't try to free
  386. // it later
  387. //
  388. Key = INVALID_HANDLE_VALUE;
  389. leave;
  390. }
  391. if(!((Flags & SCWMI_CLOBBER_SECURITY) ||
  392. (ERROR_SUCCESS != RegQueryValueEx(Key,
  393. GuidString,
  394. NULL,
  395. NULL,
  396. NULL,
  397. &SizeNeeded)))) {
  398. //
  399. // We weren't told to clobber security and security exists so
  400. // there is nothing to do.
  401. //
  402. leave;
  403. }
  404. //
  405. // No security already setup so, lets go ahead and set it up
  406. // Lets create a SD from the SDDL string
  407. //
  408. Status = GLE_FN_CALL(FALSE,
  409. ConvertStringSecurityDescriptorToSecurityDescriptor(
  410. SDDLString,
  411. SDDL_REVISION_1,
  412. &SD,
  413. NULL)
  414. );
  415. if(Status != NO_ERROR) {
  416. //
  417. // Ensure SD remains NULL so it isn't freed later.
  418. //
  419. SD = NULL;
  420. leave;
  421. }
  422. //
  423. // Break up the SD into its components
  424. //
  425. Status = ParseSecurityDescriptor(SD,
  426. &SecurityInformation,
  427. &Owner,
  428. &Group,
  429. &Dacl,
  430. &Sacl
  431. );
  432. if(Status == NO_ERROR) {
  433. //
  434. // Don't allow any SD to be setup with a NULL DACL
  435. // as this results in full access for anyone
  436. //
  437. if(Dacl != NULL) {
  438. //
  439. // For wmiguids, the owner, group and sacl don't mean
  440. // much so we just set the DACL.
  441. //
  442. SecurityInformation = DACL_SECURITY_INFORMATION;
  443. Owner = NULL;
  444. Group = NULL;
  445. Sacl = NULL;
  446. Status = SetNamedSecurityInfo(GuidString,
  447. SE_WMIGUID_OBJECT,
  448. SecurityInformation,
  449. Owner,
  450. Group,
  451. Dacl,
  452. Sacl
  453. );
  454. } else {
  455. Status = ERROR_INVALID_PARAMETER;
  456. leave;
  457. }
  458. }
  459. } except(pSetupExceptionFilter(GetExceptionCode())) {
  460. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Status);
  461. }
  462. if(SD) {
  463. //
  464. // Explicity must use LocalFree for Security Descriptors returned by
  465. // ConvertStringSecurityDescriptorToSecurityDescriptor
  466. //
  467. LocalFree(SD);
  468. }
  469. if(Key == INVALID_HANDLE_VALUE) {
  470. RegCloseKey(Key);
  471. }
  472. return Status;
  473. }
  474. ULONG
  475. ParseSection(
  476. IN INFCONTEXT InfLineContext,
  477. IN OUT PTCHAR *GuidString,
  478. IN OUT ULONG *GuidStringLen,
  479. IN OUT PDWORD Flags,
  480. IN OUT PTCHAR *SectionNameString,
  481. IN OUT ULONG *SectionNameStringLen
  482. )
  483. /*++
  484. Routinte Description:
  485. This section parses the GUID, flags, and SectionName, respectively.
  486. There should only be 3 fields in the WMIInterface section, otherwise an
  487. error will be returned.
  488. Arguments:
  489. InfLineContext [in] - The line from the INF we are parsing
  490. GuidString [in, out] - Passed as NULL by the caller, then memory is allocated
  491. and filled with the corresponding GUID string.
  492. GuidStringLen [in, out] - Passed as zero by the caller, and then set to the
  493. maximum length for the GUID.
  494. Flags [in, out] - SCWMI_CLOBBER_SECURITY flag only
  495. SectionNameString [in, out] - assed as NULL by the caller, then memory is allocated
  496. and filled with the corresponding section name.
  497. SectionNameStringLen [in, out] - assed as zero by the caller, and then set to the
  498. maximum length for the section name
  499. Returns:
  500. Status, normally NO_ERROR
  501. --*/
  502. {
  503. PTCHAR TempGuidString = NULL;
  504. ULONG FieldCount;
  505. ULONG Status;
  506. INT infFlags;
  507. int i;
  508. size_t Length;
  509. Status = NO_ERROR;
  510. try {
  511. //
  512. // Make sure there are 3 fields specified in the section
  513. //
  514. FieldCount = SetupGetFieldCount(&InfLineContext);
  515. if(FieldCount < 3) {
  516. Status = ERROR_INVALID_PARAMETER;
  517. leave;
  518. }
  519. //
  520. // Get the guid string
  521. //
  522. *GuidStringLen = MAX_GUID_STRING_LEN;
  523. *GuidString = MyMalloc((*GuidStringLen) * sizeof(TCHAR));
  524. //
  525. // If the memory wasn't allocated, then return an error
  526. //
  527. if(!(*GuidString)) {
  528. Status = ERROR_NOT_ENOUGH_MEMORY;
  529. leave;
  530. }
  531. Status = GLE_FN_CALL(FALSE,
  532. SetupGetStringField(&InfLineContext,
  533. 1,
  534. (PTSTR)(*GuidString),
  535. *GuidStringLen,
  536. NULL)
  537. );
  538. if(Status != NO_ERROR) {
  539. leave;
  540. }
  541. //
  542. // If the GUID string has curly braces take them off
  543. //
  544. //
  545. // String has curly braces as first and last character
  546. // Checks to make sure it has the same length as a GUID, otherwise, this function
  547. // relies on the WMI security API to handle and invalid GUID.
  548. //
  549. if(((*GuidString)[0] == TEXT('{')) &&
  550. SUCCEEDED(StringCchLength(*GuidString,MAX_GUID_STRING_LEN,&Length)) &&
  551. (Length == (MAX_GUID_STRING_LEN-1)) &&
  552. ((*GuidString)[MAX_GUID_STRING_LEN-2] == TEXT('}'))) {
  553. TempGuidString = MyMalloc((MAX_GUID_STRING_LEN-2) * sizeof(TCHAR));
  554. if(TempGuidString == NULL) {
  555. Status = ERROR_NOT_ENOUGH_MEMORY;
  556. leave;
  557. }
  558. //
  559. // Copy the GuidString, except the first and last character (the braces)
  560. //
  561. if(FAILED(StringCchCopyN(TempGuidString,
  562. MAX_GUID_STRING_LEN-2,
  563. &(*GuidString)[1],
  564. MAX_GUID_STRING_LEN-3))) {
  565. Status = ERROR_INVALID_PARAMETER;
  566. MyFree(TempGuidString);
  567. TempGuidString = NULL;
  568. leave;
  569. }
  570. MyFree(*GuidString);
  571. //
  572. // Set GuidString equal to our new one without braces
  573. //
  574. *GuidString = TempGuidString;
  575. TempGuidString = NULL;
  576. }
  577. //
  578. // Now get the flags string
  579. //
  580. Status = GLE_FN_CALL(FALSE,
  581. SetupGetIntField(&InfLineContext,
  582. 2,
  583. &infFlags)
  584. );
  585. if(Status != NO_ERROR) {
  586. leave;
  587. }
  588. //
  589. // if the flags in the INF were not set then use the flags indicated in the INF,
  590. // otherwise default to use the ones passed in by the calling function.
  591. //
  592. if(!(*Flags)) {
  593. *Flags = infFlags;
  594. }
  595. *SectionNameStringLen = MAX_INF_STRING_LENGTH;
  596. *SectionNameString = MyMalloc(*SectionNameStringLen * sizeof(TCHAR));
  597. //
  598. // If the memory wasn't allocated, then return an error
  599. //
  600. if(!(*SectionNameString)) {
  601. Status = ERROR_NOT_ENOUGH_MEMORY;
  602. leave;
  603. }
  604. Status = GLE_FN_CALL(FALSE,
  605. SetupGetStringField(&InfLineContext,
  606. 3,
  607. (PTSTR)(*SectionNameString),
  608. (*SectionNameStringLen),
  609. NULL)
  610. );
  611. } except(pSetupExceptionFilter(GetExceptionCode())) {
  612. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Status);
  613. }
  614. //
  615. // If the function exits abnormally then clean up any strings allocated.
  616. //
  617. if(Status != NO_ERROR) {
  618. if(*GuidString){
  619. MyFree(*GuidString);
  620. *GuidString = NULL;
  621. }
  622. if(TempGuidString) {
  623. MyFree(TempGuidString);
  624. }
  625. if(*SectionNameString){
  626. MyFree(*SectionNameString);
  627. *SectionNameString = NULL;
  628. }
  629. }
  630. return Status;
  631. }
  632. ULONG
  633. GetSecurityKeyword(
  634. IN HINF InfFile,
  635. IN LPCTSTR WMIInterfaceSection,
  636. IN OUT PTCHAR *SDDLString,
  637. IN OUT ULONG *SDDLStringLen
  638. )
  639. /*++
  640. Routine Description:
  641. The section name specified under the WMIInterface should contain a
  642. security section the specifies the SDDL. It should be in the form
  643. security = <SDDL>. This fcuntion extracts the SDDL. There should
  644. only be one security section, otherwise an error will be returned.
  645. Arguments:
  646. InfLineContext [in] - the line from the INF file
  647. WMIInterfaceSection [in] - the section name indicating what
  648. section contains the security info
  649. SDDLString [in, out] - passed in as NULL by the caller, is
  650. allocated and filled in with the
  651. corresponding security description
  652. string.
  653. SDDLStringLen [in, out] - passed in as 0 by the caller and set
  654. to the maximum length of an INF field.
  655. Returns:
  656. Status, normally NO_ERROR
  657. --*/
  658. {
  659. INFCONTEXT InfLineContext;
  660. DWORD Status;
  661. ULONG FieldCount;
  662. Status = NO_ERROR;
  663. try {
  664. if(SetupFindFirstLine(InfFile,
  665. WMIInterfaceSection,
  666. WMIGUIDSECURITYSECTION_KEY,
  667. &InfLineContext)) {
  668. //
  669. // WmiGuidSecurity = <SDDL>
  670. // sddl will be at index 1
  671. //
  672. FieldCount = SetupGetFieldCount(&InfLineContext);
  673. if(FieldCount < 1) {
  674. Status = ERROR_INVALID_PARAMETER;
  675. leave;
  676. }
  677. //
  678. // Get the SDDL string
  679. //
  680. *SDDLStringLen = MAX_INF_STRING_LENGTH;
  681. *SDDLString = MyMalloc(*SDDLStringLen * sizeof(TCHAR));
  682. //
  683. // If the memory wasn't allocated, then return an error
  684. //
  685. if(!(*SDDLString)) {
  686. Status = ERROR_NOT_ENOUGH_MEMORY;
  687. leave;
  688. }
  689. Status = GLE_FN_CALL(FALSE,
  690. SetupGetStringField(&InfLineContext,
  691. 1,
  692. (PTSTR)(*SDDLString),
  693. (*SDDLStringLen),
  694. NULL)
  695. );
  696. if(Status == NO_ERROR) {
  697. //
  698. // There should not be more than one security entry
  699. //
  700. if(SetupFindNextMatchLine(&InfLineContext,
  701. WMIGUIDSECURITYSECTION_KEY,
  702. &InfLineContext)) {
  703. Status = ERROR_INVALID_PARAMETER;
  704. leave;
  705. }
  706. }
  707. }
  708. }except(pSetupExceptionFilter(GetExceptionCode())){
  709. pSetupExceptionHandler(GetExceptionCode(), ERROR_INVALID_PARAMETER, &Status);
  710. }
  711. //
  712. // If the function exits abnormally then clean up any strings allocated.
  713. //
  714. if(Status != NO_ERROR) {
  715. if(*SDDLString) {
  716. MyFree(*SDDLString);
  717. *SDDLString = NULL;
  718. }
  719. }
  720. return Status;
  721. }