Igor Levicki asked for a plain C version of the sample code to detect whether Windows is running in S-Mode. I didn’t write one for two reasons. First, I didn’t realize that so many people still tried to use COM from plain C. And second, I didn’t realize that the people who try to use COM from plain C are not sufficiently familiar with how COM works at the ABI level to perform the mechanical conversion themselves.
p->Method(args)becomesp->lpVtbl->Method(p, args).- Copying a C++ smart COM pointer consists of copying the raw pointer and performing an
AddRefif the raw pointer is non-null. - Destroying a C++ smart COM pointer consists of performing a
Releaseif the raw pointer is non-null. - Before overwriting a C++ smart COM pointer, remember the old pointer value, and if it is non-null,
Releaseit after youAddRefthe new non-null pointer value.
The wrinkle added by the Windows Runtime is that C doesn’t support namespaces, so the Windows Runtime type names are decorated by their namespaces.
And since you’re not using WRL, then you don’t get the WRL helpers for creating HSTRINGs, so you have to call the low-level HSTRING functions yourself.
#include <Windows.System.Profile.h>
HRESULT ShouldSuggestCompanion(BOOL* suggestCompanion)
{
HSTRING_HEADER header;
HSTRING className;
HRESULT hr;
hr = WindowsCreateStringReference(RuntimeClass_Windows_System_Profile_WindowsIntegrityPolicy,
ARRAYSIZE(RuntimeClass_Windows_System_Profile_WindowsIntegrityPolicy) - 1,
&header, &className);
if (SUCCEEDED(hr))
{
__x_ABI_CWindows_CSystem_CProfile_CIWindowsIntegrityPolicyStatics* statics;
hr = RoGetActivationFactory(className, &IID___x_ABI_CWindows_CSystem_CProfile_CIWindowsIntegrityPolicyStatics, (void**)&statics);
if (SUCCEEDED(hr))
{
boolean isEnabled;
hr = statics->lpVtbl->get_IsEnabled(statics, &isEnabled);
if (SUCCEEDED(hr))
{
if (isEnabled)
{
// System is in S-Mode
boolean canDisable;
hr = statics->lpVtbl->get_CanDisable(statics, &canDisable);
if (SUCCEEDED(hr))
{
// System is in S-Mode but can be taken out of S-Mode
*suggestCompanion = TRUE;
}
else
{
// System is locked into S-Mode
*suggestCompanion = FALSE;
}
}
else
{
// System is not in S-Mode
*suggestCompanion = TRUE;
}
}
statics->lpVtbl->Release(statics);
}
}
return hr;
}
There is a micro-optimization here: We don’t need to call WindowsÂDeleteÂString(hstring) at the end because the string we created is a string reference, and those are not reference-counted. (All of the memory is preallocated; there is nothing to clean up.) That said, it doesn’t hurt to call WindowsÂDeleteÂString on a string reference; it’s just a nop.
It wasn’t that exciting. It was merely annoying. So that’s another reason I didn’t bother including a plain C sample.
Baltasar GarcÃa offered a simplification to the original code:
bool s_mode = WindowsIntegrityPolicy.IsEnabled; bool unlockable_s_mode = WindowsIntegrityPolicy.CanDisable; bool suggestCompanion = !s_mode || (s_mode && unlockable_s_mode);
and Csaba Varga simplified it further:
bool suggestCompanion = !s_mode || unlockable_s_mode;
I agree that these are valid simplifications, but I spelled it out the long way to make the multi-step logic more explicit, and to allow you to insert other logic into the blocks that right now merely contain an explanatory comment and a Boolean assignment.
0 comments
Be the first to start the discussion.