If you look at PolDllApi.h, where the FESF Policy DLL structures and callback functions are all defined, you'll almost certainly notice that the function prototypes for the callback functions are filled with what might look to you to be strange notes. For example:
_Success_(return == true)
FESFAPI
POL_GET_KEY_NEW_FILE(
_In_ FE_POLICY_PATH_INFORMATION *PolicyPathInfo,
_In_ DWORD ThreadId,
_Outptr_result_bytebuffer_(*PolHeaderDataSize) PVOID *PolHeaderData,
_Out_ _Deref_out_range_(>, 0) DWORD *PolHeaderDataSize,
_Outptr_result_z_ LPCWSTR *PolUniqueAlgorithmId,
_Outptr_result_bytebuffer_(*PolKeySize) PVOID *PolKey,
_Out_ _Deref_out_range_(>, 0) DWORD *PolKeySize,
_Outptr_result_maybenull_ PVOID *PolCleanupInfo
);
All the weird stuff that doesn't look like C++ are "annotations" in Microsoft Source-code Annotation Language (SAL). These annotations describe to the compiler and to Visual Studio Code Analysis how the various parameters of a function are to be used. We're big fans of SAL Annotations here at OSR because they've helped us find and prevent more bugs to date than we could ever count. You can read a bit about SAL Annotations in our blog post: http://www.osr.com/blog/2015/02/23/sal-annotations-dont-hate-im-beautiful/
How do these annotations affect you? Well, mostly, they won't. Except that if you enable Visual Studio Code Analysis you'll be able to find problems with how you're implementing your Policy DLL callbacks more quickly.
There is one interesting issue that you'll encounter during implementation, however. And that issue is that you will almost certainly not want to duplicate all the SAL Annotations when you declare or define your callback function. In other words, when you write the code that implements POL_GET_KEY_NEW_FILE, you probably won't want to have to include the SAL for each of your parameters. And, fortunately, that's easy to avoid.
When declaring a callback function in your Policy DLL's header file, we recommend that you use the type definition that we provide in the first line of the Syntax section of the documentation. The location of the type definition is shown in Figure 3.
In your implementation file, when you define the code for your callback function, we suggest that you use the single annotation _Use_decl_annotations_. This will avoid you having to duplicate the annotations, and leave your source code clean and easy to read.
We've provided an example of this approach below.
Figure 3 – Type Definition Example
If you're implementing the PolGetKeyNewFile callback, you'd declare your function in your header file like this:
POL_GET_KEY_NEW_FILE MyPolicyDllGetNewFileKey;
And in your implementation file, where you define your function, your code would look like this (note the use of _Use_decl_annotations_ has been highlighted):
_Use_decl_annotations_
bool MyPolicyDllGetNewFileKey(
FE_POLICY_PATH_INFORMATION *PolicyPathInfo,
DWORD ThreadId,
PVOID *PolHeaderData,
DWORD *PolHeaderDataSize,
LPCWSTR *PolUniqueAlgorithmId,
PVOID *PolKey,
DWORD *PolKeySize,
PVOID *PolCleanupInfo)
{
//
// Get the fully qualified executable path
//
CComBSTR exePath;
HRESULT hr = g_pFesfUtil->GetExecutablePathForThreadId(ThreadId, &exePath);
if (FAILED(hr))
{
return false;
}
// ... and the rest of your function goes here...
Combining the use of the Type Definition and _Use_decl_annotations_ will get you all the benefits of using SAL Annotations for your callbacks, without having to look at any of the ugly annotation text.