526 lines
21 KiB
C++
526 lines
21 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 API sample
|
|
|
|
PURPOSE: Demonstrates usage of COM Compliance API used by
|
|
applications not needing to manage settings via
|
|
WMI.
|
|
|
|
FUNCTIONS:
|
|
|
|
wmain() - implements overall command line application
|
|
WpcsCmplApiUserIsLoggingRequired() - updates out param flag
|
|
specifying whether activity logging policy is on for a user
|
|
WpcsCmplApiUserSettingsChangeTime() - sets out param time of
|
|
last change in policy settings for a user
|
|
WpcsCmplApiUserGetRestrictions() - sets bitfields in out
|
|
param DWORD of active restriction silos for a user
|
|
WpcsCmplApiGamesIsBlocked() - sets out param DWORD reason
|
|
code for any blocking of game specified by AppID GUID for
|
|
a user
|
|
WpcsCmplApiWebGetSettings() - sets bitfields in out param
|
|
DWORD of active web restriction policies for a user
|
|
WpcsCmplApiWebRequestUrlOverride() - specifying a URL and
|
|
optionally a set of associated subURLs, this method fires
|
|
an administrator override request dialog
|
|
CmdLineParse() - helper handling command line input
|
|
|
|
|
|
COMMENTS:
|
|
None of the Compliance API functions change state of policy
|
|
settings for a user
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
#include "ComplianceAPI.h"
|
|
|
|
|
|
HRESULT WpcsCmplApiUserIsLoggingRequired(IWindowsParentalControls* pWPC, PCWSTR pcszSID,
|
|
BOOL* pfLoggingRequired);
|
|
|
|
HRESULT WpcsCmplApiUserSettingsChangeTime(IWindowsParentalControls* pWPC, PCWSTR pcszSID,
|
|
SYSTEMTIME* pLastTime);
|
|
|
|
HRESULT WpcsCmplApiUserGetRestrictions(IWindowsParentalControls* pWPC, PCWSTR pcszSID,
|
|
DWORD* pdwRestrictions);
|
|
|
|
HRESULT WpcsCmplApiGamesIsBlocked(IWindowsParentalControls* pWPC, PCWSTR pcszSID,
|
|
GUID guidAppID, DWORD* pdwBlockedReasons);
|
|
|
|
HRESULT WpcsCmplApiWebGetSettings(IWindowsParentalControls* pWPC, PCWSTR pcszSID,
|
|
DWORD* pdwWebSettings);
|
|
|
|
HRESULT WpcsCmplApiWebRequestUrlOverride(IWindowsParentalControls* pWPC,
|
|
HWND hAppWindow, PCWSTR pcszSID, PCWSTR pcszUrl,
|
|
DWORD dwNumSubUrl, PCWSTR* ppcszSubUrl,
|
|
BOOL* pfChanged);
|
|
|
|
|
|
HRESULT CmdLineParse(int argc, WCHAR* argv[], PARSERESULT* pParseResult);
|
|
|
|
void Usage (PCWSTR pcszProgramName);
|
|
|
|
// call as Usage(argv[0])
|
|
void Usage (PCWSTR pcszProgramName)
|
|
{
|
|
wprintf(L"Usage: %s [<username>] <function> [additional args]\n", pcszProgramName);
|
|
wprintf(L" Note: If user name is not specified, report is for current user\n\n");
|
|
wprintf(L" Where functions, and arguments are as follows:\n\n");
|
|
wprintf(L" user \t\t\t\tShow settings for user\n\n");
|
|
wprintf(L"isgameblocked <app ID GUID> \tShow if and why blocked for \n \
|
|
\t\t\tspecified game\n\n");
|
|
wprintf(L"requrloverride <url> [<subURL1> <subURL2> ..]\n");
|
|
wprintf(L"\t\t\t\tRequest URL override, \n\t\t\t\tshowing changed status response\n\n");
|
|
}
|
|
|
|
|
|
// Application entry point
|
|
int __cdecl wmain(int argc, __in_ecount(argc) WCHAR* argv[])
|
|
{
|
|
// Declare command line parsing result structure
|
|
PARSERESULT stParseResult;
|
|
|
|
// Parse operational mode and arguments from command line.
|
|
// Function is responsible for printing its own errors.
|
|
HRESULT hr = CmdLineParse(argc, argv, &stParseResult);
|
|
if (hr == E_INVALIDARG)
|
|
{
|
|
// Printf usage and bypass further initialization
|
|
Usage(argv[0]);
|
|
}
|
|
else if (SUCCEEDED(hr))
|
|
{
|
|
hr = WpcuCOMInit();
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: Failed to initialize COM, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Obtain Compliance Interface
|
|
IWindowsParentalControls* piWPC;
|
|
hr = CoCreateInstance(__uuidof(WindowsParentalControls), 0, CLSCTX_INPROC_SERVER,
|
|
__uuidof(IWindowsParentalControls), (LPVOID *)&piWPC);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Info: Parental Controls interface not detected.\n");
|
|
wprintf(L"Info: This is an error if on a supported SKU.\n");
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
// Perform mode-specific operations
|
|
switch (stParseResult.eOperation)
|
|
{
|
|
case OPERATION_USER:
|
|
{
|
|
BOOL fLoggingRequired;
|
|
SYSTEMTIME LastTime;
|
|
DWORD dwUserRestrictions;
|
|
DWORD dwWebSettings;
|
|
hr = WpcsCmplApiUserIsLoggingRequired(piWPC, stParseResult.pszSID,
|
|
&fLoggingRequired);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsCmplApiUserIsLoggingRequired() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Print results
|
|
hr = WpcsCmplApiUserSettingsChangeTime(piWPC, stParseResult.pszSID,
|
|
&LastTime);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsCmplApiUserSettingsChangeTime() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = WpcsCmplApiUserGetRestrictions(piWPC, stParseResult.pszSID,
|
|
&dwUserRestrictions);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsCmplApiUserGetRestrictions() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
hr = WpcsCmplApiWebGetSettings(piWPC, stParseResult.pszSID, &dwWebSettings);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsmplApiWebGetSettings() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Info: User IsLoggingRequired is %s\n",
|
|
(fLoggingRequired == TRUE) ? L"TRUE" : L"FALSE");
|
|
|
|
// Display SYSTEMTIME info
|
|
wprintf(L"Info: Last settings change time is %4d/%02d/%02d %02d:%02d:%02d.%03d UTC\n",
|
|
LastTime.wYear, LastTime.wMonth, LastTime.wDay,
|
|
LastTime.wHour, LastTime.wMinute, LastTime.wSecond,
|
|
LastTime.wMilliseconds);
|
|
|
|
// Print web settings
|
|
wprintf(L"Info: User web settings:");
|
|
if (dwWebSettings == WPCFLAG_WEB_SETTING_NOTBLOCKED)
|
|
{
|
|
wprintf(L" No blocking\n");
|
|
}
|
|
else
|
|
{
|
|
// Leave room for future expansion
|
|
wprintf(L"\t Download blocking is %s\n",
|
|
(dwWebSettings & WPCFLAG_WEB_SETTING_DOWNLOADSBLOCKED) ?
|
|
L"on" : L"off");
|
|
}
|
|
|
|
// Print user restrictions fields
|
|
wprintf(L"Info: User restrictions:");
|
|
if (dwUserRestrictions == WPCFLAG_NO_RESTRICTION)
|
|
{
|
|
wprintf(L"\t None\n");
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"\n\t Logging required is %s\n",
|
|
(dwUserRestrictions & WPCFLAG_LOGGING_REQUIRED) ?
|
|
L"on" : L"off");
|
|
wprintf(L"\t Web restrictions are %s\n",
|
|
(dwUserRestrictions & WPCFLAG_WEB_FILTERED) ?
|
|
L"on" : L"off");
|
|
wprintf(L"\t Hours restrictions are %s\n",
|
|
(dwUserRestrictions & WPCFLAG_HOURS_RESTRICTED) ?
|
|
L"on" : L"off");
|
|
wprintf(L"\t Games restrictions are %s\n",
|
|
(dwUserRestrictions & WPCFLAG_HOURS_RESTRICTED) ?
|
|
L"on" : L"off");
|
|
wprintf(L"\t Application restrictions are %s\n",
|
|
(dwUserRestrictions & WPCFLAG_APPS_RESTRICTED) ?
|
|
L"on" : L"off");
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case OPERATION_ISGAMEBLOCKED:
|
|
{
|
|
DWORD dwBlockedReasons = 0;
|
|
hr = WpcsCmplApiGamesIsBlocked(piWPC, stParseResult.pszSID,
|
|
stParseResult.guidAppID, &dwBlockedReasons);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsCmplApiGamesIsBlocked() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
// Print games IsBlocked reasons
|
|
wprintf(L"Info: Games IsBlocked reason:\n");
|
|
if (dwBlockedReasons == WPCFLAG_ISBLOCKED_NOTBLOCKED)
|
|
{
|
|
wprintf(L"\tNot blocked\n");
|
|
}
|
|
else if (dwBlockedReasons == WPCFLAG_ISBLOCKED_INTERNALERROR)
|
|
{
|
|
wprintf(L"tInternal error\n");
|
|
}
|
|
else if (dwBlockedReasons & WPCFLAG_ISBLOCKED_EXPLICITBLOCK)
|
|
{
|
|
wprintf(L"\tExplicit block\n");
|
|
}
|
|
else if (dwBlockedReasons & WPCFLAG_ISBLOCKED_RATINGBLOCKED)
|
|
{
|
|
wprintf(L"\tRating block\n");
|
|
}
|
|
else if (dwBlockedReasons & WPCFLAG_ISBLOCKED_DESCRIPTORBLOCKED)
|
|
{
|
|
wprintf(L"\tRating descriptor block\n");
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"\tUnknown reason\n");
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case OPERATION_REQUESTURLOVERRIDE:
|
|
{
|
|
BOOL fChanged = FALSE;
|
|
// Pass in handle of application main window. For purposes of this console-based
|
|
// sample, NULL is used
|
|
hr = WpcsCmplApiWebRequestUrlOverride(piWPC,
|
|
NULL,
|
|
stParseResult.pszSID,
|
|
stParseResult.stRequestUrlOverride.pszUrl,
|
|
stParseResult.stRequestUrlOverride.dwNumSubUrl,
|
|
stParseResult.stRequestUrlOverride.ppcszSubUrl,
|
|
&fChanged);
|
|
if (FAILED(hr))
|
|
{
|
|
wprintf(L"Error: WpcsCmplApiWebRequestUrlOverride() failed, hr is %8x.\n", hr);
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"Info: User web request URL override changed is %s.\n",
|
|
fChanged ? L"TRUE" : L"FALSE");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
piWPC->Release();
|
|
}
|
|
WpcuCOMCleanup();
|
|
}
|
|
}
|
|
|
|
|
|
if (stParseResult.pszSID)
|
|
{
|
|
LocalFree(stParseResult.pszSID);
|
|
}
|
|
|
|
return (SUCCEEDED(hr)) ? 0 : 1;
|
|
}
|
|
|
|
|
|
HRESULT WpcsCmplApiUserIsLoggingRequired(IWindowsParentalControls* piWPC, PCWSTR pcszSID,
|
|
BOOL* pfLoggingRequired)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pfLoggingRequired)
|
|
{
|
|
// Obtain WpcUserSettings interface
|
|
IWPCSettings* piWPCSettings = NULL;
|
|
hr = piWPC->GetUserSettings(pcszSID, &piWPCSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCSettings->IsLoggingRequired(pfLoggingRequired);
|
|
piWPCSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WpcsCmplApiUserSettingsChangeTime(IWindowsParentalControls* piWPC, PCWSTR pcszSID,
|
|
SYSTEMTIME* pLastTime)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pLastTime)
|
|
{
|
|
// Obtain WpcUserSettings interface
|
|
IWPCSettings* piWPCSettings = NULL;
|
|
hr = piWPC->GetUserSettings(pcszSID, &piWPCSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCSettings->GetLastSettingsChangeTime(pLastTime);
|
|
piWPCSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WpcsCmplApiUserGetRestrictions(IWindowsParentalControls* piWPC, PCWSTR pcszSID,
|
|
DWORD* pdwRestrictions)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pdwRestrictions)
|
|
{
|
|
// Obtain WpcUserSettings interface
|
|
IWPCSettings* piWPCSettings = NULL;
|
|
hr = piWPC->GetUserSettings(pcszSID, &piWPCSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCSettings->GetRestrictions(pdwRestrictions);
|
|
piWPCSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WpcsCmplApiGamesIsBlocked(IWindowsParentalControls* piWPC, PCWSTR pcszSID,
|
|
GUID guidAppID, DWORD* pdwBlockedReasons)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pdwBlockedReasons)
|
|
{
|
|
// Obtain WpcGamesSettings interface
|
|
IWPCGamesSettings* piWPCGamesSettings = NULL;
|
|
hr = piWPC->GetGamesSettings(pcszSID, &piWPCGamesSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCGamesSettings->IsBlocked(guidAppID, pdwBlockedReasons);
|
|
piWPCGamesSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WpcsCmplApiWebGetSettings(IWindowsParentalControls* piWPC, PCWSTR pcszSID,
|
|
DWORD* pdwWebSettings)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pdwWebSettings)
|
|
{
|
|
// Obtain WpcWebSettings interface
|
|
IWPCWebSettings* piWPCWebSettings = NULL;
|
|
hr = piWPC->GetWebSettings(pcszSID, &piWPCWebSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCWebSettings->GetSettings(pdwWebSettings);
|
|
piWPCWebSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT WpcsCmplApiWebRequestUrlOverride(IWindowsParentalControls* piWPC,
|
|
HWND hAppWindow, PCWSTR pcszSID, PCWSTR pcszUrl,
|
|
DWORD dwNumSubUrl, PCWSTR* ppcszSubUrl,
|
|
BOOL* pfChanged)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// Do basic parameter validation. Allow NULL pcszSID to signal method to
|
|
// use current user SID
|
|
if (piWPC && pcszUrl && (!dwNumSubUrl || ppcszSubUrl) && pfChanged)
|
|
{
|
|
// Obtain WpcWebSettings interface
|
|
IWPCWebSettings* piWPCWebSettings = NULL;
|
|
hr = piWPC->GetWebSettings(pcszSID, &piWPCWebSettings);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Call method
|
|
hr = piWPCWebSettings->RequestURLOverride(hAppWindow, pcszUrl, dwNumSubUrl,
|
|
ppcszSubUrl, pfChanged);
|
|
piWPCWebSettings->Release();
|
|
}
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
//
|
|
// Helper functions
|
|
//
|
|
|
|
|
|
// Parse the command line
|
|
HRESULT CmdLineParse(int argc, WCHAR* argv[], PARSERESULT* pParseResult)
|
|
{
|
|
// Default is invalid until args are validated
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
// Do basic parameter validation
|
|
if (pParseResult && argc >= ARGS_MIN)
|
|
{
|
|
ZeroMemory(pParseResult, sizeof(PARSERESULT));
|
|
BOOL fOperation = FALSE;
|
|
PCWSTR pcszUserName = NULL;
|
|
int i;
|
|
|
|
// Determine operational mode and check prerequisites
|
|
for (i = 1; !fOperation && i < 3 && i < argc; ++i)
|
|
{
|
|
if (_wcsicmp(argv[i], L"user") == 0)
|
|
{
|
|
pParseResult->eOperation = OPERATION_USER;
|
|
fOperation = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[i], L"requrloverride") == 0)
|
|
{
|
|
pParseResult->eOperation = OPERATION_REQUESTURLOVERRIDE;
|
|
fOperation = TRUE;
|
|
}
|
|
else if (_wcsicmp(argv[i], L"isgameblocked") == 0)
|
|
{
|
|
pParseResult->eOperation = OPERATION_ISGAMEBLOCKED;
|
|
fOperation = TRUE;
|
|
}
|
|
if (fOperation && (i == 2))
|
|
{
|
|
//there is a username
|
|
pcszUserName = argv[1];
|
|
}
|
|
}
|
|
|
|
if (fOperation)
|
|
{
|
|
hr = S_OK;
|
|
switch (pParseResult->eOperation)
|
|
{
|
|
case OPERATION_ISGAMEBLOCKED:
|
|
if (i == argc)
|
|
{
|
|
// No app ID
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = CLSIDFromString(argv[i], &(pParseResult->guidAppID));
|
|
}
|
|
break;
|
|
|
|
case OPERATION_REQUESTURLOVERRIDE:
|
|
if (i == argc)
|
|
{
|
|
// No URL
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
pParseResult->stRequestUrlOverride.dwNumSubUrl = argc - i -1;
|
|
pParseResult->stRequestUrlOverride.pszUrl = argv[i];
|
|
if (pParseResult->stRequestUrlOverride.dwNumSubUrl > 0)
|
|
{
|
|
pParseResult->stRequestUrlOverride.ppcszSubUrl = (PCWSTR*)(&(argv[i+1]));
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && pcszUserName)
|
|
{
|
|
// Function allocates local memory for pszSID buffer
|
|
hr = WpcuSidStringFromUserName(pcszUserName, &pParseResult->pszSID);
|
|
}
|
|
}
|
|
return (hr);
|
|
}
|
|
|