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.

1071 lines
30 KiB

  1. /*++
  2. Microsoft Windows
  3. Copyright (c) Microsoft Corporation. All rights reserved.
  4. File: WMIInst.C
  5. Contents: co-installer hook to setup security on wmi guids
  6. The assumption is that the INF is setup to have an install
  7. section decorated with a "WMI" keyword. Then there should
  8. be a section defining a WMIInterface that has 3 fields: a
  9. GUID, flags, and WMIInterfaceSection.
  10. WMIINterface = <GUID>, flags, <SectionName>
  11. A security field should then be defined under that
  12. SectionName, that contains the SDDL need to setup WMI
  13. security.
  14. [WMIInterfaceSectionName]
  15. security = <SDDL>
  16. This example shows both a way to install INF's for a
  17. multi-function device for Windows 2000, and also how
  18. to add to the INF syntax for other purposes.
  19. Notes: For a complete description of CoInstallers, please see the
  20. Microsoft Windows 2000 DDK Documentation
  21. @@BEGIN_DDKSPLIT
  22. Author: AlanWar 03/29/02
  23. Revision History:
  24. @@END_DDKSPLIT
  25. --*/
  26. #include <windows.h>
  27. #include <setupapi.h>
  28. #include <stdio.h>
  29. #include <malloc.h>
  30. #include <sddl.h>
  31. #include <aclapi.h>
  32. #include <strsafe.h>
  33. #define AllocMemory malloc
  34. #define FreeMemory free
  35. DWORD
  36. __inline
  37. pSetupGetLastError(
  38. VOID
  39. )
  40. /*++
  41. Routine Description:
  42. This inline routine retrieves a Win32 error, and guarantees that the error
  43. isn't NO_ERROR. This routine should not be called unless the preceding
  44. call failed, and GetLastError() is supposed to contain the problem's cause.
  45. Arguments:
  46. None.
  47. Return Value:
  48. Win32 error code retrieved via GetLastError(), or ERROR_UNIDENTIFIED_ERROR
  49. if GetLastError() returned NO_ERROR.
  50. --*/
  51. {
  52. DWORD Err = GetLastError();
  53. return ((Err == NO_ERROR) ? ERROR_INVALID_DATA : Err);
  54. }
  55. //
  56. // Macro to simplify calling of a function that reports error status via
  57. // GetLastError(). This macro allows the caller to specify what Win32 error
  58. // code should be returned if the function reports success. (If the default of
  59. // NO_ERROR is desired, use the GLE_FN_CALL macro instead.)
  60. //
  61. // The "prototype" of this macro is as follows:
  62. //
  63. // DWORD
  64. // GLE_FN_CALL_WITH_SUCCESS(
  65. // SuccessfulStatus, // Win32 error code to return if function succeeded
  66. // FailureIndicator, // value returned by function to indicate failure (e.g., FALSE, NULL, INVALID_HANDLE_VALUE)
  67. // FunctionCall // actual call to the function
  68. // );
  69. //
  70. #define GLE_FN_CALL_WITH_SUCCESS(SuccessfulStatus, \
  71. FailureIndicator, \
  72. FunctionCall) \
  73. \
  74. (SetLastError(NO_ERROR), \
  75. (((FunctionCall) != (FailureIndicator)) \
  76. ? (SuccessfulStatus) \
  77. : pSetupGetLastError()))
  78. //
  79. // Macro to simplify calling of a function that reports error status via
  80. // GetLastError(). If the function call is successful, NO_ERROR is returned.
  81. // (To specify an alternate value returned upon success, use the
  82. // GLE_FN_CALL_WITH_SUCCESS macro instead.)
  83. //
  84. // The "prototype" of this macro is as follows:
  85. //
  86. // DWORD
  87. // GLE_FN_CALL(
  88. // FailureIndicator, // value returned by function to indicate failure (e.g., FALSE, NULL, INVALID_HANDLE_VALUE)
  89. // FunctionCall // actual call to the function
  90. // );
  91. //
  92. #define GLE_FN_CALL(FailureIndicator, FunctionCall) \
  93. GLE_FN_CALL_WITH_SUCCESS(NO_ERROR, FailureIndicator, FunctionCall)
  94. //
  95. // ** Function Prototypes **
  96. //
  97. ULONG
  98. ParseSection(
  99. IN INFCONTEXT InfLineContext,
  100. IN OUT PTCHAR *GuidString,
  101. IN OUT ULONG *GuidStringLen,
  102. OUT PDWORD Flags,
  103. IN OUT PTCHAR *SectionNameString,
  104. IN OUT ULONG *SectionNameStringLen
  105. );
  106. ULONG
  107. EstablishGuidSecurity(
  108. IN PTCHAR GuidString,
  109. IN PTCHAR SDDLString,
  110. IN DWORD Flags
  111. );
  112. ULONG
  113. GetSecurityKeyword(
  114. IN HINF InfFile,
  115. IN LPCTSTR WMIINterfaceSection,
  116. IN OUT PTCHAR *SDDLString,
  117. IN OUT ULONG *SDDLStringLen
  118. );
  119. ULONG
  120. ParseSecurityDescriptor(
  121. IN PSECURITY_DESCRIPTOR SD,
  122. OUT PSECURITY_INFORMATION SecurityInformation,
  123. OUT PSID *Owner,
  124. OUT PSID *Group,
  125. OUT PACL *Dacl,
  126. OUT PACL *Sacl
  127. );
  128. //+-----------------------------------------------------------------------------
  129. //
  130. // WARNING!
  131. //
  132. // A Coinstaller must not generate any popup to the user when called with
  133. // DI_QUIETINSTALL. However, it's generally never a good idea to generate
  134. // popups.
  135. //
  136. // OutputDebugString is a fine way to output information for debugging
  137. //
  138. #if DBG
  139. VOID
  140. DebugPrintX(
  141. PCHAR DebugMessage,
  142. ...
  143. );
  144. #define DbgOut(x) DebugPrintX x
  145. #define DEBUG_BUFFER_LENGTH 1024
  146. #else
  147. #define DbgOut(Text)
  148. #endif
  149. //
  150. // these are keywords introduced by this co-installer
  151. // note that the names are not case sensitive
  152. //
  153. #define WMI_KEY TEXT(".WMI")
  154. #define WMIINTERFACE_KEY TEXT("WmiInterface")
  155. #define WMIGUIDSECURITYSECTION_KEY TEXT("security")
  156. #define MAX_GUID_STRING_LEN 39 // 38 chars + terminator null
  157. DWORD
  158. ProcessWMIInstallation(
  159. IN HINF InfFile,
  160. IN LPCTSTR CompSectionName
  161. )
  162. /*++
  163. Routine Description:
  164. Process all WmiInterface lines from the WMI install sections, by parsing
  165. the directives to obatins the GUID and SDDL strings. For each corresponding
  166. SDDL for GUID, then establish the appropriate security descriptors.
  167. Arguments:
  168. InfFile - handle to INF file
  169. CompSectionName - name of the WMI install section
  170. Return Value:
  171. Status, normally NO_ERROR
  172. --*/
  173. {
  174. PTCHAR GuidString, SDDLString, SectionNameString;
  175. ULONG GuidStringLen, SDDLStringLen, SectionNameStringLen;
  176. DWORD Flags;
  177. INFCONTEXT InfLineContext;
  178. DWORD Status;
  179. Status = NO_ERROR;
  180. //
  181. // we look for keyword "WmiInterface" in the CompSectionName section
  182. //
  183. GuidString = NULL;
  184. GuidStringLen = 0;
  185. SectionNameString = NULL;
  186. SectionNameStringLen = 0;
  187. SDDLString = NULL;
  188. SDDLStringLen = 0;
  189. Flags = 0;
  190. if(SetupFindFirstLine(InfFile,
  191. CompSectionName,
  192. WMIINTERFACE_KEY,
  193. &InfLineContext)) {
  194. do {
  195. //
  196. // WMIInterface = GUID, flags, SectionName
  197. // The GIUD should be at index 1, flags at index 2, and section
  198. // name at index 3
  199. //
  200. Status = ParseSection(InfLineContext,
  201. &GuidString,
  202. &GuidStringLen,
  203. &Flags,
  204. &SectionNameString,
  205. &SectionNameStringLen
  206. );
  207. if(Status != NO_ERROR) {
  208. break;
  209. }
  210. //
  211. // Get SDDL string from the section specified by the interface
  212. //
  213. Status = GetSecurityKeyword(InfFile,
  214. SectionNameString,
  215. &SDDLString,
  216. &SDDLStringLen
  217. );
  218. if(Status != NO_ERROR) {
  219. break;
  220. }
  221. Status = EstablishGuidSecurity(GuidString, SDDLString, Flags);
  222. if(Status != NO_ERROR) {
  223. break;
  224. }
  225. } while(SetupFindNextMatchLine(&InfLineContext,
  226. WMIINTERFACE_KEY,
  227. &InfLineContext));
  228. //
  229. // Cleanup any strings allocated
  230. //
  231. if(GuidString != NULL) {
  232. FreeMemory(GuidString);
  233. }
  234. if(SectionNameString != NULL) {
  235. FreeMemory(SectionNameString);
  236. }
  237. if(SDDLString != NULL) {
  238. FreeMemory(SDDLString);
  239. }
  240. }
  241. return Status;
  242. }
  243. DWORD
  244. PreProcessInstallDevice (
  245. IN HDEVINFO DeviceInfoSet,
  246. IN PSP_DEVINFO_DATA DeviceInfoData,
  247. IN OUT PCOINSTALLER_CONTEXT_DATA Context
  248. )
  249. /*++
  250. Function:
  251. PreProcessInstallDevice
  252. Purpose:
  253. Handle DIF_INSTALLDEVICE PostProcessing
  254. Opens the INF file, locates the install section with the decoration
  255. ".WMI" (as defined by WMI_KEY above). Then performs the WMI installation.
  256. Arguments:
  257. DeviceInfoSet [in]
  258. DeviceInfoData [in]
  259. Context [in,out]
  260. Returns:
  261. NO_ERROR or an error code.
  262. --*/
  263. {
  264. DWORD Status = NO_ERROR;
  265. DWORD FinalStatus;
  266. HINF InfFile = INVALID_HANDLE_VALUE;
  267. SP_DRVINFO_DATA DriverInfoData;
  268. SP_DRVINFO_DETAIL_DATA DriverInfoDetailData;
  269. TCHAR InstallSectionName[255]; //MAX_SECT_NAME_LEN
  270. TCHAR CompSectionName[255]; //MAX_SECT_NAME_LEN
  271. INFCONTEXT CompLine;
  272. DWORD FieldCount, FieldIndex;
  273. FinalStatus = NO_ERROR;
  274. //
  275. // Find name of INF and name of install section
  276. //
  277. DriverInfoData.cbSize = sizeof(SP_DRVINFO_DATA);
  278. Status = GLE_FN_CALL(FALSE,
  279. SetupDiGetSelectedDriver(DeviceInfoSet,
  280. DeviceInfoData,
  281. &DriverInfoData)
  282. );
  283. if(Status != NO_ERROR) {
  284. DbgOut(("Fail: SetupDiGetSelectedDriver %d\n", Status));
  285. goto clean;
  286. }
  287. DriverInfoDetailData.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA);
  288. Status = GLE_FN_CALL(FALSE,
  289. SetupDiGetDriverInfoDetail(
  290. DeviceInfoSet,
  291. DeviceInfoData,
  292. &DriverInfoData,
  293. &DriverInfoDetailData,
  294. sizeof(SP_DRVINFO_DETAIL_DATA),
  295. NULL)
  296. );
  297. if(Status != NO_ERROR) {
  298. if(Status == ERROR_INSUFFICIENT_BUFFER) {
  299. //
  300. // We don't need the extended information. Ignore.
  301. //
  302. } else {
  303. DbgOut(("Fail: SetupDiGetDriverInfoDetail %d\n", Status));
  304. goto clean;
  305. }
  306. }
  307. //
  308. // We have InfFileName, open the INF
  309. //
  310. InfFile = SetupOpenInfFile(DriverInfoDetailData.InfFileName,
  311. NULL,
  312. INF_STYLE_WIN4,
  313. NULL);
  314. if(InfFile == INVALID_HANDLE_VALUE) {
  315. Status = GetLastError();
  316. DbgOut(("Fail: SetupOpenInfFile %d", Status));
  317. goto clean;
  318. }
  319. //
  320. // determine section used for the install which might be different
  321. // from the section name specified in DriverInfoDetailData.
  322. //
  323. Status = GLE_FN_CALL(FALSE,
  324. SetupDiGetActualSectionToInstall(
  325. InfFile,
  326. DriverInfoDetailData.SectionName,
  327. InstallSectionName,
  328. (sizeof(InstallSectionName)/sizeof(InstallSectionName[0])),
  329. NULL,
  330. NULL)
  331. );
  332. if(Status != NO_ERROR) {
  333. DbgOut(("Fail: SetupDiGetActualSectionToInstall %d\n", Status));
  334. goto clean;
  335. }
  336. //
  337. // We need to append the WMI_KEY to find the correct decorated section
  338. //
  339. if(FAILED(StringCchCat(InstallSectionName,
  340. (sizeof(InstallSectionName)/sizeof(InstallSectionName[0])),
  341. WMI_KEY))) {
  342. DbgOut(("WMICoInstaller: Fail - StringCchCat\n"));
  343. goto clean;
  344. }
  345. //
  346. // we have a listed section
  347. //
  348. Status = ProcessWMIInstallation(InfFile,
  349. InstallSectionName);
  350. if(Status != NO_ERROR) {
  351. FinalStatus = Status;
  352. goto clean;
  353. }
  354. clean:
  355. if(InfFile) {
  356. SetupCloseInfFile(InfFile);
  357. }
  358. //
  359. // since what we are doing does not affect primary device installation
  360. // always return success
  361. //
  362. return FinalStatus;
  363. }
  364. ULONG
  365. ParseSecurityDescriptor(
  366. IN PSECURITY_DESCRIPTOR SD,
  367. OUT PSECURITY_INFORMATION SecurityInformation,
  368. OUT PSID *Owner,
  369. OUT PSID *Group,
  370. OUT PACL *Dacl,
  371. OUT PACL *Sacl
  372. )
  373. /*++
  374. Function:
  375. ParseSecurityDescriptor
  376. Purpose:
  377. Checks information provided in the security descriptor to make sure that
  378. at least the dacl, sacl, owner or group security was specified. Otherwise
  379. it will return an error.
  380. Arguments:
  381. SD [in]
  382. SecurityInformation [out]
  383. Owner [out]
  384. Group [out]
  385. Dacl [out]
  386. Sacl [out]
  387. Returns:
  388. NO_ERROR or an error code.
  389. --*/
  390. {
  391. BOOL Ok, Present, Defaulted;
  392. *SecurityInformation = 0;
  393. *Dacl = NULL;
  394. *Sacl = NULL;
  395. *Owner = NULL;
  396. *Group = NULL;
  397. Ok = GetSecurityDescriptorOwner(SD,
  398. Owner,
  399. &Defaulted);
  400. if(Ok && (Owner != NULL)) {
  401. *SecurityInformation |= OWNER_SECURITY_INFORMATION;
  402. }
  403. Ok = GetSecurityDescriptorGroup(SD,
  404. Group,
  405. &Defaulted);
  406. if(Ok && (Group != NULL)) {
  407. *SecurityInformation |= GROUP_SECURITY_INFORMATION;
  408. }
  409. Ok = GetSecurityDescriptorDacl(SD,
  410. &Present,
  411. Dacl,
  412. &Defaulted);
  413. if(Ok && Present) {
  414. *SecurityInformation |= DACL_SECURITY_INFORMATION;
  415. }
  416. Ok = GetSecurityDescriptorSacl(SD,
  417. &Present,
  418. Sacl,
  419. &Defaulted);
  420. if(Ok && Present) {
  421. *SecurityInformation |= SACL_SECURITY_INFORMATION;
  422. }
  423. //
  424. // If no security info in the security descriptor then it is an
  425. // error
  426. //
  427. return((*SecurityInformation == 0) ?
  428. ERROR_INVALID_PARAMETER :
  429. NO_ERROR);
  430. }
  431. #define WMIGUIDSECURITYKEY TEXT("System\\CurrentControlSet\\Control\\Wmi\\Security")
  432. // path should be moved to regstr.h, nt\base\published\regstr.w
  433. ULONG
  434. EstablishGuidSecurity(
  435. IN PTCHAR GuidString,
  436. IN PTCHAR SDDLString,
  437. IN DWORD Flags
  438. )
  439. /*++
  440. Function:
  441. EstablishGuidSecurity
  442. Purpose:
  443. Writes security information to registry key (specified by WMIGUIDSECURITYKEY in
  444. regstr.w). Makes sure that the DACL is not null. Function will only write
  445. security information if it is not specified or the SCWMI_OVERWRITE_SECURITY is set.
  446. Arguments:
  447. GuidString [in]
  448. SDDLString [in]
  449. Flags [in] - SCWMI_OVERWRITE_SECURITY flag only
  450. Returns:
  451. Status, normally NO_ERROR
  452. --*/
  453. {
  454. HKEY Key;
  455. PACL Dacl, Sacl;
  456. PSID Owner, Group;
  457. SECURITY_INFORMATION SecurityInformation;
  458. PSECURITY_DESCRIPTOR SD;
  459. ULONG Status;
  460. ULONG SizeNeeded;
  461. BOOL Present, Ok;
  462. Key = INVALID_HANDLE_VALUE;
  463. SD = NULL;
  464. SizeNeeded = 0;
  465. //
  466. // First check if security has already been set for this guid. If
  467. // so then we don't want to overwrite it.
  468. //
  469. Status = RegOpenKey(HKEY_LOCAL_MACHINE,
  470. WMIGUIDSECURITYKEY,
  471. &Key);
  472. if(Status != ERROR_SUCCESS) {
  473. //
  474. // Ensure key remains INVALID_HANDLE_VALUE so we don't try to free
  475. // it later
  476. //
  477. Key = INVALID_HANDLE_VALUE;
  478. goto clean;
  479. }
  480. if((Flags & SCWMI_CLOBBER_SECURITY) ||
  481. (ERROR_SUCCESS != RegQueryValueEx(Key,
  482. GuidString,
  483. NULL,
  484. NULL,
  485. NULL,
  486. &SizeNeeded))) {
  487. //
  488. // No security already setup so, lets go ahead and set it up
  489. // Lets create a SD from the SDDL string
  490. //
  491. Status = GLE_FN_CALL(FALSE,
  492. ConvertStringSecurityDescriptorToSecurityDescriptor(
  493. SDDLString,
  494. SDDL_REVISION_1,
  495. &SD,
  496. NULL)
  497. );
  498. if(Status != NO_ERROR) {
  499. //
  500. // Ensure SD remains NULL so it isn't freed later.
  501. //
  502. SD = NULL;
  503. goto clean;
  504. }
  505. //
  506. // Break up the SD into its components
  507. //
  508. Status = ParseSecurityDescriptor(SD,
  509. &SecurityInformation,
  510. &Owner,
  511. &Group,
  512. &Dacl,
  513. &Sacl);
  514. if(Status != NO_ERROR) {
  515. goto clean;
  516. }
  517. //
  518. // Don't allow any SD to be setup with a NULL DACL
  519. // as this results in full access for anyone
  520. //
  521. if(Dacl != NULL) {
  522. //
  523. // For wmiguids, the owner, group and sacl don't mean
  524. // much so we just set the DACL.
  525. //
  526. SecurityInformation = DACL_SECURITY_INFORMATION;
  527. Owner = NULL;
  528. Group = NULL;
  529. Sacl = NULL;
  530. Status = SetNamedSecurityInfo(GuidString,
  531. SE_WMIGUID_OBJECT,
  532. SecurityInformation,
  533. Owner,
  534. Group,
  535. Dacl,
  536. Sacl);
  537. if(Status != ERROR_SUCCESS) {
  538. DbgOut(("SetNamedSecurityInfo failed %d\n",
  539. Status));
  540. goto clean;
  541. }
  542. } else {
  543. Status = ERROR_INVALID_PARAMETER;
  544. goto clean;
  545. }
  546. }
  547. clean:
  548. if(SD) {
  549. //
  550. // Explicity must use LocalFree for Security Descriptors returned by
  551. // ConvertStringSecurityDescriptorToSecurityDescriptor
  552. //
  553. LocalFree(SD);
  554. }
  555. if(Key != INVALID_HANDLE_VALUE) {
  556. RegCloseKey(Key);
  557. }
  558. return(Status);
  559. }
  560. ULONG
  561. ParseSection(
  562. IN INFCONTEXT InfLineContext,
  563. IN OUT PTCHAR *GuidString,
  564. IN OUT ULONG *GuidStringLen,
  565. OUT PDWORD Flags,
  566. IN OUT PTCHAR *SectionNameString,
  567. IN OUT ULONG *SectionNameStringLen
  568. )
  569. /*++
  570. Routinte Description:
  571. This section parses the GUID, flags, and SectionName, respectively.
  572. There should only be 3 fields in the WMIInterface section, otherwise an
  573. error will be returned.
  574. Arguments:
  575. InfLineContext [in] - The line from the INF we are parsing
  576. GuidString [in, out] - Passed as NULL by the caller, then memory is allocated
  577. and filled with the corresponding GUID string.
  578. GuidStringLen [in, out] - Passed as zero by the caller, and then set to the
  579. maximum length for the GUID.
  580. Flags [in, out] - SCWMI_CLOBBER_SECURITY flag only
  581. SectionNameString [in, out] - assed as NULL by the caller, then memory is allocated
  582. and filled with the corresponding section name.
  583. SectionNameStringLen [in, out] - assed as zero by the caller, and then set to the
  584. maximum length for the section name
  585. Returns:
  586. Status, normally NO_ERROR
  587. --*/
  588. {
  589. PTCHAR TempGuidString = NULL;
  590. ULONG FieldCount;
  591. ULONG Status;
  592. INT infFlags;
  593. int i;
  594. size_t Length;
  595. Status = NO_ERROR;
  596. //
  597. // Make sure there are 3 fields specified in the section
  598. //
  599. FieldCount = SetupGetFieldCount(&InfLineContext);
  600. if(FieldCount < 3) {
  601. Status = ERROR_INVALID_PARAMETER;
  602. goto clean;
  603. }
  604. //
  605. // Get the guid string
  606. //
  607. *GuidStringLen = MAX_GUID_STRING_LEN;
  608. *GuidString = AllocMemory((*GuidStringLen) * sizeof(TCHAR));
  609. //
  610. // If the memory wasn't allocated, then return an error
  611. //
  612. if(!(*GuidString)) {
  613. Status = ERROR_NOT_ENOUGH_MEMORY;
  614. goto clean;
  615. }
  616. Status = GLE_FN_CALL(FALSE,
  617. SetupGetStringField(&InfLineContext,
  618. 1,
  619. (PTSTR)(*GuidString),
  620. *GuidStringLen,
  621. NULL)
  622. );
  623. if(Status != NO_ERROR) {
  624. goto clean;
  625. }
  626. //
  627. // If the GUID string has curly braces take them off
  628. //
  629. //
  630. // String has curly braces as first and last character
  631. // Checks to make sure it has the same length as a GUID, otherwise, this function
  632. // relies on the WMI security API to handle and invalid GUID.
  633. //
  634. if(((*GuidString)[0] == TEXT('{')) &&
  635. SUCCEEDED(StringCchLength(*GuidString,MAX_GUID_STRING_LEN,&Length)) &&
  636. (Length == (MAX_GUID_STRING_LEN-1)) &&
  637. ((*GuidString)[MAX_GUID_STRING_LEN-2] == TEXT('}'))) {
  638. TempGuidString = AllocMemory((MAX_GUID_STRING_LEN-2) * sizeof(TCHAR));
  639. if(TempGuidString == NULL) {
  640. Status = ERROR_NOT_ENOUGH_MEMORY;
  641. goto clean;
  642. }
  643. //
  644. // Copy the GuidString, except the first and last character (the braces)
  645. //
  646. if(FAILED(StringCchCopyN(TempGuidString,
  647. MAX_GUID_STRING_LEN-2,
  648. &(*GuidString)[1],
  649. MAX_GUID_STRING_LEN-3))) {
  650. Status = ERROR_INVALID_PARAMETER;
  651. FreeMemory(TempGuidString);
  652. TempGuidString = NULL;
  653. goto clean;
  654. }
  655. FreeMemory(*GuidString);
  656. //
  657. // Set GuidString equal to our new one without braces
  658. //
  659. *GuidString = TempGuidString;
  660. TempGuidString = NULL;
  661. }
  662. //
  663. // Now get the flags string
  664. //
  665. Status = GLE_FN_CALL(FALSE,
  666. SetupGetIntField(&InfLineContext,
  667. 2,
  668. &infFlags)
  669. );
  670. if(Status != NO_ERROR) {
  671. goto clean;
  672. }
  673. //
  674. // if the flags in the INF were not set then use the flags indicated in the INF,
  675. // otherwise default to use the ones passed in by the calling function.
  676. //
  677. if(!(*Flags)) {
  678. *Flags = infFlags;
  679. }
  680. *SectionNameStringLen = MAX_INF_STRING_LENGTH;
  681. *SectionNameString = AllocMemory(*SectionNameStringLen * sizeof(TCHAR));
  682. //
  683. // If the memory wasn't allocated, then return an error
  684. //
  685. if(!(*SectionNameString)) {
  686. Status = ERROR_NOT_ENOUGH_MEMORY;
  687. goto clean;
  688. }
  689. Status = GLE_FN_CALL(FALSE,
  690. SetupGetStringField(&InfLineContext,
  691. 3,
  692. (PTSTR)(*SectionNameString),
  693. (*SectionNameStringLen),
  694. NULL)
  695. );
  696. clean:
  697. //
  698. // If the function exits abnormally then clean up any strings allocated.
  699. //
  700. if(Status != NO_ERROR) {
  701. if(*GuidString){
  702. FreeMemory(*GuidString);
  703. *GuidString = NULL;
  704. }
  705. if(TempGuidString) {
  706. FreeMemory(TempGuidString);
  707. }
  708. if(*SectionNameString){
  709. FreeMemory(*SectionNameString);
  710. *SectionNameString = NULL;
  711. }
  712. }
  713. return Status;
  714. }
  715. ULONG
  716. GetSecurityKeyword(
  717. IN HINF InfFile,
  718. IN LPCTSTR WMIInterfaceSection,
  719. IN OUT PTCHAR *SDDLString,
  720. IN OUT ULONG *SDDLStringLen
  721. )
  722. /*++
  723. Routine Description:
  724. The section name specified under the WMIInterface should contain a
  725. security section the specifies the SDDL. It should be in the form
  726. security = <SDDL>. This fcuntion extracts the SDDL. There should
  727. only be one security section, otherwise an error will be returned.
  728. Arguments:
  729. InfLineContext [in] - the line from the INF file
  730. WMIInterfaceSection [in] - the section name indicating what
  731. section contains the security info
  732. SDDLString [in, out] - passed in as NULL by the caller, is
  733. allocated and filled in with the
  734. corresponding security description
  735. string.
  736. SDDLStringLen [in, out] - passed in as 0 by the caller and set
  737. to the maximum length of an INF field.
  738. Returns:
  739. Status, normally NO_ERROR
  740. --*/
  741. {
  742. INFCONTEXT InfLineContext;
  743. DWORD Status;
  744. ULONG FieldCount;
  745. Status = NO_ERROR;
  746. if(SetupFindFirstLine(InfFile,
  747. WMIInterfaceSection,
  748. WMIGUIDSECURITYSECTION_KEY,
  749. &InfLineContext)) {
  750. //
  751. // WmiGuidSecurity = <SDDL>
  752. // sddl will be at index 1
  753. //
  754. FieldCount = SetupGetFieldCount(&InfLineContext);
  755. if(FieldCount < 1) {
  756. Status = ERROR_INVALID_PARAMETER;
  757. goto clean;
  758. }
  759. //
  760. // Get the SDDL string
  761. //
  762. *SDDLStringLen = MAX_INF_STRING_LENGTH;
  763. *SDDLString = AllocMemory(*SDDLStringLen * sizeof(TCHAR));
  764. //
  765. // If the memory wasn't allocated, then return an error
  766. //
  767. if(!(*SDDLString)) {
  768. Status = ERROR_NOT_ENOUGH_MEMORY;
  769. goto clean;
  770. }
  771. Status = GLE_FN_CALL(FALSE,
  772. SetupGetStringField(&InfLineContext,
  773. 1,
  774. (PTSTR)(*SDDLString),
  775. (*SDDLStringLen),
  776. NULL)
  777. );
  778. if(Status == NO_ERROR) {
  779. //
  780. // There should not be more than one security entry
  781. //
  782. if(SetupFindNextMatchLine(&InfLineContext,
  783. WMIGUIDSECURITYSECTION_KEY,
  784. &InfLineContext)) {
  785. Status = ERROR_INVALID_PARAMETER;
  786. goto clean;
  787. }
  788. }
  789. }
  790. clean:
  791. //
  792. // If the function exits abnormally then clean up any strings allocated.
  793. //
  794. if(Status != NO_ERROR) {
  795. if(*SDDLString) {
  796. FreeMemory(*SDDLString);
  797. *SDDLString = NULL;
  798. }
  799. }
  800. return Status;
  801. }
  802. DWORD
  803. __stdcall WmiGuidSecurityINF (
  804. IN DI_FUNCTION InstallFunction,
  805. IN HDEVINFO DeviceInfoSet,
  806. IN PSP_DEVINFO_DATA DeviceInfoData,
  807. IN OUT PCOINSTALLER_CONTEXT_DATA Context
  808. )
  809. /*++
  810. Function:
  811. WmiGuidSecurityINF
  812. Purpose:
  813. Responds to co-installer messages
  814. Arguments:
  815. InstallFunction [in]
  816. DeviceInfoSet [in]
  817. DeviceInfoData [in]
  818. Context [in,out]
  819. Returns:
  820. NO_ERROR, or an error code.
  821. --*/
  822. {
  823. DWORD Status = NO_ERROR;
  824. switch(InstallFunction) {
  825. case DIF_INSTALLDEVICE:
  826. //
  827. // We want to set security on the device before we install to eliminate
  828. // the race condition of setting up a device without security.
  829. // (No Post Processing required)
  830. //
  831. Status = PreProcessInstallDevice(DeviceInfoSet,
  832. DeviceInfoData,
  833. Context);
  834. break;
  835. default:
  836. break;
  837. }
  838. return Status;
  839. }
  840. #if DBG
  841. VOID
  842. DebugPrintX(
  843. PCHAR DebugMessage,
  844. ...
  845. )
  846. {
  847. CHAR SpewBuffer[DEBUG_BUFFER_LENGTH];
  848. va_list ap;
  849. va_start(ap, DebugMessage);
  850. StringCchVPrintf(SpewBuffer, DEBUG_BUFFER_LENGTH, DebugMessage, ap);
  851. OutputDebugStringA("WMIInst: ");
  852. OutputDebugStringA(SpewBuffer);
  853. va_end(ap);
  854. }
  855. #endif