294 lines
11 KiB
C++
294 lines
11 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.
|
|
|
|
/****************************************************************************
|
|
|
|
FILE: Windows Parental Controls (WPC) Compliance Application sample
|
|
|
|
PURPOSE: Shows simple flow of Compliance API usage for an application
|
|
implementing HTTP-based communication, and not needing any, or at
|
|
least infrequent, access to the Parental Controls WMI-based settings
|
|
policy management interfaces.
|
|
|
|
FUNCTIONS:
|
|
|
|
wmain() - implements overall command line application
|
|
|
|
COMMENTS:
|
|
Sample may easily be modified for time, games, or application
|
|
restrictions awareness.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "ComplianceApp.h"
|
|
|
|
HRESULT EventParseXML(IXMLDOMDocument2* pXMLDom);
|
|
|
|
DWORD WINAPI EventCallBack(EVT_SUBSCRIBE_NOTIFY_ACTION, PVOID, EVT_HANDLE hEvent);
|
|
|
|
|
|
// Application entry point
|
|
int __cdecl wmain(int argc, __in_ecount(argc) WCHAR* argv[])
|
|
{
|
|
|
|
HRESULT hr = WpcuCOMInit();
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: Failed to initialize COM, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Obtain Compliance interface
|
|
IWindowsParentalControls* pWPC = NULL;
|
|
hr = CoCreateInstance(__uuidof(WindowsParentalControls), 0, CLSCTX_INPROC_SERVER,
|
|
__uuidof(IWindowsParentalControls), (LPVOID *)&pWPC);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Info: Parental Controls interface not detected.\n");
|
|
wprintf(L"Info: This is an error if on a supported SKU of Windows Vista.\n");
|
|
|
|
// Applications needing parental controls functionality on unsupported
|
|
// operating system versions will use alternative implementations
|
|
}
|
|
else
|
|
{
|
|
// Obtain WpcUserSettings interface for current user. Passing in a
|
|
// NULL SID pointer does this.
|
|
IWPCSettings* piWPCSettings = NULL;
|
|
hr = pWPC->GetUserSettings(NULL, &piWPCSettings);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Warning: Unable to obtain the Parental Controls user\n");
|
|
wprintf(L" settings interface. This is expected if the\n");
|
|
wprintf(L" current user is a Protected Administrator or\n");
|
|
wprintf(L" Built-In Administrator.\n");
|
|
}
|
|
else
|
|
{
|
|
// Have prerequisites for Parental Controls restricted account.
|
|
// Check if logging is required
|
|
BOOL fLoggingRequired = FALSE;
|
|
hr = piWPCSettings->IsLoggingRequired(&fLoggingRequired);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: IsLoggingRequired() failed, hr is %8x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
if (fLoggingRequired)
|
|
{
|
|
// Set internal state for application to log activity
|
|
|
|
// Optional: get restrictions state
|
|
DWORD dwRestrictions;
|
|
hr = piWPCSettings->GetRestrictions(&dwRestrictions);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: GetRestrictions() failed, hr is %8x\n",
|
|
hr);
|
|
}
|
|
else
|
|
{
|
|
if (dwRestrictions & WPCFLAG_WEB_FILTERED)
|
|
{
|
|
// Take any necessary actions for web filtering of HTTP
|
|
// traffic
|
|
wprintf(L"Info: HTTP filtering for user is on\n");
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Info: HTTP filtering for user is off\n");
|
|
}
|
|
if (dwRestrictions & WPCFLAG_HOURS_RESTRICTED)
|
|
{
|
|
// Take action to monitor logout warning events
|
|
wprintf(L"Info: Time restrictions for user are on - \
|
|
monitoring for logout events\n");
|
|
// Set up an Event Tracing for Windows subscription to
|
|
// the winlogon channel
|
|
HANDLE hSubWinlogon = EvtSubscribe(NULL,
|
|
NULL,
|
|
L"Microsoft-Windows-Winlogon/Operational",
|
|
L"Event/System[EventID=1001] and \
|
|
Event/System/Provider[@Name='Microsoft-Windows-Winlogon'] and \
|
|
Event/System/Provider[@Guid='{dbe9b383-7cf3-4331-91cc-a3cb16a3b538}'] \
|
|
and Event/EventData/Data[@Name='TimeLeft']",
|
|
NULL,
|
|
NULL,
|
|
EventCallBack,
|
|
EvtSubscribeToFutureEvents);
|
|
if (!hSubWinlogon)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
wprintf(L"Error: EvtSubscrible failed, hr is 0x08%x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Simple spin loop waiting for logout warning callback
|
|
wprintf(L"Hit any key to exit\n");
|
|
while (!_kbhit())
|
|
{
|
|
Sleep(10);
|
|
}
|
|
// Clean up event subscription
|
|
EvtClose(hSubWinlogon);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Info: Time restrictions for user are off\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
piWPCSettings->Release();
|
|
}
|
|
pWPC->Release();
|
|
}
|
|
}
|
|
WpcuCOMCleanup();
|
|
|
|
return (SUCCEEDED(hr)) ? 0 : 1;
|
|
}
|
|
|
|
// Runs in calling thread context
|
|
DWORD WINAPI EventCallBack(EVT_SUBSCRIBE_NOTIFY_ACTION, PVOID, EVT_HANDLE hEvent)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD cb = 0;
|
|
DWORD dwPropCount = 0;
|
|
|
|
// Call once to get the required size
|
|
EvtRender(NULL, hEvent, EvtRenderEventXml, cb, NULL, &cb, &dwPropCount);
|
|
|
|
// Allocate an array to the required size
|
|
WCHAR* pszBuff = (WCHAR*)(new BYTE[cb]);
|
|
if (!pszBuff)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
wprintf(L"Error: Out of memory rendering event\n");
|
|
}
|
|
else
|
|
{
|
|
if (!EvtRender(NULL, hEvent, EvtRenderEventXml, cb, pszBuff, &cb, &dwPropCount))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
wprintf(L"Error: EvtRender failed 0x%08x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Initialize COM
|
|
hr = CoInitialize(NULL);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: CoInitialize() failed, hr is 0x%08x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Create a DOM Document for the ETW event, then load and parse it
|
|
IXMLDOMDocument2* pXMLDocument;
|
|
|
|
hr = CoCreateInstance(CLSID_DOMDocument60, 0, CLSCTX_INPROC_SERVER,
|
|
IID_IXMLDOMDocument2, (LPVOID *) &pXMLDocument);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: CoCreate of DOMDOcument60 failed, hr is 0x%08x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
BSTR bstrXML = SysAllocString(pszBuff);
|
|
if (!bstrXML)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
wprintf(L"Error: insufficient memory for XML string allocation\n");
|
|
}
|
|
else
|
|
{
|
|
VARIANT_BOOL varfSuccess;
|
|
hr = pXMLDocument->loadXML(bstrXML, &varfSuccess);
|
|
if (FAILED(hr) || varfSuccess != VARIANT_TRUE)
|
|
{
|
|
wprintf(L"Error: loadXML() failed, hr is 0x%08x\n", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = EventParseXML(pXMLDocument);
|
|
|
|
}
|
|
SysFreeString(bstrXML);
|
|
}
|
|
pXMLDocument->Release();
|
|
}
|
|
CoUninitialize();
|
|
}
|
|
}
|
|
delete [] pszBuff;
|
|
}
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
// Runs in callback thread's context
|
|
HRESULT EventParseXML(IXMLDOMDocument2* pXMLDom)
|
|
{
|
|
HRESULT hr;
|
|
BSTR bstrNameSpace = SysAllocString(L"xmlns:event='http://schemas.microsoft.com/win/2004/08/events/event'");
|
|
BSTR bstrSelectionNamespaces = SysAllocString(L"SelectionNamespaces");
|
|
if (!bstrNameSpace || !bstrSelectionNamespaces)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
wprintf(L"Error: insufficient memory for namespace string allocations\n");
|
|
}
|
|
else
|
|
{
|
|
VARIANT var;
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = bstrNameSpace;
|
|
// Set the namespace
|
|
hr = pXMLDom->setProperty(bstrSelectionNamespaces, var);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrTimeLeftXPath = SysAllocString(L"event:Event/event:EventData/event:Data[@Name='TimeLeft']");
|
|
if (!bstrTimeLeftXPath)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
wprintf(L"Error: insufficient memory for time remaining string allocation\n");
|
|
}
|
|
else
|
|
{
|
|
IXMLDOMNode* piNode = NULL;
|
|
hr = pXMLDom->selectSingleNode(bstrTimeLeftXPath, &piNode);
|
|
if (hr == S_OK)
|
|
{
|
|
BSTR bstrTimeLeft;
|
|
hr = piNode->get_text(&bstrTimeLeft);
|
|
if (hr == S_OK)
|
|
{
|
|
wprintf(L"Info: Warning received - time remaining is %s minutes\n", bstrTimeLeft);
|
|
SysFreeString(bstrTimeLeft);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Error: pNode->get_text failed 0x%08x\n", hr);
|
|
}
|
|
piNode->Release();
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Error: pNode->selectSingleNode failed 0x%08x\n", hr);
|
|
}
|
|
SysFreeString(bstrTimeLeftXPath);
|
|
}
|
|
}
|
|
SysFreeString(bstrNameSpace);
|
|
SysFreeString(bstrSelectionNamespaces);
|
|
}
|
|
|
|
return hr;
|
|
} |