SAL annotation updates & fix warnings (#5617)
Various SAL annotations were either incorrect or not backed up by code. This PR address these issues. NOTE: By default, Start-BuildNativeWindowsBinaries does not enable code analysis and issues detected by SAL annotations are not reported. To identify these issues, run Start-BuildNativeWindowsBinaries to generate the solution and vcxproj files. Launch a Visual Studio developer prompt, cd to src\powershell-native and run msbuild manually. > msbuild PowerShellNative.sln /p:RunCodeAnalysis=true /p:Configuration=RelWithDebInfo /p:Platform=x64 The following changes address all code analysis warnings: - GetRegistryInfo in NativeMsh had incorrect out annotations, remove __opt - Fix handling of various out parameters - check for non-null and initialize - Update and Align SAL annotations for GetFormattedErrorMessage overloads - Allow PluginException to accept NULL message.
This commit is contained in:
parent
22f47295f4
commit
da5d897823
|
@ -78,25 +78,27 @@ namespace NativeMsh
|
||||||
// Note: During successful calls the following values must be freed by the caller:
|
// Note: During successful calls the following values must be freed by the caller:
|
||||||
// pwszMonadVersion
|
// pwszMonadVersion
|
||||||
// pwszRuntimeVersion
|
// pwszRuntimeVersion
|
||||||
// pwzsRegKeyValue
|
// pwszRegKeyValue
|
||||||
//
|
//
|
||||||
// The caller must take care to check to see if they must be freed during error scenarios
|
// The caller must take care to check to see if they must be freed during error scenarios
|
||||||
// because the function may fail after allocating one or more strings.
|
// because the function may fail after allocating one or more strings.
|
||||||
//
|
//
|
||||||
|
_Success_(return == 0)
|
||||||
unsigned int GetRegistryInfo(
|
unsigned int GetRegistryInfo(
|
||||||
__deref_out_opt PWSTR * pwszMonadVersion,
|
__out PWSTR * pwszMonadVersion,
|
||||||
__inout_ecount(1) int * lpMonadMajorVersion,
|
__inout_ecount(1) int * lpMonadMajorVersion,
|
||||||
int monadMinorVersion,
|
int monadMinorVersion,
|
||||||
__deref_out_opt PWSTR * pwszRuntimeVersion,
|
__out PWSTR * pwszRuntimeVersion,
|
||||||
LPCWSTR lpszRegKeyNameToRead,
|
LPCWSTR lpszRegKeyNameToRead,
|
||||||
__deref_out_opt PWSTR * pwzsRegKeyValue);
|
__out PWSTR * pwszRegKeyValue);
|
||||||
|
|
||||||
|
_Success_(return == 0)
|
||||||
unsigned int GetRegistryInfo(
|
unsigned int GetRegistryInfo(
|
||||||
__deref_out_opt PWSTR * pwszMonadVersion,
|
__out PWSTR * pwszMonadVersion,
|
||||||
__inout_ecount(1) int * lpMonadMajorVersion,
|
__inout_ecount(1) int * lpMonadMajorVersion,
|
||||||
int monadMinorVersion,
|
int monadMinorVersion,
|
||||||
__deref_out_opt PWSTR * pwszRuntimeVersion,
|
__out PWSTR * pwszRuntimeVersion,
|
||||||
__deref_out_opt PWSTR * pwszConsoleHostAssemblyName);
|
__out PWSTR * pwszConsoleHostAssemblyName);
|
||||||
|
|
||||||
unsigned int LaunchCoreCLR(
|
unsigned int LaunchCoreCLR(
|
||||||
ClrHostWrapper* hostWrapper,
|
ClrHostWrapper* hostWrapper,
|
||||||
|
|
|
@ -1238,18 +1238,19 @@ namespace NativeMsh
|
||||||
// Note: During successful calls the following values must be freed by the caller:
|
// Note: During successful calls the following values must be freed by the caller:
|
||||||
// pwszMonadVersion
|
// pwszMonadVersion
|
||||||
// pwszRuntimeVersion
|
// pwszRuntimeVersion
|
||||||
// pwzsRegKeyValue
|
// pwszRegKeyValue
|
||||||
//
|
//
|
||||||
// The caller must take care to check to see if they must be freed during error scenarios
|
// The caller must take care to check to see if they must be freed during error scenarios
|
||||||
// because the function may fail after allocating one or more strings.
|
// because the function may fail after allocating one or more strings.
|
||||||
//
|
//
|
||||||
|
_Success_(return == 0)
|
||||||
unsigned int PwrshCommon::GetRegistryInfo(
|
unsigned int PwrshCommon::GetRegistryInfo(
|
||||||
__deref_out_opt PWSTR * pwszMonadVersion,
|
__out PWSTR * pwszMonadVersion,
|
||||||
__inout_ecount(1) int * lpMonadMajorVersion,
|
__inout_ecount(1) int * lpMonadMajorVersion,
|
||||||
int monadMinorVersion,
|
int monadMinorVersion,
|
||||||
__deref_out_opt PWSTR * pwszRuntimeVersion,
|
__out PWSTR * pwszRuntimeVersion,
|
||||||
LPCWSTR lpszRegKeyNameToRead,
|
LPCWSTR lpszRegKeyNameToRead,
|
||||||
__deref_out_opt PWSTR * pwzsRegKeyValue)
|
__out PWSTR * pwszRegKeyValue)
|
||||||
{
|
{
|
||||||
HKEY hEngineKey = NULL;
|
HKEY hEngineKey = NULL;
|
||||||
bool bEngineKeyOpened = true;
|
bool bEngineKeyOpened = true;
|
||||||
|
@ -1257,12 +1258,27 @@ namespace NativeMsh
|
||||||
wchar_t * wszMshEngineRegKeyPath = NULL;
|
wchar_t * wszMshEngineRegKeyPath = NULL;
|
||||||
LPWSTR wszFullMonadVersion = NULL;
|
LPWSTR wszFullMonadVersion = NULL;
|
||||||
|
|
||||||
|
if (NULL != pwszRegKeyValue)
|
||||||
|
{
|
||||||
|
*pwszRegKeyValue = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != pwszRuntimeVersion)
|
||||||
|
{
|
||||||
|
*pwszRuntimeVersion = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL != pwszMonadVersion)
|
||||||
|
{
|
||||||
|
*pwszMonadVersion = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (NULL == pwszMonadVersion ||
|
if (NULL == pwszMonadVersion ||
|
||||||
NULL == lpMonadMajorVersion ||
|
NULL == lpMonadMajorVersion ||
|
||||||
NULL == pwszRuntimeVersion ||
|
NULL == pwszRuntimeVersion ||
|
||||||
NULL == pwzsRegKeyValue)
|
NULL == pwszRegKeyValue)
|
||||||
{
|
{
|
||||||
exitCode = EXIT_CODE_READ_REGISTRY_FAILURE;
|
exitCode = EXIT_CODE_READ_REGISTRY_FAILURE;
|
||||||
break;
|
break;
|
||||||
|
@ -1315,7 +1331,7 @@ namespace NativeMsh
|
||||||
{
|
{
|
||||||
LPCWSTR wszRequestedRegValueName = lpszRegKeyNameToRead;
|
LPCWSTR wszRequestedRegValueName = lpszRegKeyNameToRead;
|
||||||
if (!this->RegQueryREG_SZValue(hEngineKey, wszRequestedRegValueName,
|
if (!this->RegQueryREG_SZValue(hEngineKey, wszRequestedRegValueName,
|
||||||
wszMshEngineRegKeyPath, pwzsRegKeyValue))
|
wszMshEngineRegKeyPath, pwszRegKeyValue))
|
||||||
{
|
{
|
||||||
exitCode = EXIT_CODE_READ_REGISTRY_FAILURE;
|
exitCode = EXIT_CODE_READ_REGISTRY_FAILURE;
|
||||||
break;
|
break;
|
||||||
|
@ -1361,12 +1377,13 @@ namespace NativeMsh
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Success_(return == 0)
|
||||||
unsigned int PwrshCommon::GetRegistryInfo(
|
unsigned int PwrshCommon::GetRegistryInfo(
|
||||||
__deref_out_opt PWSTR * pwszMonadVersion,
|
__out PWSTR * pwszMonadVersion,
|
||||||
__inout_ecount(1) int * lpMonadMajorVersion,
|
__inout_ecount(1) int * lpMonadMajorVersion,
|
||||||
int monadMinorVersion,
|
int monadMinorVersion,
|
||||||
__deref_out_opt PWSTR * pwszRuntimeVersion,
|
__out PWSTR * pwszRuntimeVersion,
|
||||||
__deref_out_opt PWSTR * pwszConsoleHostAssemblyName)
|
__out PWSTR * pwszConsoleHostAssemblyName)
|
||||||
{
|
{
|
||||||
return GetRegistryInfo(pwszMonadVersion,
|
return GetRegistryInfo(pwszMonadVersion,
|
||||||
lpMonadMajorVersion,
|
lpMonadMajorVersion,
|
||||||
|
|
|
@ -217,7 +217,7 @@ int __cdecl wmain(const int argc, const wchar_t* argv[])
|
||||||
if (debug)
|
if (debug)
|
||||||
{
|
{
|
||||||
::wprintf(L" Attach the debugger to powershell.exe and press any key to continue\n");
|
::wprintf(L" Attach the debugger to powershell.exe and press any key to continue\n");
|
||||||
::getchar();
|
(void) ::getchar();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (helpRequested)
|
if (helpRequested)
|
||||||
|
|
|
@ -31,15 +31,18 @@ LPCWSTR g_MAIN_BINARY_NAME = L"pwrshplugin.dll";
|
||||||
// the caller should free pwszErrorMessage using LocalFree().
|
// the caller should free pwszErrorMessage using LocalFree().
|
||||||
// returns: If the function succeeds the return value is the number of CHARs stored int the output
|
// returns: If the function succeeds the return value is the number of CHARs stored int the output
|
||||||
// buffer, excluding the terminating null character. If the function fails the return value is zero.
|
// buffer, excluding the terminating null character. If the function fails the return value is zero.
|
||||||
#pragma prefast(push)
|
_Success_(return > 0)
|
||||||
#pragma prefast (disable: 28196)
|
DWORD GetFormattedErrorMessage(__out PWSTR * pwszErrorMessage, DWORD dwMessageId, va_list* arguments)
|
||||||
DWORD GetFormattedErrorMessage(__deref_out PWSTR * pwszErrorMessage, DWORD dwMessageId, va_list* arguments)
|
|
||||||
#pragma prefast(pop)
|
|
||||||
{
|
{
|
||||||
DWORD dwLength = 0;
|
DWORD dwLength = 0;
|
||||||
|
LPWSTR wszSystemErrorMessage = NULL;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
if (NULL == pwszErrorMessage)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
*pwszErrorMessage = NULL;
|
*pwszErrorMessage = NULL;
|
||||||
|
|
||||||
if (NULL == g_hResourceInstance)
|
if (NULL == g_hResourceInstance)
|
||||||
|
@ -51,8 +54,6 @@ DWORD GetFormattedErrorMessage(__deref_out PWSTR * pwszErrorMessage, DWORD dwMes
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
LPWSTR wszSystemErrorMessage = NULL;
|
|
||||||
//string function
|
|
||||||
dwLength = FormatMessageW(
|
dwLength = FormatMessageW(
|
||||||
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_ALLOCATE_BUFFER,
|
||||||
g_hResourceInstance,
|
g_hResourceInstance,
|
||||||
|
@ -62,28 +63,36 @@ DWORD GetFormattedErrorMessage(__deref_out PWSTR * pwszErrorMessage, DWORD dwMes
|
||||||
0,
|
0,
|
||||||
arguments);
|
arguments);
|
||||||
|
|
||||||
if (dwLength > 0)
|
if (dwLength == 0)
|
||||||
{
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
*pwszErrorMessage = new WCHAR[dwLength + 1];
|
*pwszErrorMessage = new WCHAR[dwLength + 1];
|
||||||
if (NULL != *pwszErrorMessage)
|
if (*pwszErrorMessage == NULL)
|
||||||
{
|
{
|
||||||
//string function
|
dwLength = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (FAILED(StringCchCopyW(*pwszErrorMessage, dwLength + 1, wszSystemErrorMessage)))
|
if (FAILED(StringCchCopyW(*pwszErrorMessage, dwLength + 1, wszSystemErrorMessage)))
|
||||||
{
|
{
|
||||||
dwLength = 0;
|
dwLength = 0;
|
||||||
delete [] (*pwszErrorMessage);
|
delete [] (*pwszErrorMessage);
|
||||||
*pwszErrorMessage = NULL;
|
*pwszErrorMessage = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
LocalFree(wszSystemErrorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
}while(false);
|
}while(false);
|
||||||
|
|
||||||
|
if (NULL != wszSystemErrorMessage)
|
||||||
|
{
|
||||||
|
LocalFree(wszSystemErrorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
return dwLength;
|
return dwLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD GetFormattedErrorMessage(__deref_out PZPWSTR pwszErrorMessage, DWORD dwMessageId, ...)
|
DWORD GetFormattedErrorMessage(__out PWSTR * pwszErrorMessage, DWORD dwMessageId, ...)
|
||||||
{
|
{
|
||||||
DWORD result = 0;
|
DWORD result = 0;
|
||||||
|
|
||||||
|
@ -307,12 +316,19 @@ DWORD ReportOperationComplete(WSMAN_PLUGIN_REQUEST *requestDetails, DWORD errorC
|
||||||
|
|
||||||
DWORD result = EXIT_CODE_SUCCESS;
|
DWORD result = EXIT_CODE_SUCCESS;
|
||||||
PWSTR pwszErrorMessage = NULL;
|
PWSTR pwszErrorMessage = NULL;
|
||||||
GetFormattedErrorMessage(&pwszErrorMessage, errorCode);
|
if (GetFormattedErrorMessage(&pwszErrorMessage, errorCode) == 0)
|
||||||
|
|
||||||
result = WSManPluginOperationComplete(requestDetails, 0, errorCode, pwszErrorMessage);
|
|
||||||
|
|
||||||
if (NULL != pwszErrorMessage)
|
|
||||||
{
|
{
|
||||||
|
/* if an error message could not be loaded, generate a fallback
|
||||||
|
message to provide a level of diagnosability.
|
||||||
|
*/
|
||||||
|
WCHAR szFallbackMessageMessage[64] = L"\0";
|
||||||
|
swprintf_s(szFallbackMessageMessage, _countof(szFallbackMessageMessage), L"ReportOperationComplete: %d", errorCode);
|
||||||
|
|
||||||
|
result = WSManPluginOperationComplete(requestDetails, 0, errorCode, szFallbackMessageMessage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = WSManPluginOperationComplete(requestDetails, 0, errorCode, pwszErrorMessage);
|
||||||
delete[] pwszErrorMessage;
|
delete[] pwszErrorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,6 @@
|
||||||
|
|
||||||
const int EXIT_CODE_BAD_INPUT = 100;
|
const int EXIT_CODE_BAD_INPUT = 100;
|
||||||
|
|
||||||
extern DWORD GetFormattedErrorMessage(__deref_out PWSTR * pwszErrorMessage, DWORD dwMessageId, ...);
|
extern DWORD GetFormattedErrorMessage(__out PWSTR * pwszErrorMessage, DWORD dwMessageId, ...);
|
||||||
extern unsigned int ConstructPowerShellVersion(int iPSMajorVersion, int iPSMinorVersion, __deref_out_opt PWSTR *pwszMonadVersion);
|
extern unsigned int ConstructPowerShellVersion(int iPSMajorVersion, int iPSMinorVersion, __deref_out_opt PWSTR *pwszMonadVersion);
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,10 @@ unsigned int PowerShellClrWorker::LoadWorkerCallbackPtrs(
|
||||||
{
|
{
|
||||||
PWSTR msg = NULL;
|
PWSTR msg = NULL;
|
||||||
exitCode = g_MANAGED_METHOD_RESOLUTION_FAILED;
|
exitCode = g_MANAGED_METHOD_RESOLUTION_FAILED;
|
||||||
GetFormattedErrorMessage(&msg, exitCode);
|
/* NOTE: don't use a string literal for a fallback; PlugInException expects msg to allocated
|
||||||
|
and will free it but also supports NULL.
|
||||||
|
*/
|
||||||
|
(void) GetFormattedErrorMessage(&msg, exitCode);
|
||||||
*pPluginException = new PlugInException(exitCode, msg);
|
*pPluginException = new PlugInException(exitCode, msg);
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,6 +490,11 @@ private:
|
||||||
{
|
{
|
||||||
iMajorVersion = iVPSMajorVersion;
|
iMajorVersion = iVPSMajorVersion;
|
||||||
|
|
||||||
|
if (NULL != wszMgdPlugInFileName)
|
||||||
|
{
|
||||||
|
*wszMgdPlugInFileName = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
exitCode = ConstructPowerShellVersion(iVPSMajorVersion, iVPSMinorVersion, &wszMonadVersion);
|
exitCode = ConstructPowerShellVersion(iVPSMajorVersion, iVPSMinorVersion, &wszMonadVersion);
|
||||||
if (EXIT_CODE_SUCCESS != exitCode)
|
if (EXIT_CODE_SUCCESS != exitCode)
|
||||||
{
|
{
|
||||||
|
@ -561,10 +566,19 @@ private:
|
||||||
_In_ PWSTR wszMgdPlugInFileName,
|
_In_ PWSTR wszMgdPlugInFileName,
|
||||||
_In_ PWSTR wszVCLRVersion, // Conditionally set to wszCLRVersion on success
|
_In_ PWSTR wszVCLRVersion, // Conditionally set to wszCLRVersion on success
|
||||||
_In_ PWSTR wszVAppBase, // Conditionally set to wszAppBase on success
|
_In_ PWSTR wszVAppBase, // Conditionally set to wszAppBase on success
|
||||||
__out_opt PlugInException** pPluginException )
|
__out PlugInException** pPluginException )
|
||||||
{
|
{
|
||||||
unsigned int exitCode = EXIT_CODE_SUCCESS;
|
unsigned int exitCode = EXIT_CODE_SUCCESS;
|
||||||
|
|
||||||
|
if (NULL != pPluginException)
|
||||||
|
{
|
||||||
|
*pPluginException = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return g_INVALID_INPUT;
|
||||||
|
}
|
||||||
|
|
||||||
if (bIsPluginLoaded)
|
if (bIsPluginLoaded)
|
||||||
{
|
{
|
||||||
return g_MANAGED_PLUGIN_ALREADY_LOADED;
|
return g_MANAGED_PLUGIN_ALREADY_LOADED;
|
||||||
|
@ -577,8 +591,6 @@ private:
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
*pPluginException = NULL;
|
|
||||||
|
|
||||||
// Setting global AppBase and CLR Version
|
// Setting global AppBase and CLR Version
|
||||||
wszCLRVersion = wszVCLRVersion;
|
wszCLRVersion = wszVCLRVersion;
|
||||||
wszAppBase = wszVAppBase;
|
wszAppBase = wszVAppBase;
|
||||||
|
@ -768,7 +780,9 @@ private:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PWSTR msg = NULL;
|
PWSTR msg = NULL;
|
||||||
GetFormattedErrorMessage(&msg, g_OPTION_SET_NOT_COMPLY, g_BUILD_VERSION);
|
(void) GetFormattedErrorMessage(&msg, g_OPTION_SET_NOT_COMPLY, g_BUILD_VERSION);
|
||||||
|
/* NOTE: Passing possible NULL msg. PlugInExpecption requires allocated
|
||||||
|
or NULL. Literal strings are not supported. */
|
||||||
throw new PlugInException(exitCode, msg);
|
throw new PlugInException(exitCode, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,7 +140,7 @@ public:
|
||||||
// the memory.
|
// the memory.
|
||||||
PWSTR extendedErrorInformation;
|
PWSTR extendedErrorInformation;
|
||||||
|
|
||||||
PlugInException(DWORD msgId, __in PWSTR msg)
|
PlugInException(DWORD msgId, __in_opt PWSTR msg)
|
||||||
{
|
{
|
||||||
dwMessageId = msgId;
|
dwMessageId = msgId;
|
||||||
extendedErrorInformation = msg;
|
extendedErrorInformation = msg;
|
||||||
|
|
Loading…
Reference in a new issue