Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1812 lines
39 KiB

/*++
Copyright (c) 1999-2001 Microsoft Corporation
Module Name:
svcapis.cpp
Abstract:
This module implements routines to assist
CUSTOM Mode Value SSR Knowledge Base processing.
Author:
Vishnu Patankar (VishnuP) - Oct 2001
Environment:
User mode only.
Exported Functions:
svcapis.def
Revision History:
Created - Oct 2001
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <tchar.h>
#include <comdef.h>
#include <msxml2.h>
#include <winsvc.h>
#include <ntlsa.h>
#include <Lmshare.h>
#include <Lmapibuf.h>
#include <lmerr.h>
#include <winsta.h>
#include <winsock2.h>
#include <iphlpapi.h>
#include <iptypes.h>
#include <wbemcli.h>
#include <atlbase.h>
CComModule _Module;
#include <atlcom.h>
#include <regapi.h>
#include <initguid.h>
#include <ole2.h>
#include <mstask.h>
#include <msterr.h>
#include <wchar.h>
#include <dsrole.h>
typedef DWORD (WINAPI *PFGETDOMAININFO)(LPCWSTR, DSROLE_PRIMARY_DOMAIN_INFO_LEVEL, PBYTE *);
typedef VOID (WINAPI *PFDSFREE)( PVOID );
typedef BOOLEAN (WINAPI *PFREMOTEASSISTANCEENABLED)(VOID);
DWORD
SvcapispQueryServiceStartupType(
IN PWSTR pszMachineName,
IN PWSTR pszServiceName,
OUT BYTE *pbyStartupType
);
HRESULT
SvcapispGetRemoteOSVersionInfo(
IN PWSTR pszMachineName,
OUT OSVERSIONINFOEX *posVersionInfo
);
BOOL WINAPI DllMain(
IN HANDLE DllHandle,
IN ULONG ulReason,
IN LPVOID Reserved
)
/*++
Routine Description:
Typical DllMain functionality
Arguments:
DllHandle
ulReason
Reserved
Return:
TRUE if successfully initialized, FALSE otherwise
--*/
{
switch(ulReason) {
case DLL_PROCESS_ATTACH:
//
// Fall through to process first thread
//
case DLL_THREAD_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
STDAPI DllRegisterServer(
void
)
/*++
Routine Description:
Registers dll
Arguments:
Return:
S_OK if successful
--*/
{
return S_OK;
}
STDAPI
DllUnregisterServer(
void
)
/*++
Routine Description:
Unregisters dll
Arguments:
Return:
S_OK if successful
--*/
{
return S_OK;
}
DWORD
SvcapispQueryServiceStartupType(
IN PWSTR pszMachineName,
IN PWSTR pszServiceName,
OUT BYTE *pbyStartupType
)
/*++
Routine Description:
Routine called to check service startup type
Arguments:
pszMachineName - name of machine to evaluate function on
pszServiceName - name of service
pbyStartupType - startup type
Return:
Win32 error code
++*/
{
DWORD rc = ERROR_SUCCESS;
DWORD dwBytesNeeded = 0;
SC_HANDLE hService = NULL;
LPQUERY_SERVICE_CONFIG pServiceConfig=NULL;
SC_HANDLE hScm = NULL;
if (pbyStartupType == NULL || pszServiceName == NULL){
return ERROR_INVALID_PARAMETER;
}
*pbyStartupType = SERVICE_DISABLED;
hScm = OpenSCManager(
pszMachineName,
NULL,
GENERIC_READ);
if (hScm == NULL) {
rc = GetLastError();
goto ExitHandler;
}
hService = OpenService(
hScm,
pszServiceName,
SERVICE_QUERY_CONFIG |
READ_CONTROL
);
if ( hService == NULL ) {
rc = GetLastError();
goto ExitHandler;
}
if ( !QueryServiceConfig(
hService,
NULL,
0,
&dwBytesNeeded
)) {
if (ERROR_INSUFFICIENT_BUFFER != (rc = GetLastError())){
goto ExitHandler;
}
}
rc = ERROR_SUCCESS;
pServiceConfig = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_ZEROINIT, dwBytesNeeded);
if ( pServiceConfig == NULL ) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto ExitHandler;
}
if ( !QueryServiceConfig(
hService,
pServiceConfig,
dwBytesNeeded,
&dwBytesNeeded) )
{
rc = GetLastError();
goto ExitHandler;
}
*pbyStartupType = (BYTE)(pServiceConfig->dwStartType) ;
ExitHandler:
if (pServiceConfig) {
LocalFree(pServiceConfig);
}
if (hService) {
CloseServiceHandle(hService);
}
if (hScm) {
CloseServiceHandle(hScm);
}
return rc;
}
DWORD
SvcapisIsDomainMember(
IN PWSTR pszMachineName,
OUT BOOL *pbIsDomainMember
)
/*++
Routine Description:
Detects if machine is joined to a domain
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsDomainMember - pointer to boolean to fill
Return:
Win32 error code
--*/
{
NTSTATUS NtStatus;
PPOLICY_DNS_DOMAIN_INFO pDnsDomainInfo=NULL;
LSA_HANDLE LsaHandle=NULL;
LSA_OBJECT_ATTRIBUTES attributes;
SECURITY_QUALITY_OF_SERVICE service;
UNICODE_STRING uMachineName;
if (pbIsDomainMember == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsDomainMember = FALSE;
//
// Open the LSA policy first
//
memset( &attributes, 0, sizeof(attributes) );
attributes.Length = sizeof(attributes);
attributes.SecurityQualityOfService = &service;
service.Length = sizeof(service);
service.ImpersonationLevel= SecurityImpersonation;
service.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
service.EffectiveOnly = TRUE;
RtlInitUnicodeString(&uMachineName, pszMachineName);
NtStatus = LsaOpenPolicy(
pszMachineName ? &uMachineName: NULL,
&attributes,
POLICY_VIEW_LOCAL_INFORMATION,
&LsaHandle
);
if ( !NT_SUCCESS( NtStatus) ) {
goto ExitHandler;
}
//
// query primary domain DNS information
//
NtStatus = LsaQueryInformationPolicy(
LsaHandle,
PolicyDnsDomainInformation,
(PVOID *)&pDnsDomainInfo
);
if ( !NT_SUCCESS( NtStatus) || pDnsDomainInfo == NULL) {
goto ExitHandler;
}
if (pDnsDomainInfo->Sid){
*pbIsDomainMember = TRUE;
}
ExitHandler:
if (pDnsDomainInfo){
LsaFreeMemory(pDnsDomainInfo);
}
if (LsaHandle){
LsaClose( LsaHandle );
}
return(RtlNtStatusToDosError(NtStatus));
}
DWORD
SvcapisDoPrintSharesExist(
IN PWSTR pszMachineName,
OUT BOOL *pbPrintSharesExist
)
/*++
Routine Description:
Detects if print shares exist on machine
Arguments:
pszMachineName - name of machine to evaluate function on
pbPrintSharesExist - pointer to boolean to fill
Return:
Win32/NetApi error code
--*/
{
NET_API_STATUS NetStatus;
DWORD ParmError = 0;
DWORD Status = ERROR_SUCCESS;
LPBYTE Buffer = NULL;
DWORD EntriesRead = 0;
DWORD TotalEntries = 0;
LPSHARE_INFO_1 pShareInfo = NULL;
if (pbPrintSharesExist == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbPrintSharesExist = FALSE;
NetStatus = NetShareEnum(
pszMachineName,
1,
&Buffer,
MAX_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
NULL
);
if (NetStatus != NERR_Success ||
EntriesRead == 0 ||
Buffer == NULL)
{
goto ExitHandler;
}
pShareInfo = (LPSHARE_INFO_1)Buffer;
for (ULONG uIndex=0; uIndex < EntriesRead; uIndex++) {
if (pShareInfo[uIndex].shi1_type == STYPE_PRINTQ){
*pbPrintSharesExist = TRUE;
break;
}
}
ExitHandler:
if (Buffer) {
NetApiBufferFree(Buffer);
}
return NetStatus;
}
DWORD
SvcapisIsRemoteAssistanceEnabled(
IN PWSTR pszMachineName,
OUT BOOL *pbIsRemoteAssistanceEnabled
)
/*++
Routine Description:
Detects if remote assistance is enabled on machine
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsRemoteAssistanceEnabled - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
OSVERSIONINFOEX osVersionInfo;
if (pbIsRemoteAssistanceEnabled == NULL) {
return ERROR_INVALID_PARAMETER;
}
if (!GetVersionEx((LPOSVERSIONINFOW)&osVersionInfo)) {
rc = GetLastError();
return E_INVALIDARG;
}
if (osVersionInfo.dwMajorVersion == 5 &&
osVersionInfo.dwMajorVersion < 1) {
//
// remote assistance available on > w2k
//
return S_OK;
}
HRESULT hr = S_OK;
CComPtr <IWbemLocator> pWbemLocator = NULL;
CComPtr <IWbemServices> pWbemServices = NULL;
CComPtr <IWbemClassObject> pWbemTsObjectInstance = NULL;
CComPtr <IEnumWbemClassObject> pWbemEnumObject = NULL;
CComBSTR bstrMachineAndNamespace;
ULONG nReturned = 0;
bstrMachineAndNamespace = pszMachineName;
bstrMachineAndNamespace += L"\\root\\cimv2";
hr = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID *) &pWbemLocator
);
if (FAILED(hr) || pWbemLocator == NULL ) {
goto ExitHandler;
}
hr = pWbemLocator->ConnectServer(
bstrMachineAndNamespace,
NULL,
NULL,
NULL,
0L,
NULL,
NULL,
&pWbemServices
);
if (FAILED(hr) || pWbemServices == NULL ) {
goto ExitHandler;
}
hr = CoSetProxyBlanket(
pWbemServices,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr)) {
goto ExitHandler;
}
hr = pWbemServices->ExecQuery(CComBSTR(L"WQL"),
CComBSTR(L"SELECT * FROM Win32_TerminalServiceSetting"),
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL,
&pWbemEnumObject);
if (FAILED(hr) || pWbemEnumObject == NULL) {
goto ExitHandler;
}
hr = pWbemEnumObject->Next(WBEM_INFINITE, 1, &pWbemTsObjectInstance, &nReturned);
if (FAILED(hr) || pWbemTsObjectInstance == NULL) {
goto ExitHandler;
}
VARIANT vHelp;
VariantInit(&vHelp);
hr = pWbemTsObjectInstance->Get(CComBSTR(L"Help"),
0,
&vHelp,
NULL,
NULL);
if (FAILED(hr)) {
goto ExitHandler;
}
if (V_VT(&vHelp) == VT_NULL) {
goto ExitHandler;
}
ULONG uHelp = V_INT(&vHelp);
if (uHelp) {
*pbIsRemoteAssistanceEnabled = TRUE;
}
ExitHandler:
if (V_VT(&vHelp) != VT_NULL) {
VariantClear( &vHelp );
}
return hr;
}
DWORD
SvcapisIsWINSClient(
IN PWSTR pszMachineName,
OUT BOOL *pbIsWINSClient
)
/*++
Routine Description:
Detects if machine is a WINS client
Arguments:
pszMachineName - name of machine to evaluate function on (this API is not remotable)
pbIsWINSClient - pointer to boolean to fill
Return:
Win32 error code
--*/
{
ULONG ulSize = 0;
DWORD rc = ERROR_SUCCESS;
PIP_ADAPTER_INFO pAdapterInfo = NULL;
if (pbIsWINSClient == NULL) {
return ERROR_INVALID_PARAMETER;
}
if (pszMachineName != NULL) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
*pbIsWINSClient = FALSE;
rc = GetAdaptersInfo(
NULL,
&ulSize);
if (rc != ERROR_BUFFER_OVERFLOW &&
rc != ERROR_INSUFFICIENT_BUFFER ){
goto ExitHandler;
}
pAdapterInfo = (PIP_ADAPTER_INFO) LocalAlloc(LMEM_ZEROINIT, ulSize);
if (pAdapterInfo == NULL) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto ExitHandler;
}
rc = GetAdaptersInfo(
pAdapterInfo,
&ulSize);
if (rc != ERROR_SUCCESS){
goto ExitHandler;
}
for(PIP_ADAPTER_INFO pCurrAdapterInfo=pAdapterInfo;
pCurrAdapterInfo!=NULL;
pCurrAdapterInfo=pCurrAdapterInfo->Next){
if (pCurrAdapterInfo->PrimaryWinsServer.IpAddress.String != NULL ||
pCurrAdapterInfo->SecondaryWinsServer.IpAddress.String != NULL ){
*pbIsWINSClient = TRUE;
break;
}
}
ExitHandler:
if (pAdapterInfo) {
LocalFree(pAdapterInfo);
}
return rc;
}
DWORD
SvcapisAreTasksScheduled(
IN PWSTR pszMachineName,
OUT BOOL *pbAreTasksScheduled
)
/*++
Routine Description:
Detects if at least one task is scheduled
Arguments:
pszMachineName - name of machine to evaluate function on
pbAreTasksScheduled - pointer to boolean to fill
Return:
Win32 error code
--*/
{
HRESULT hr = S_OK;
CComPtr <ITaskScheduler> pITS = NULL;
CComPtr <IEnumWorkItems> pIEnum = NULL;
if (pbAreTasksScheduled == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbAreTasksScheduled = FALSE;
hr = CoInitialize(NULL);
if (FAILED(hr)){
return hr;
}
hr = CoCreateInstance(CLSID_CTaskScheduler,
NULL,
CLSCTX_INPROC_SERVER,
IID_ITaskScheduler,
(void **) &pITS);
if (FAILED(hr) || pITS == NULL ){
goto ExitHandler;
}
if (pszMachineName != NULL) {
hr = pITS->SetTargetComputer((LPCTSTR)pszMachineName);
if (SCHED_E_SERVICE_NOT_INSTALLED == hr) {
hr = S_OK;
goto ExitHandler;
}
if (FAILED(hr)) {
goto ExitHandler;
}
}
hr = pITS->Enum(&pIEnum);
if (FAILED(hr) || pIEnum == NULL){
goto ExitHandler;
}
LPWSTR *lpwszNames = NULL;
DWORD dwFetchedTasks = 0;
hr = pIEnum->Next(1,
&lpwszNames,
&dwFetchedTasks);
if (S_FALSE == hr){
hr = ERROR_SUCCESS;
}
if (FAILED(hr)){
goto ExitHandler;
}
if (dwFetchedTasks > 0 ){
*pbAreTasksScheduled = TRUE;
}
ExitHandler:
if (lpwszNames){
CoTaskMemFree(lpwszNames);
}
CoUninitialize();
return hr;
}
DWORD
SvcapisUPSAttached(
IN PWSTR pszMachineName,
OUT BOOL *pbIsUPSAttached
)
/*++
Routine Description:
Detects if UPS hardware is(was) attached
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsUPSAttached - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
HKEY hKeyHklm = HKEY_LOCAL_MACHINE;
HKEY hKey = NULL;
DWORD RegType;
DWORD cbData;
DWORD dwOptions = 0;
if (pbIsUPSAttached == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsUPSAttached = FALSE;
if (pszMachineName) {
rc = RegConnectRegistry(
pszMachineName,
HKEY_LOCAL_MACHINE,
&hKeyHklm
);
}
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
rc = RegOpenKeyEx(hKeyHklm,
L"SYSTEM\\CurrentControlSet\\Services\\UPS",
0,
KEY_READ | KEY_QUERY_VALUE,
&hKey
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
cbData = sizeof(DWORD);
rc = RegQueryValueEx (
hKey,
L"Options",
NULL,
&RegType,
(LPBYTE)&dwOptions,
&cbData
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
if (dwOptions & 0x1) {
*pbIsUPSAttached = TRUE;
}
ExitHandler:
if (hKeyHklm != HKEY_LOCAL_MACHINE) {
RegCloseKey(hKeyHklm);
}
if (hKey) {
RegCloseKey(hKey);
}
if (rc == ERROR_FILE_NOT_FOUND ||
rc == ERROR_PATH_NOT_FOUND) {
rc = ERROR_SUCCESS;
}
return rc;
}
DWORD
SvcapisAutoUpdateEnabled(
IN PWSTR pszMachineName,
OUT BOOL *pbAutoUpdateIsEnabled
)
/*++
Routine Description:
Detects if Auto Update is enabled
Arguments:
pszMachineName - name of machine to evaluate function on
pbAutoUpdateIsEnabled - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
HKEY hKeyHklm = HKEY_LOCAL_MACHINE;
HKEY hKey = NULL;
DWORD RegType;
DWORD cbData;
DWORD dwOptions = 0;
if (pbAutoUpdateIsEnabled == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbAutoUpdateIsEnabled = FALSE;
if (pszMachineName) {
rc = RegConnectRegistry(
pszMachineName,
HKEY_LOCAL_MACHINE,
&hKeyHklm
);
}
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WindowsUpdate\\Auto Update",
0,
KEY_READ | KEY_QUERY_VALUE,
&hKey
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
cbData = sizeof(DWORD);
rc = RegQueryValueEx (
hKey,
L"AUOptions",
NULL,
&RegType,
(LPBYTE)&dwOptions,
&cbData
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
if (!(dwOptions & 1)) {
*pbAutoUpdateIsEnabled = TRUE;
}
ExitHandler:
if (hKeyHklm != HKEY_LOCAL_MACHINE) {
RegCloseKey(hKeyHklm);
}
if (hKey) {
RegCloseKey(hKey);
}
if (rc == ERROR_FILE_NOT_FOUND ||
rc == ERROR_PATH_NOT_FOUND) {
rc = ERROR_SUCCESS;
}
return rc;
}
DWORD
ServicesFoundThatAreNotinKB(
OUT BOOL *pbIsServiceSatisfiable
)
/*++
Routine Description:
Detects if service is enabled on machine
Arguments:
pbIsServiceSatisfiable - pointer to boolean to fill
Return:
Win32 error code
--*/
{
if (pbIsServiceSatisfiable == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsServiceSatisfiable = TRUE;
return ERROR_SUCCESS;
}
DWORD
SvcapisIsPerfCollectionScheduled(
IN PWSTR pszMachineName,
OUT BOOL *pbIsPerfCollectionScheduled
)
/*++
Routine Description:
Detects if perf data is being collected on the machine
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsPerfCollectionScheduled - pointer to boolean to fill
Return:
Win32 error code
--*/
{
BYTE byStartupType;
DWORD rc;
if (pbIsPerfCollectionScheduled == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsPerfCollectionScheduled = FALSE;
rc = SvcapispQueryServiceStartupType(pszMachineName,
L"SysmonLog",
&byStartupType
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
*pbIsPerfCollectionScheduled = (byStartupType == SERVICE_AUTO_START ? TRUE : FALSE);
ExitHandler:
return rc;
}
DWORD
SvcapisIsSBS(
IN PWSTR pszMachineName,
OUT BOOL *pbIsSmallBusinessServer
)
/*++
Routine Description:
Routine called to check if SBS is installed
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsSmallBusinessServer - booolean to fill
Return:
Win32 error code
++*/
{
if (pbIsSmallBusinessServer == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsSmallBusinessServer = FALSE;
DWORD rc = ERROR_SUCCESS;
HRESULT hr = S_OK;
OSVERSIONINFOEX osVersionInfo;
osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
if (NULL == pszMachineName) {
if (!GetVersionEx((LPOSVERSIONINFOW)&osVersionInfo)) {
rc = GetLastError();
goto ExitHandler;
}
}
else {
hr = SvcapispGetRemoteOSVersionInfo(
pszMachineName,
&osVersionInfo);
if (FAILED(hr)) {
rc = ERROR_PRODUCT_VERSION;
goto ExitHandler;
}
}
if (osVersionInfo.dwMajorVersion == VER_SUITE_SMALLBUSINESS ||
osVersionInfo.dwMajorVersion == VER_SUITE_SMALLBUSINESS_RESTRICTED) {
*pbIsSmallBusinessServer = TRUE;
}
ExitHandler:
return rc;
}
DWORD
SvcapisIsDC(
IN PWSTR pszMachineName,
OUT BOOL *pbIsDC
)
/*++
Routine Description:
Detects if machine is a DC
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsDC - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
if (pbIsDC == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsDC = FALSE;
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole=NULL;
HINSTANCE hDsRoleDll = LoadLibrary(TEXT("netapi32.dll"));
if ( hDsRoleDll == NULL) {
rc = ERROR_MOD_NOT_FOUND;
goto ExitHandler;
}
PVOID pfDsRole;
pfDsRole = (PVOID)GetProcAddress(
hDsRoleDll,
"DsRoleGetPrimaryDomainInformation");
if ( pfDsRole == NULL ){
rc = ERROR_PROC_NOT_FOUND;
goto ExitHandler;
}
rc = (*((PFGETDOMAININFO)pfDsRole))(
pszMachineName,
DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pDsRole
);
if (rc != ERROR_SUCCESS || NULL == pDsRole) {
goto ExitHandler;
}
if ( pDsRole->MachineRole == DsRole_RolePrimaryDomainController ||
pDsRole->MachineRole == DsRole_RoleBackupDomainController ) {
*pbIsDC = TRUE;
}
pfDsRole = (PVOID)GetProcAddress(
hDsRoleDll,
"DsRoleFreeMemory");
if ( pfDsRole ) {
(*((PFDSFREE)pfDsRole))( pDsRole );
}
ExitHandler:
if (hDsRoleDll) {
FreeLibrary(hDsRoleDll);
}
return(rc);
}
DWORD
SvcapisIsAppModeTS(
IN PWSTR pszMachineName,
OUT BOOL *pbIsAppModeTS
)
/*++
Routine Description:
Detects if TS is in app mode
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsAppModeTS - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
HKEY hKeyHklm = HKEY_LOCAL_MACHINE;
HKEY hKey = NULL;
DWORD RegType;
DWORD cbData;
DWORD dwOptions = 0;
OSVERSIONINFOEX osVersionInfo;
HRESULT hr = S_OK;
if (pbIsAppModeTS == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsAppModeTS = FALSE;
//
// SSR paradigm for preprocessing remoteability
//
// if local, try the traditional approach
// if remote, dig-into the registry etc. (maybe less reliable)
//
if (pszMachineName == NULL) {
//
// local
//
if (!GetVersionEx((LPOSVERSIONINFOW)&osVersionInfo)) {
rc = GetLastError();
goto ExitHandler;
}
} else {
//
// remote
//
hr = SvcapispGetRemoteOSVersionInfo(
pszMachineName,
&osVersionInfo);
if (FAILED(hr)) {
rc = ERROR_PRODUCT_VERSION;
goto ExitHandler;
}
}
if (osVersionInfo.wSuiteMask & VER_SUITE_TERMINAL &&
osVersionInfo.wSuiteMask & VER_SUITE_SINGLEUSERTS) {
*pbIsAppModeTS = TRUE;
}
/*
rc = RegConnectRegistry(
pszMachineName,
HKEY_LOCAL_MACHINE,
&hKeyHklm
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
rc = RegOpenKeyEx(hKeyHklm,
L"System\\CurrentControlSet\\Control\\Terminal Server",
0,
KEY_READ | KEY_QUERY_VALUE,
&hKey
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
cbData = sizeof(DWORD);
rc = RegQueryValueEx (
hKey,
L"TSAppCompat",
NULL,
&RegType,
(LPBYTE)&dwOptions,
&cbData
);
if (rc != ERROR_SUCCESS) {
goto ExitHandler;
}
if (dwOptions & 0x1) {
*pbIsAppModeTS = TRUE;
}
}
*/
ExitHandler:
if (hKeyHklm != HKEY_LOCAL_MACHINE) {
RegCloseKey(hKeyHklm);
}
if (hKey) {
RegCloseKey(hKey);
}
if (rc == ERROR_FILE_NOT_FOUND ||
rc == ERROR_PATH_NOT_FOUND) {
rc = ERROR_SUCCESS;
}
return rc;
}
DWORD
SvcapisDFSSharesExist(
IN PWSTR pszMachineName,
OUT BOOL *pbDFSSharesExist
)
/*++
Routine Description:
Detects if DFS shares exist on machine
Arguments:
pszMachineName - name of machine to evaluate function on
pbDFSSharesExist - pointer to boolean to fill
Return:
Win32/NetApi error code
--*/
{
NET_API_STATUS NetStatus;
DWORD ParmError = 0;
DWORD Status = ERROR_SUCCESS;
LPBYTE Buffer = NULL;
DWORD EntriesRead = 0;
DWORD TotalEntries = 0;
LPSHARE_INFO_1 pShareInfo = NULL;
if (pbDFSSharesExist == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbDFSSharesExist = FALSE;
NetStatus = NetShareEnum(
pszMachineName,
1,
&Buffer,
MAX_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
NULL
);
if (NetStatus != NERR_Success ||
EntriesRead == 0 ||
Buffer == NULL) {
goto ExitHandler;
}
pShareInfo = (LPSHARE_INFO_1)Buffer;
PSHARE_INFO_1005 pBufShareInfo = NULL;
DWORD shi1005_flags;
for (ULONG uIndex=0; uIndex < EntriesRead; uIndex++) {
if (pShareInfo[uIndex].shi1_type == STYPE_DISKTREE) {
NetStatus = NetShareGetInfo(
pszMachineName,
pShareInfo[uIndex].shi1_netname,
1005,
(LPBYTE *) &pBufShareInfo
);
if (NetStatus != NERR_Success ||
pBufShareInfo == NULL) {
goto ExitHandler;
}
shi1005_flags = pBufShareInfo->shi1005_flags;
NetApiBufferFree(pBufShareInfo);
pBufShareInfo = NULL;
if (SHI1005_FLAGS_DFS & shi1005_flags) {
*pbDFSSharesExist = TRUE;
break;
}
}
}
ExitHandler:
if (Buffer) {
NetApiBufferFree(Buffer);
}
return NetStatus;
}
DWORD
SvcapisIsUsingDHCP(
IN PWSTR pszMachineName,
OUT BOOL *pbIsUsingDHCP
)
/*++
Routine Description:
Detects if any adapter on this machine is using DHCP
in its TCP/IP stack
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsUsingDHCP - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
DWORD dwOutBufLen = 0;
PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL;
if (pbIsUsingDHCP == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsUsingDHCP = FALSE;
rc = GetAdaptersAddresses(
AF_UNSPEC,
0,
NULL,
NULL,
&dwOutBufLen
);
if (ERROR_SUCCESS == rc ||
(ERROR_SUCCESS != rc && ERROR_BUFFER_OVERFLOW != rc)) {
goto ExitHandler;
}
pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) LocalAlloc(LMEM_ZEROINIT, dwOutBufLen);
if ( NULL == pAdapterAddresses) {
rc = ERROR_NOT_ENOUGH_MEMORY;
goto ExitHandler;
}
rc = GetAdaptersAddresses(
AF_UNSPEC,
0,
NULL,
pAdapterAddresses,
&dwOutBufLen
);
if (ERROR_SUCCESS != rc) {
goto ExitHandler;
}
for (PIP_ADAPTER_ADDRESSES pCurrentAddress = pAdapterAddresses;
pCurrentAddress != NULL;
pCurrentAddress = pCurrentAddress->Next) {
if (pCurrentAddress->Flags & IP_ADAPTER_DHCP_ENABLED) {
*pbIsUsingDHCP = TRUE;
goto ExitHandler;
}
}
ExitHandler:
if (pAdapterAddresses) {
LocalFree(pAdapterAddresses);
}
return(rc);
}
DWORD
SvcapisIsUsingDDNS(
IN PWSTR pszMachineName,
OUT BOOL *pbIsUsingDDNS
)
/*++
Routine Description:
Detects if any adapter on this machine is using DDNS (DNS is always enabled)
in its TCP/IP stack
Arguments:
pszMachineName - name of machine to evaluate function on
pbIsUsingDHCP - pointer to boolean to fill
Return:
Win32 error code
--*/
{
DWORD rc = ERROR_SUCCESS;
DWORD dwOutBufLen = 0;
PIP_ADAPTER_ADDRESSES pAdapterAddresses;
if (pbIsUsingDDNS == NULL) {
return ERROR_INVALID_PARAMETER;
}
*pbIsUsingDDNS = FALSE;
rc = GetAdaptersAddresses(
AF_UNSPEC,
0,
NULL,
NULL,
&dwOutBufLen
);
if (ERROR_SUCCESS == rc ||
(ERROR_SUCCESS != rc && ERROR_BUFFER_OVERFLOW != rc)) {
goto ExitHandler;
}
pAdapterAddresses = (PIP_ADAPTER_ADDRESSES) LocalAlloc(LMEM_ZEROINIT, dwOutBufLen);
if ( NULL == pAdapterAddresses) {
goto ExitHandler;
}
rc = GetAdaptersAddresses(
AF_UNSPEC,
0,
NULL,
pAdapterAddresses,
&dwOutBufLen
);
if (ERROR_SUCCESS != rc) {
goto ExitHandler;
}
for (PIP_ADAPTER_ADDRESSES pCurrentAddress = pAdapterAddresses;
pCurrentAddress != NULL;
pCurrentAddress = pCurrentAddress->Next) {
if (pCurrentAddress->Flags & IP_ADAPTER_DDNS_ENABLED) {
*pbIsUsingDDNS = TRUE;
goto ExitHandler;
}
}
ExitHandler:
if (pAdapterAddresses) {
LocalFree(pAdapterAddresses);
}
return(rc);
}
HRESULT
SvcapispGetRemoteOSVersionInfo(
IN PWSTR pszMachineName,
OUT OSVERSIONINFOEX *posVersionInfo
)
/*++
Routine Description:
Routine called to get version info from remote machine via WMI
Arguments:
pszMachineName - remote machine name
posVersionInfo - os version info to fill via WMI queries
Return:
HRESULT error code
++*/
{
HRESULT hr = S_OK;
CComPtr <IWbemLocator> pWbemLocator = NULL;
CComPtr <IWbemServices> pWbemServices = NULL;
CComPtr <IWbemClassObject> pWbemOsObjectInstance = NULL;
CComPtr <IEnumWbemClassObject> pWbemEnumObject = NULL;
CComBSTR bstrMachineAndNamespace;
ULONG nReturned = 0;
bstrMachineAndNamespace = pszMachineName;
bstrMachineAndNamespace += L"\\root\\cimv2";
hr = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID *) &pWbemLocator
);
if (FAILED(hr) || pWbemLocator == NULL ) {
goto ExitHandler;
}
hr = pWbemLocator->ConnectServer(
bstrMachineAndNamespace,
NULL,
NULL,
NULL,
0L,
NULL,
NULL,
&pWbemServices
);
if (FAILED(hr) || pWbemServices == NULL ) {
goto ExitHandler;
}
hr = CoSetProxyBlanket(
pWbemServices,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
EOAC_NONE
);
if (FAILED(hr)) {
goto ExitHandler;
}
hr = pWbemServices->ExecQuery(CComBSTR(L"WQL"),
CComBSTR(L"SELECT * FROM Win32_OperatingSystem"),
WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
NULL,
&pWbemEnumObject);
if (FAILED(hr) || pWbemEnumObject == NULL) {
goto ExitHandler;
}
hr = pWbemEnumObject->Next(WBEM_INFINITE, 1, &pWbemOsObjectInstance, &nReturned);
if (FAILED(hr) || pWbemOsObjectInstance == NULL) {
goto ExitHandler;
}
VARIANT vVersion;
VariantInit(&vVersion);
hr = pWbemOsObjectInstance->Get(CComBSTR(L"Version"),
0,
&vVersion,
NULL,
NULL);
if (FAILED(hr)) {
goto ExitHandler;
}
if (V_VT(&vVersion) == VT_NULL) {
goto ExitHandler;
}
//
// extract the version information into DWORDs since
// the return type of this property is BSTR variant
// of the form "5.1.2195"
//
BSTR bstrVersion = V_BSTR(&vVersion);
WCHAR szVersion[5];
szVersion[0] = L'\0';
PWSTR pszDot = wcsstr(bstrVersion, L".");
if (NULL == pszDot) {
hr = E_INVALIDARG;
goto ExitHandler;
}
wcsncpy(szVersion, bstrVersion, 1);
posVersionInfo->dwMajorVersion = (DWORD)_wtoi(szVersion);
wcsncpy(szVersion, pszDot+1, 1);
posVersionInfo->dwMinorVersion = (DWORD)_wtoi(szVersion);
ExitHandler:
if (V_VT(&vVersion) != VT_NULL) {
VariantClear( &vVersion );
}
return hr;
}