2025-11-28 00:35:46 +09:00

257 lines
7.1 KiB
C++

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
#include "stdafx.h"
#include "QEC.h"
#include <Strsafe.h>
#include <objbase.h>
using namespace SDK_SAMPLE_COMMON;
using namespace SDK_SAMPLE_QEC;
// Helper Function for displaying selection menu.
void showSdkQecInterfaceOptions() throw()
{
wprintf(L"\n x : To Quit");
wprintf(L"\nOption: \n");
}
void showSdkQecExecutionOptions() throw()
{
wprintf(L"\n sdkqec.exe /register : To Register the QEC with NAPAgent");
wprintf(L"\n sdkqec.exe /unregister : To Unregister the QEC from NAPAgent");
wprintf(L"\n sdkqec.exe /execute : To execute the QEC and observe activity");
wprintf(L"\n (for this to succeed, registration must be completed prior)");
}
QecActionCode GetActionFromParams ( __in WCHAR * arg ) throw()
{
HRESULT hr = S_OK;
// default to noaction in case parsing fails
QecActionCode actionCode = NOACTION;
size_t cCount = 0;
size_t maxcCount = 0;
wprintf(L"\nQEC GetActionFromParams: parsing command params");
//size of largest valid argument
maxcCount = sizeof(QecActionCode_Unregister)/sizeof(WCHAR);
hr = StringCchLengthW( arg, maxcCount, &cCount);
if ( FAILED(hr) )
{
wprintf(L"\nQEC GetActionFromParams: unable to determine length of parameter");
goto Cleanup;
}
//performing lowercase comparisons against valid parameters
if ( 0 == _wcsicmp(arg, QecActionCode_Register) )
{
actionCode = DOREGISTER;
goto Cleanup;
}
if ( 0 == _wcsicmp(arg, QecActionCode_Unregister) )
{
actionCode = DOUNREGISTER;
goto Cleanup;
}
if ( 0 == _wcsicmp(arg, QecActionCode_Execute) )
{
actionCode = DOEXECUTE;
goto Cleanup;
}
Cleanup:
return actionCode;
}
//Register the SDKQEC with the NAPAgent
void DoQECRegistration ( CSdkQecModule * sdkQecModule ) throw()
{
HRESULT hr = S_OK;
// Register QEC with NapAgent
hr = sdkQecModule->RegisterSdkQec();
if (FAILED(hr))
{
wprintf(L"\nQEC DoQECUnRegistration: Failed to Register SdkQec with NapAgent (error = %x)\n", hr);
}
return;
}
//Unregister the SDKQEC from the NAPAgent
void DoQECUnRegistration( CSdkQecModule * sdkQecModule ) throw()
{
HRESULT hr = S_OK;
// UnRegister QEC with NapAgent
hr = sdkQecModule->UnregisterSdkQec();
if (FAILED(hr))
{
wprintf(L"\nQEC DoQECUnRegistration: Failed to Unregister SdkQec with NapAgent (error = %x)\n", hr);
}
return;
}
// Have the QEC Bind and run its observation loop, logging data to the console
void DoQECExecution ( ) throw()
{
HRESULT hr = S_OK;
// Create Callback
IQecCallbackPtr callback = NULL;
// pointer to the binding interface
CComPtr<INapEnforcementClientBinding> binding = NULL;
// Create binding.
hr = binding.CoCreateInstance(CLSID_NapEnforcementClientBinding,
NULL,
CLSCTX_INPROC_SERVER);
if (FAILED(hr))
{
wprintf(L"\nQEC DoQECExecution: Failed to create an instance to NapEnforcementClientBinding (error = %x)\n", hr);
goto Cleanup;
}
// Create callback using the binding
callback = QecCallback::CreateInstance(binding);
if (!callback)
{
wprintf(L"\nQEC DoQECExecution: Failed to call QecCallback::CreateInstance (error = %x)\n", hr);
goto Cleanup;
}
// Initialize the binding with the callback
hr = binding->Initialize(NapSdkQecId,callback);
if (FAILED(hr))
{
wprintf(L"\nQEC DoQECExecution: Failed to call NapEnforcementClientBinding::Initialize (error = %x)\n", hr);
wprintf(L"\n\tIs the SDKQEC enabled ? (enable via netsh or the NAP Client Configuration console) \n");
goto Cleanup;
}
// SDK Note:
// The following is just an example to show how QEC will responding to NapAgent's
// Calls like NotifySoHChange etc. Callback functions will be called and will generate
// output while the loop below is running.
//throw-away var used for the input loop
WCHAR input = 0;
showSdkQecInterfaceOptions();
input = getwchar();
while ((input != L'x') && (input != L'X'))
{
showSdkQecInterfaceOptions();
input = getwchar();
}
// Stopping the QEC
hr = binding->Uninitialize();
if (FAILED(hr))
{
wprintf(L"\nQEC DoQECExecution: Failed to call QuarSystemHealthAgentBinding-> Uninitialize (error = %x)\n", hr);
goto Cleanup;
}
wprintf(L"\nQEC DoQECExecution: QEC stopped successfully \n");
Cleanup:
return;
}
// Main function
DWORD __cdecl wmain(DWORD argc, WCHAR * pArgv[]) throw()
{
HRESULT hr = S_OK;
CSecurityDescriptor sd;
QecActionCode actionCode = NOACTION;
CSdkQecModule _AtlModule;
BOOL comInitialized = FALSE;
// only ever expect 2 arguments, 1st is always exe name,
// second should be one of the execution options
if (2 != argc)
{
showSdkQecExecutionOptions();
goto Cleanup;
}
// Start up COM and ATL.
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED );
if (FAILED(hr))
{
wprintf(L"\nQEC main: Failed to initialize COM (error = %x)\n", hr);
goto Cleanup;
}
comInitialized = TRUE;
// setting security on COM to allow communication to/from the
// NAPAgent service, which runs as NetworkService
sd.InitializeFromThreadToken();
sd.Allow("NETWORK_SERVICE", COM_RIGHTS_EXECUTE);
hr = CoInitializeSecurity( sd,
-1,
NULL,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE,
NULL );
if (FAILED(hr))
{
wprintf(L"\nQEC main: Failed to initialize COM security (error = %x)\n", hr);
goto Cleanup;
}
// got an argument - parse it and decide what to do
actionCode = GetActionFromParams( pArgv[1] );
switch (actionCode)
{
case DOREGISTER:
wprintf(L"\nQEC main: Action code is DOREGISTER, proceeding\n");
DoQECRegistration(&_AtlModule);
break;
case DOUNREGISTER:
wprintf(L"\nQEC main: Action code is DOUNREGISTER, proceeding\n");
DoQECUnRegistration(&_AtlModule);
break;
case DOEXECUTE:
wprintf(L"\nQEC main: Action code is DOEXECUTE, proceeding\n");
DoQECExecution();
break;
default:
wprintf(L"\nQEC main: No action code, or unrecognized, proceeding\n");
showSdkQecExecutionOptions();
break;
}
Cleanup:
if (comInitialized)
{
CoUninitialize();
}
return 0;
}