@@ -36,17 +36,49 @@ namespace AppInstaller::CLI::ConfigurationRemoting
36
36
}
37
37
#endif
38
38
39
+ // This is implemented completely in the packaged context for now, if we want to make it more configurable, we will probably want to move it to configuration and
40
+ // have this implementation leverage that one with an event handler for the packaged specifics.
41
+ // TODO: Add SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties and pass values along to sets on creation
42
+ // In turn, any properties must only be set via the command line (or eventual UI requests to the user).
43
+ struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
44
+ {
45
+ DynamicFactory ();
46
+
47
+ IConfigurationSetProcessor CreateSetProcessor (const ConfigurationSet& configurationSet);
48
+
49
+ winrt::event_token Diagnostics (const EventHandler<IDiagnosticInformation>& handler);
50
+ void Diagnostics (const winrt::event_token& token) noexcept ;
51
+
52
+ DiagnosticLevel MinimumLevel ();
53
+ void MinimumLevel (DiagnosticLevel value);
54
+
55
+ HRESULT STDMETHODCALLTYPE SetLifetimeWatcher (IUnknown* watcher);
56
+
57
+ IConfigurationSetProcessorFactory& DefaultFactory ();
58
+
59
+ void SendDiagnostics (const IDiagnosticInformation& information);
60
+
61
+ private:
62
+ IConfigurationSetProcessorFactory m_defaultRemoteFactory;
63
+ winrt::event<EventHandler<IDiagnosticInformation>> m_diagnostics;
64
+ IConfigurationSetProcessorFactory::Diagnostics_revoker m_factoryDiagnosticsEventRevoker;
65
+ std::mutex m_diagnosticsMutex;
66
+ DiagnosticLevel m_minimumLevel = DiagnosticLevel::Informational;
67
+ };
68
+
39
69
struct DynamicProcessorInfo
40
70
{
41
71
IConfigurationSetProcessorFactory Factory;
42
72
IConfigurationSetProcessor Processor;
73
+ IConfigurationSetProcessorFactory::Diagnostics_revoker DiagnosticsEventRevoker;
43
74
};
44
75
45
76
struct DynamicSetProcessor : winrt::implements<DynamicSetProcessor, IConfigurationSetProcessor>
46
77
{
47
78
using ProcessorMap = std::map<Security::IntegrityLevel, DynamicProcessorInfo>;
48
79
49
- DynamicSetProcessor (IConfigurationSetProcessorFactory defaultRemoteFactory, IConfigurationSetProcessor defaultRemoteSetProcessor, const ConfigurationSet& configurationSet) : m_configurationSet(configurationSet)
80
+ DynamicSetProcessor (winrt::com_ptr<DynamicFactory> dynamicFactory, IConfigurationSetProcessor defaultRemoteSetProcessor, const ConfigurationSet& configurationSet) :
81
+ m_dynamicFactory (std::move(dynamicFactory)), m_configurationSet(configurationSet)
50
82
{
51
83
#ifndef AICLI_DISABLE_TEST_HOOKS
52
84
m_enableTestMode = GetConfigurationSetMetadataOverride (m_configurationSet, EnableTestModeTestGuid);
@@ -58,7 +90,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
58
90
m_currentIntegrityLevel = Security::GetEffectiveIntegrityLevel ();
59
91
#endif
60
92
61
- m_setProcessors.emplace (m_currentIntegrityLevel, DynamicProcessorInfo{ defaultRemoteFactory , defaultRemoteSetProcessor });
93
+ m_setProcessors.emplace (m_currentIntegrityLevel, DynamicProcessorInfo{ m_dynamicFactory-> DefaultFactory () , defaultRemoteSetProcessor});
62
94
}
63
95
64
96
IConfigurationUnitProcessorDetails GetUnitProcessorDetails (const ConfigurationUnit& unit, ConfigurationUnitDetailFlags detailFlags)
@@ -212,6 +244,7 @@ namespace AppInstaller::CLI::ConfigurationRemoting
212
244
ProcessorMap::iterator CreateSetProcessorForIntegrityLevel (Security::IntegrityLevel integrityLevel)
213
245
{
214
246
IConfigurationSetProcessorFactory factory;
247
+ IConfigurationSetProcessorFactory::Diagnostics_revoker factoryDiagnosticsEventRevoker;
215
248
216
249
// If we got here, the only option is that the current integrity level is not High.
217
250
if (integrityLevel == Security::IntegrityLevel::High)
@@ -228,9 +261,22 @@ namespace AppInstaller::CLI::ConfigurationRemoting
228
261
THROW_WIN32 (ERROR_NOT_SUPPORTED);
229
262
}
230
263
231
- return m_setProcessors.emplace (integrityLevel, DynamicProcessorInfo{ factory, factory.CreateSetProcessor (m_configurationSet) }).first ;
264
+ if (factory)
265
+ {
266
+ factoryDiagnosticsEventRevoker = factory.Diagnostics (winrt::auto_revoke,
267
+ [weak_this{ get_weak () }](const IInspectable&, const IDiagnosticInformation& information)
268
+ {
269
+ if (auto strong_this{ weak_this.get () })
270
+ {
271
+ strong_this->m_dynamicFactory ->SendDiagnostics (information);
272
+ }
273
+ });
274
+ }
275
+
276
+ return m_setProcessors.emplace (integrityLevel, DynamicProcessorInfo{ factory, factory.CreateSetProcessor (m_configurationSet), std::move (factoryDiagnosticsEventRevoker) }).first ;
232
277
}
233
278
279
+ winrt::com_ptr<DynamicFactory> m_dynamicFactory;
234
280
Security::IntegrityLevel m_currentIntegrityLevel;
235
281
ProcessorMap m_setProcessors;
236
282
ConfigurationSet m_configurationSet;
@@ -243,52 +289,68 @@ namespace AppInstaller::CLI::ConfigurationRemoting
243
289
#endif
244
290
};
245
291
246
- // This is implemented completely in the packaged context for now, if we want to make it more configurable, we will probably want to move it to configuration and
247
- // have this implementation leverage that one with an event handler for the packaged specifics.
248
- // TODO: Add SetProcessorFactory::IPwshConfigurationSetProcessorFactoryProperties and pass values along to sets on creation
249
- // In turn, any properties must only be set via the command line (or eventual UI requests to the user).
250
- struct DynamicFactory : winrt::implements<DynamicFactory, IConfigurationSetProcessorFactory, winrt::cloaked<WinRT::ILifetimeWatcher>>, WinRT::LifetimeWatcherBase
292
+ DynamicFactory::DynamicFactory ()
251
293
{
252
- DynamicFactory ()
253
- {
254
- m_defaultRemoteFactory = CreateOutOfProcessFactory ();
255
- }
294
+ m_defaultRemoteFactory = CreateOutOfProcessFactory ();
256
295
257
- IConfigurationSetProcessor CreateSetProcessor ( const ConfigurationSet& configurationSet )
296
+ if (m_defaultRemoteFactory )
258
297
{
259
- return winrt::make<DynamicSetProcessor>(m_defaultRemoteFactory, m_defaultRemoteFactory.CreateSetProcessor (configurationSet), configurationSet);
298
+ m_factoryDiagnosticsEventRevoker = m_defaultRemoteFactory.Diagnostics (winrt::auto_revoke,
299
+ [weak_this{ get_weak () }](const IInspectable&, const IDiagnosticInformation& information)
300
+ {
301
+ if (auto strong_this{ weak_this.get () })
302
+ {
303
+ strong_this->SendDiagnostics (information);
304
+ }
305
+ });
260
306
}
307
+ }
261
308
262
- winrt::event_token Diagnostics (const EventHandler<IDiagnosticInformation>&)
263
- {
264
- // TODO: If we want diagnostics here, see ConfigurationProcessor for how to integrate nicely with the infrastructure.
265
- // Best solution is probably to create a base class that both can leverage to handle it cleanly.
266
- return {};
267
- }
309
+ IConfigurationSetProcessor DynamicFactory::CreateSetProcessor (const ConfigurationSet& configurationSet)
310
+ {
311
+ return winrt::make<DynamicSetProcessor>(get_strong (), m_defaultRemoteFactory.CreateSetProcessor (configurationSet), configurationSet);
312
+ }
268
313
269
- void Diagnostics (const winrt::event_token&) noexcept
270
- {
271
- }
314
+ winrt::event_token DynamicFactory::Diagnostics (const EventHandler<IDiagnosticInformation>& handler)
315
+ {
316
+ return m_diagnostics.add (handler);
317
+ }
272
318
273
- DiagnosticLevel MinimumLevel ()
274
- {
275
- return m_minimumLevel ;
276
- }
319
+ void DynamicFactory::Diagnostics ( const winrt::event_token& token) noexcept
320
+ {
321
+ m_diagnostics. remove (token) ;
322
+ }
277
323
278
- void MinimumLevel (DiagnosticLevel value )
279
- {
280
- m_minimumLevel = value ;
281
- }
324
+ DiagnosticLevel DynamicFactory:: MinimumLevel ()
325
+ {
326
+ return m_minimumLevel;
327
+ }
282
328
283
- HRESULT STDMETHODCALLTYPE SetLifetimeWatcher (IUnknown* watcher)
329
+ void DynamicFactory::MinimumLevel (DiagnosticLevel value)
330
+ {
331
+ m_minimumLevel = value;
332
+ }
333
+
334
+ HRESULT STDMETHODCALLTYPE DynamicFactory::SetLifetimeWatcher (IUnknown* watcher)
335
+ {
336
+ return WinRT::LifetimeWatcherBase::SetLifetimeWatcher (watcher);
337
+ }
338
+
339
+ IConfigurationSetProcessorFactory& DynamicFactory::DefaultFactory ()
340
+ {
341
+ return m_defaultRemoteFactory;
342
+ }
343
+
344
+ void DynamicFactory::SendDiagnostics (const IDiagnosticInformation& information) try
345
+ {
346
+ if (information.Level () >= m_minimumLevel)
284
347
{
285
- return WinRT::LifetimeWatcherBase::SetLifetimeWatcher (watcher);
348
+ std::lock_guard<std::mutex> lock{ m_diagnosticsMutex };
349
+ m_diagnostics (*this , information);
286
350
}
287
-
288
- private:
289
- IConfigurationSetProcessorFactory m_defaultRemoteFactory;
290
- DiagnosticLevel m_minimumLevel = DiagnosticLevel::Informational;
291
- };
351
+ }
352
+ // While diagnostics can be important, a failure to send them should not cause additional issues.
353
+ catch (...) {}
292
354
}
293
355
294
356
winrt::Microsoft::Management::Configuration::IConfigurationSetProcessorFactory CreateDynamicRuntimeFactory ()
0 commit comments