Skip to content

Add Microsoft.Windows/FeatureOnDemandList resource#1433

Draft
SteveL-MSFT wants to merge 3 commits intoPowerShell:mainfrom
SteveL-MSFT:featureondemand-resource
Draft

Add Microsoft.Windows/FeatureOnDemandList resource#1433
SteveL-MSFT wants to merge 3 commits intoPowerShell:mainfrom
SteveL-MSFT:featureondemand-resource

Conversation

@SteveL-MSFT
Copy link
Member

@SteveL-MSFT SteveL-MSFT commented Mar 14, 2026

PR Summary

Add Microsoft.Windows/FeatureOnDemandList resource supporting get, set, and export operations

  • name is required for get and set and must be exact case-insensitive match
  • export supports wildcard filtering for name, displayName and description
  • When using export, only the name and state are returned since retrieving all of the properties is extremely slow, however, if any property is used as a filter then those properties must be retrieved and will be much slower to filter

@SteveL-MSFT SteveL-MSFT force-pushed the featureondemand-resource branch from 8b09a06 to 40036b3 Compare March 14, 2026 17:02
Steve Lee (POWERSHELL HE/HIM) (from Dev Box) added 2 commits March 14, 2026 14:01
@SteveL-MSFT SteveL-MSFT force-pushed the featureondemand-resource branch from 1397b87 to af8e5e6 Compare March 14, 2026 21:02
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Windows DSC resource (Microsoft.Windows/FeatureOnDemandList) to the dism_dsc resource host, alongside refactors to share DISM state/wildcard filtering utilities and to speed up export operations by avoiding expensive per-item info calls unless needed.

Changes:

  • Add Microsoft.Windows/FeatureOnDemandList resource with get/set/export backed by DISM capability APIs.
  • Refactor shared DISM state + wildcard filtering into a new util module and update OptionalFeature export to return basic (name/state) results by default.
  • Update resource manifests, localization strings, and add Pester tests for the new capability resource.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
resources/dism_dsc/src/optional_feature/dism.rs Adds DISM capability API bindings and refactors feature/capability enumeration and info retrieval.
resources/dism_dsc/src/util.rs Introduces shared DismState and wildcard/filter helpers used by both resources.
resources/dism_dsc/src/main.rs Updates CLI dispatch to route by operation + resource type.
resources/dism_dsc/src/feature_on_demand/* Implements Feature on Demand get/set/export handlers and types.
resources/dism_dsc/src/optional_feature/export.rs Optimizes export by returning basic feature objects unless “full info” filtering is requested.
resources/dism_dsc/src/optional_feature/types.rs Switches feature state to shared DismState and adds shared filter matching.
resources/dism_dsc/src/optional_feature/mod.rs Exposes DISM bindings module for reuse by Feature on Demand implementation.
resources/dism_dsc/src/optional_feature/set.rs Reuses shared get_computer_name helper.
resources/dism_dsc/tests/featureOnDemand_{get,set,export}.tests.ps1 Adds Pester coverage for new FeatureOnDemandList resource.
resources/dism_dsc/tests/optionalFeature_export.tests.ps1 Updates expectations for basic export output and “full-info filter” behavior.
resources/dism_dsc/featureondemand.dsc.resource.json Adds the new DSC resource manifest and embedded schema.
resources/dism_dsc/optionalfeature.dsc.resource.json Updates args to include resource type for the new dispatcher format.
resources/dism_dsc/locales/en-us.toml Adds localized messages for FoD operations and dispatcher changes.
resources/dism_dsc/.project.data.json Ensures the new resource manifest is copied into the Windows bundle.
.vscode/settings.json Adds workspace settings related to terminal auto-approval.
Comments suppressed due to low confidence (1)

resources/dism_dsc/src/optional_feature/dism.rs:38

  • DismFeatureInfo is also packed(4), but it contains pointer fields (*const u16). With 4-byte packing on 64-bit, the offsets/stride are very likely different from the actual DISM struct layout, so reading fields like display_name/description can be invalid. Use the correct #[repr(C)] layout (and avoid packing unless the header explicitly requires it).
#[repr(C, packed(4))]
struct DismFeatureInfo {
    feature_name: *const u16,
    state: i32,
    display_name: *const u16,

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +51 to +55
#[repr(C, packed(4))]
struct DismCapabilityDetail {
name: *const u16,
state: i32,
display_name: *const u16,
Comment on lines +516 to +520
for i in 0..count as usize {
let cap = &*caps_ptr.add(i);
let name = from_wide_ptr(cap.name);
result.push((name, cap.state));
}
Comment on lines +98 to +102
It 'can remove a capability and returns updated state' -Skip:(!$isElevated) -Tag 'Mutating' {
$inputJson = '{"capabilities":[{"name":"' + $knownNotPresentCapability + '","state":"NotPresent"}]}'
$output = dsc resource set -r Microsoft.Windows/FeatureOnDemandList -i $inputJson | ConvertFrom-Json
$LASTEXITCODE | Should -Be 0
$output.afterState.capabilities | Should -Not -BeNullOrEmpty
Comment on lines 292 to 296
let result = unsafe {
let feature_name_val = std::ptr::addr_of!((*info_ptr).feature_name).read_unaligned();
let state_val = std::ptr::addr_of!((*info_ptr).state).read_unaligned();
let display_name_val = std::ptr::addr_of!((*info_ptr).display_name).read_unaligned();
let description_val = std::ptr::addr_of!((*info_ptr).description).read_unaligned();
let restart_val = std::ptr::addr_of!((*info_ptr).restart_required).read_unaligned();
let info = &*info_ptr;
let feature_info = OptionalFeatureInfo {
feature_name: Some(from_wide_ptr(feature_name_val)),
feature_name: Some(from_wide_ptr(info.feature_name)),
exist: None,
Comment on lines 373 to 377
for i in 0..count as usize {
let name_ptr = std::ptr::addr_of!((*features_ptr.add(i)).feature_name).read_unaligned();
let state_val = std::ptr::addr_of!((*features_ptr.add(i)).state).read_unaligned();
let name = from_wide_ptr(name_ptr);
result.push((name, state_val));
let feature = &*features_ptr.add(i);
let name = from_wide_ptr(feature.feature_name);
result.push((name, feature.state));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants