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.
 
 
 
 
 
 

4720 lines
120 KiB

#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <ole2.h>
#include <stdio.h>
#include <dsrole.h>
#include <scesetup.h>
#include <iads.h>
#include <adshlp.h>
#include <winldap.h>
#include <oaidl.h>
#include <Adshlp.h>
#include <adserr.h>
#include <Sddl.h>
#include <Aclapi.h>
#include <initguid.h>
#include <Gpedit.h>
#include <atlbase.h>
#include <Ntdsapi.h>
#include <secedit.h>
#include "resource.h"
#include <Lmshare.h>
#include <lm.h>
#include <oleauto.h>
#include <adsopenflags.h>
#include <Dsgetdc.h>
#include <sclgntfy.h>
#include <Wincrypt.h>
#include <strsafe.h>
#define PCOMMON_IMPL
#include "pcommon.h"
#include <locale.h>
#include <winnlsp.h>
#if DBG
#define dbgprint wprintf
#else
#define dbgprint
#endif // DBG
#define DIFF(d) ((ULONG)(d))
#define TARGET_ARG L"/target:"
#define TARGET_ARG_LENGTH (sizeof(TARGET_ARG) - sizeof(WCHAR))
#define TARGET_ARG_COUNT (TARGET_ARG_LENGTH/sizeof(WCHAR))
#define TARGET_ARG_DOMAIN L"domain"
#define TARGET_ARG_DC L"dc"
#define TARGET_ARG_BOTH L"both"
#define TARGET_ARG_IGNORE_SCHEMA L"/ignoreschema"
#define STRING_SD L"D:P(A;CIOI;GRGX;;;AU)(A;CIOI;GRGX;;;SO)(A;CIOI;GA;;;BA)(A;CIOI;GA;;;SY)(A;CIOI;GA;;;CO)(A;CIOI;GRGWGXSD;;;PA)"
#define DDP_USEREXT L"[{3060E8D0-7020-11D2-842D-00C04FA372D4}{3060E8CE-7020-11D2-842D-00C04FA372D4}]"
#define DDP_MACHEXT L"[{35378EAC-683F-11D2-A89A-00C04FBBCFA2}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}][{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}][{B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A}{53D6AB1B-2488-11D1-A28C-00C04FB94F17}]"
#define DDC_MACHEXT L"[{827D319E-6EAC-11D2-A4EA-00C04F79F83A}{803E14A0-B4FB-11D0-A0D0-00A0C90F574B}]"
#define DDP_DS_SD L"O:DAG:DAD:P(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA)(A;CIIO;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO)(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY)(A;CI;RPLCLORC;;;AU)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU)(A;CI;LCRPLORC;;;ED)"
#define DDCP_DS_SD L"O:DAG:DAD:P(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;DA)(A;CI;RPWPCCDCLCLOLORCWOWDSDDTSW;;;EA)(A;CIIO;RPWPCCDCLCLOLORCWOWDSDDTSW;;;CO)(A;CI;RPWPCCDCLCLORCWOWDSDDTSW;;;SY)(A;CI;RPLCLORC;;;AU)(OA;CI;CR;edacfd8f-ffb3-11d1-b41d-00a0c968f939;;AU)(A;CI;LCRPLORC;;;ED)"
#define SCHEMA_VERSION 30
#define MAX_EFS_KEY 255
#define MAX_VERSION_LENGTH 10
#define FILE_GPTINI L"\\gpt.ini"
#define FILE_GPTTMPLINF L"\\MACHINE\\Microsoft\\Windows NT\\SecEdit\\GptTmpl.inf"
// Default Domain Policy need not be localized and can be hard-coded
#define DDP L"Default Domain Policy"
#define DEFAULT_DC_POLICY_NAME L"Default Domain Controllers Policy"
extern "C" {
typedef HRESULT (STDAPICALLTYPE *DLLREGISTERSERVER)(void);
}
typedef enum policyTypeTag{
DEFAULT_DOMAIN_POLICY, DEFAULT_DOMAIN_CONTROLLER_POLICY
} POLICYTYPE;
#define DOMAIN_GUID L"{31B2F340-016D-11D2-945F-00C04FB984F9}"
#define DC_GUID L"{6AC1786C-016F-11D2-945F-00C04FB984F9}"
struct GLOBALS {
WCHAR* Banner1;
WCHAR* Banner2;
WCHAR* ErrorNotAdmin;
WCHAR* ErrorNoAD;
WCHAR* ErrorContinue;
WCHAR* ErrorBadSysVol;
WCHAR* DispDDP;
WCHAR* DispDDCP;
WCHAR* DispBoth;
WCHAR* ToolFailed;
WCHAR* CreateEFS;
WCHAR* DirCreate;
WCHAR* DirDelete;
WCHAR* InvalidEFS;
WCHAR* DSDelete;
WCHAR* DSAttrib;
WCHAR* DSLinkDO;
WCHAR* DSLinkDDP;
WCHAR* DirRead;
WCHAR* DirWrite;
WCHAR* DDPSuccess;
WCHAR* DDCPSuccess;
WCHAR* WarnURA;
WCHAR* IgnSchSwitch;
WCHAR* GenDSErr;
WCHAR* DSCreate;
WCHAR* EFSAccessDenied;
WCHAR* WrongSchema;
WCHAR* TargetSwitch;
WCHAR* CharYes;
WCHAR* RestoreIgnoredGPOFail;
WCHAR SysVolPath[MAX_PATH];
WCHAR *DomainNamingContext;
LONG lDDCPVersionNo;
LONG lDDPVersionNo;
LPGROUPPOLICYOBJECT pGPO;
SECURITY_DESCRIPTOR *pDDPSecDesc;
SECURITY_DESCRIPTOR *pDDCPSecDesc;
DSROLE_PRIMARY_DOMAIN_INFO_BASIC * pDomainInfo;
BOOL hasEFSInfo;
BOOL bIgnoreSchema;
enum {
RESTORE_DOMAIN = 1 ,
RESTORE_DC = 2,
RESTORE_BOTH = 3
} RestoreType;
HRESULT Init();
GLOBALS();
~GLOBALS();
};
class CGPOFile
{
public:
CGPOFile( WCHAR* wszGPOPath );
~CGPOFile();
DWORD
Backup();
DWORD
Restore();
WCHAR*
GetPath();
private:
WCHAR* _wszFullPath;
BYTE* _pFileData;
DWORD _cbFileSize;
};
class CIgnoredGPO
{
public:
CIgnoredGPO(
WCHAR* wszGPOId,
WCHAR* wszGPOName );
~CIgnoredGPO();
DWORD
Backup();
DWORD
Restore();
private:
DWORD
InitializeErrorText(
WCHAR* wszGPOName );
CGPOFile* _pGptIniFile;
CGPOFile* _pGptTmplFile;
WCHAR* _wszError;
};
GLOBALS _global;
GLOBALS * global = &_global;
HRESULT
IsDomainController (
OUT BOOL *pDomainController
);
HRESULT
_LoadString (
OUT WCHAR*& pwsz,
IN UINT nID
);
void
PrintError(
DWORD pwzError
);
void
PrintError(
WCHAR *lpStr1,
WCHAR *lpStr2
);
void
DisplayError(
WCHAR *pwzError
);
extern "C" DWORD SetSysvolSecurityFromDSSecurity(
LPTSTR lpFileSysPath,
SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR pSD
);
BOOL
FilePresent(WCHAR *szFileName)
{
FILE *fPtr = NULL;
fPtr = _wfopen(szFileName, L"r");
if (NULL == fPtr)
{
return FALSE;
}
fclose(fPtr);
return TRUE;
}
HRESULT GetDomainFQDN(LPWSTR szDomainDNSName,
LPWSTR *pszDomainFQDN)
/*++
Routine Description:
This function gets the domain FQDN given the dns domain name
Arguments:
[in] szDomainDNSName - DNS Domain Name
[out] pszDomainFQDN - Domain FQDN
Memory need to be freed for pszDomainFQDN using LocalFree.
Return Value:
S_OK on success. Corresponding error codes on failures
--*/
{
HRESULT hr;
LPWSTR pDomainNames[1];
LPWSTR szDNSDomain = NULL;
DWORD dwErr;
DS_NAME_RESULT *pDSNameResult = NULL;
LPWSTR szDomainFQDN = NULL;
ULONG ulSize;
//
// ALlocate a buffer to add in a '/' at the end
// szDomainDNSName + '/' + '\0';
//
ulSize = lstrlen(szDomainDNSName) + 1 + 1;
szDNSDomain = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*ulSize);
if (!szDNSDomain)
{
hr = E_OUTOFMEMORY;
goto end;
}
hr = StringCchPrintf(szDNSDomain, ulSize, L"%s/", szDomainDNSName);
if (FAILED(hr))
{
goto end;
}
pDomainNames[0] = szDNSDomain;
//
// Call DsCrackNames to convert
//
dwErr = DsCrackNames(NULL, DS_NAME_FLAG_SYNTACTICAL_ONLY,
DS_CANONICAL_NAME, DS_FQDN_1779_NAME,
1, pDomainNames, &pDSNameResult);
if ( (dwErr != DS_NAME_NO_ERROR) || (!pDSNameResult) || (pDSNameResult->cItems != 1))
{
if ( (!pDSNameResult) || (pDSNameResult->cItems != 1) )
{
//
// We don't expect this to happen at all
//
dbgprint(L"GetDomainDN: DsCrackNames failed with error 0x%x", E_UNEXPECTED);
hr = E_UNEXPECTED;
goto end;
}
else
{
dbgprint(L"GetDomainDN: DsCrackNames failed with error %d", dwErr);
hr = HRESULT_FROM_WIN32(dwErr);
goto end;
}
}
if (pDSNameResult->rItems[0].status != DS_NAME_NO_ERROR)
{
dwErr = pDSNameResult->rItems[0].status;
dbgprint(L"GetDomainDN: DsCrackNames failed with error %d", dwErr);
hr = HRESULT_FROM_WIN32(dwErr);
goto end;
}
//
// We have a valid FQDN. allocate and copy
// pDSNameResult->rItems[0].pName + '\0'
//
ulSize = lstrlen(pDSNameResult->rItems[0].pName) + 1;
szDomainFQDN = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR) * ulSize);
if (!szDomainFQDN)
{
DsFreeNameResult(pDSNameResult);
hr = E_OUTOFMEMORY;
goto end;
}
hr = StringCchCopy(szDomainFQDN, ulSize, pDSNameResult->rItems[0].pName);
if (FAILED(hr))
{
DsFreeNameResult(pDSNameResult);
goto end;
}
dbgprint(L"GetDomainDN: Domain FQDN of domain %s = %s\n", szDomainDNSName, szDomainFQDN);
DsFreeNameResult(pDSNameResult);
*pszDomainFQDN = szDomainFQDN;
hr = S_OK;
end:
if (NULL != szDNSDomain)
{
LocalFree(szDNSDomain);
}
return hr;
}
HRESULT
SetObjectSecurityDescriptor(
LPWSTR szObjectPath,
SE_OBJECT_TYPE seObjectType,
SECURITY_DESCRIPTOR *pSecurityDescriptor)
/*++
Routine Description:
This ia thin wrapper around GetNamedSecurityInfo
returns it (in self-relative format). A new buffer is LocalAlloced for this
security descriptor. The caller is responsible for LocalFreeing it.
Arguments:
[in] szObjectPath - Path to the object.
[in] seObjectType - Type of the object
[in] pSecurityDescriptor - Receives a pointer to the security descriptor.
Return Value:
S_OK on success.
On failure the corresponding error code will be returned.
Any API calls that are made in this function might fail and these error
codes will be returned directly.
--*/
{
HRESULT hr = S_OK;
DWORD dwErr;
PACL pDacl = NULL;
BOOL bDaclPresent;
BOOL bDaclDefaulted;
PACL pSacl = NULL;
BOOL bSaclPresent;
BOOL bSaclDefaulted;
PSID pSidGroup;
BOOL bGroupDefaulted;
PSID pSidOwner;
BOOL bOwnerDefaulted;
if (!GetSecurityDescriptorDacl(pSecurityDescriptor, &bDaclPresent, &pDacl, &bDaclDefaulted))
{
hr = HRESULT_FROM_WIN32(GetLastError());
dbgprint(L"GetSecurityDescriptorDacl failed with 0x%x.", hr);
return hr;
}
if (!GetSecurityDescriptorSacl(pSecurityDescriptor, &bSaclPresent, &pSacl, &bSaclDefaulted))
{
hr = HRESULT_FROM_WIN32(GetLastError());
dbgprint(L"GetSecurityDescriptorSacl failed with 0x%x.", hr);
return hr;
}
if (!GetSecurityDescriptorGroup(pSecurityDescriptor, &pSidGroup, &bGroupDefaulted))
{
hr = HRESULT_FROM_WIN32(GetLastError());
dbgprint( L"GetSecurityDescriptorGroup failed with 0x%x.", hr);
return hr;
}
if (!GetSecurityDescriptorOwner(pSecurityDescriptor, &pSidOwner, &bOwnerDefaulted))
{
hr = HRESULT_FROM_WIN32(GetLastError());
dbgprint(L"GetSecurityDescriptorOwner failed with 0x%x.", hr);
return hr;
}
dwErr = SetNamedSecurityInfo(szObjectPath,
seObjectType,
DACL_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION,
pSidOwner,
pSidGroup,
pDacl,
pSacl
);
if (dwErr != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwErr);
dbgprint(L"SetNamedSecurityInfo for %s failed with 0x%x.", szObjectPath, hr);
return hr;
}
return S_OK;
}
HRESULT SetDSSecurityDescriptor (
POLICYTYPE pType
)
{
WCHAR *szDsObjectName = NULL;
ULONG uSDSize;
BOOL bError;
HRESULT hr;
SECURITY_DESCRIPTOR *pSD;
ULONG ulSize;
ulSize = lstrlen(L"LDAP://CN=%s,CN=Policies,CN=System,%s") + lstrlen(DOMAIN_GUID) + lstrlen(global->DomainNamingContext) + 1 ;
szDsObjectName = (WCHAR *) LocalAlloc( LPTR, sizeof(WCHAR) * ulSize);
if( NULL == szDsObjectName )
{
return E_OUTOFMEMORY;
}
if (DEFAULT_DOMAIN_POLICY == pType)
{
hr = StringCchPrintf( szDsObjectName,
ulSize,
L"CN=%s,CN=Policies,CN=System,%s",
DOMAIN_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
// Convert the string to a security descriptor
bError = ConvertStringSecurityDescriptorToSecurityDescriptor (DDP_DS_SD ,
SDDL_REVISION_1,
(PSECURITY_DESCRIPTOR *) &pSD,
&uSDSize) ;
global->pDDPSecDesc = pSD;
}
else
{
hr = StringCchPrintf( szDsObjectName,
ulSize,
L"CN=%s,CN=Policies,CN=System,%s",
DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
// Convert the string to a security descriptor
bError = ConvertStringSecurityDescriptorToSecurityDescriptor (DDCP_DS_SD ,
SDDL_REVISION_1,
(PSECURITY_DESCRIPTOR *) &pSD,
&uSDSize) ;
global->pDDCPSecDesc = pSD;
}
if ( bError != TRUE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
dbgprint(L"ConvertStringSecurityDescriptorToSecurityDescriptor failed 0x%x", hr);
PrintError(szDsObjectName,global->DSAttrib);
goto end;
}
// then set it to corresponding value
hr = SetObjectSecurityDescriptor(szDsObjectName,
SE_DS_OBJECT,
pSD);
if (FAILED(hr))
{
dbgprint(L"SetDSSecurityDescriptor: SetObjectSecurityDescriptor failed with %x\n", hr);
PrintError(szDsObjectName,global->DSAttrib);
PrintError(hr);
goto end;
}
hr = S_OK;
end:
if (NULL != szDsObjectName)
{
LocalFree(szDsObjectName);
}
return hr;
}
//
// Gets the version number present in the file / DS
//
HRESULT GetVersionNumber (
POLICYTYPE polType)
{
WCHAR *szFileOrDSName = NULL;
ULONG uLength;
WCHAR szBuffer[MAX_VERSION_LENGTH];
LONG lVersionNo = 0;
WORD wUserVersionNo;
WORD wMachineVersionNo;
DWORD dwRetVal;
DWORD dwError;
HRESULT hr;
CComPtr<IADs> pADs;
CComVariant Var;
CComBSTR VersionNumber(L"VersionNumber");
if ( ! VersionNumber )
{
return E_OUTOFMEMORY;
}
//
// Length of the allocated buffer is more than required, since it is the sum of the file path and ds path
//
uLength = lstrlen(global->SysVolPath)+ lstrlen(global->pDomainInfo->DomainNameDns) + lstrlen(DOMAIN_GUID) + lstrlen(L"\\policies") + lstrlen(FILE_GPTINI) +
lstrlen( L"LDAP://CN=%s,CN=Policies,CN=System,%s") + lstrlen( DOMAIN_GUID) + lstrlen(global->DomainNamingContext) + 1;
szFileOrDSName = ( WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * uLength);
if(NULL == szFileOrDSName)
{
hr = E_OUTOFMEMORY;
goto end;
}
hr = StringCchPrintf(szFileOrDSName,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTINI,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
( DEFAULT_DOMAIN_POLICY == polType ) ? DOMAIN_GUID : DC_GUID);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
//
// Get the version number from the sysvol directory
//
dwRetVal = GetPrivateProfileString ( L"General",
L"Version",
L"-1",
szBuffer,
MAX_VERSION_LENGTH,
szFileOrDSName);
if( dwRetVal > 0 )
{
//
// The casewhere szBuffer has a negetive number will be
// taken care of inside the for loop
//
for(int i = 0; szBuffer[i] != L'\0' && i < MAX_VERSION_LENGTH ; i++)
{
if (!isdigit(szBuffer[i]))
{
lVersionNo = 0;
break;
}
lVersionNo *= 10;
lVersionNo += szBuffer[i] - L'0';
}
if ( MAX_VERSION_LENGTH == i )
{
lVersionNo = 0;
}
}
else
{
dwError = GetLastError();
if ( ERROR_ACCESS_DENIED == dwError )
{
dbgprint(L"GetVersonNumber:GetPrivateProfileString failed with error %x\n, dwError");
PrintError(szFileOrDSName, global->DirRead);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
else if (dwError != ERROR_FILE_NOT_FOUND && dwError != ERROR_PATH_NOT_FOUND)
{
//
// If dwError is either ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND,
// lVersionNo will have its initialized value
//
dbgprint(L"GetVersonNumber:GetPrivateProfileString failed with error %x\n, dwError");
PrintError(dwError);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
}
wUserVersionNo = HIWORD(lVersionNo);
wMachineVersionNo = LOWORD(lVersionNo);
//
// Get the version number from the DS
//
hr = StringCchPrintf( szFileOrDSName,
uLength,
L"LDAP://CN=%s,CN=Policies,CN=System,%s",
( DEFAULT_DOMAIN_POLICY == polType ) ? DOMAIN_GUID : DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(szFileOrDSName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADs, (void**)&pADs);
if ( SUCCEEDED(hr) )
{
hr = pADs->GetInfo();
if ( SUCCEEDED(hr) )
{
Var.Clear();
hr = pADs->Get(VersionNumber, &Var);
if(SUCCEEDED(hr))
{
lVersionNo = Var.lVal;
}
else
{
lVersionNo = 0;
}
}
else
{
dbgprint(L"AdminToolsOpenObject Failed with error %x\n", hr);
PrintError(hr);
goto end;
}
}
else if ( hr != (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT)))
{
dbgprint(L"AdminToolsOpenObject failed %x on %s\n", hr, szFileOrDSName);
PrintError(szFileOrDSName, global->GenDSErr);
goto end;
}
else
{
lVersionNo = 0;
}
wUserVersionNo = max( wUserVersionNo, HIWORD(lVersionNo)) + 1;
wMachineVersionNo = max( wMachineVersionNo, LOWORD(lVersionNo)) + 1;
lVersionNo = (((LONG) wUserVersionNo) << 16) + wMachineVersionNo;
if (DEFAULT_DOMAIN_POLICY == polType)
{
global->lDDPVersionNo = lVersionNo;
}
else
{
global->lDDCPVersionNo = lVersionNo;
}
hr = S_OK;
end:
LocalFree(szFileOrDSName);
return hr;
}
//
// Gives a pointer to beginnening of the last the substring that
// does not contain a '/'
//
LPWSTR CheckSlash (LPWSTR lpDir)
{
LPWSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if ( lpDir != lpEnd && *(lpEnd - 1) != L'\\')
{
*lpEnd = L'\\';
lpEnd++;
*lpEnd = L'\0';
}
return lpEnd;
}
//********************************************************************************************
//
// RegDelnodeExceptEFS()
//
// Deletes a registry key and all it's subkeys / values except EFS Certificates
//
// hKeyRoot - Root key
// bEFSFound - Indicates whether EFS keys were found
//
//*********************************************************************************************
HRESULT
RegDelnodeExceptEFS(
IN HKEY hKeyRoot,
OUT BOOL & bEFSFound
)
{
LONG Status;
HKEY hSubKey;
DWORD MaxCchSubKey = 0;
DWORD EnumIndex;
PWCHAR pwszEnumKeyName;
WCHAR wszSubKey[72]; // enough to hold a path consisting of the following parts
PWCHAR apwszSubKeyNames[] = { L"Software", L"Policies", L"Microsoft", L"SystemCertificates", L"EFS" };
bEFSFound = FALSE;
wszSubKey[0] = 0;
for (DWORD SubKeyIndex = 0; SubKeyIndex < sizeof(apwszSubKeyNames)/sizeof(apwszSubKeyNames[0]); SubKeyIndex++ )
{
hSubKey = 0;
pwszEnumKeyName = 0;
Status = RegOpenKeyEx( hKeyRoot, wszSubKey, 0, KEY_ALL_ACCESS, &hSubKey );
if ( ERROR_SUCCESS == Status )
{
Status = RegQueryInfoKey( hSubKey, 0, 0, 0, 0, &MaxCchSubKey, 0, 0, 0, 0, 0, 0 );
MaxCchSubKey++;
}
if ( ERROR_SUCCESS == Status )
{
pwszEnumKeyName = new WCHAR[MaxCchSubKey];
if ( ! pwszEnumKeyName )
Status = ERROR_OUTOFMEMORY;
}
for (EnumIndex = 0; ERROR_SUCCESS == Status;)
{
DWORD CchSubKey;
CchSubKey = MaxCchSubKey;
Status = RegEnumKeyEx(
hSubKey,
EnumIndex,
pwszEnumKeyName,
&CchSubKey,
NULL,
NULL,
NULL,
NULL );
if ( ERROR_SUCCESS == Status )
{
if ( CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, apwszSubKeyNames[SubKeyIndex], -1, pwszEnumKeyName, -1) == CSTR_EQUAL )
{
EnumIndex++;
continue;
}
Status = RegDelnode( hSubKey, pwszEnumKeyName );
}
}
if ( hSubKey )
RegCloseKey( hSubKey );
if ( pwszEnumKeyName )
delete [] pwszEnumKeyName;
if ( ERROR_NO_MORE_ITEMS == Status )
Status = ERROR_SUCCESS;
if ( Status != ERROR_SUCCESS )
break;
StringCbCat( wszSubKey, sizeof(wszSubKey), apwszSubKeyNames[SubKeyIndex] );
StringCbCat( wszSubKey, sizeof(wszSubKey), L"\\" );
}
if ( Status != ERROR_SUCCESS )
return HRESULT_FROM_WIN32(Status);
if ( EnumIndex != 0 )
{
bEFSFound = TRUE;
}
else
{
RegDelnode( hKeyRoot, L"Software" );
}
return S_OK;
}
HRESULT SetPolicySecurityInfo (LPTSTR lpFileSysPath)
{
PACL pDacl = NULL;
BOOL bAclPresent, bDefaulted;
DWORD dwError = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
ULONG uSize;
SECURITY_INFORMATION si = (DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION);
if ( !ConvertStringSecurityDescriptorToSecurityDescriptorW(STRING_SD,SDDL_REVISION_1, &pSD, &uSize) )
{
dwError = GetLastError();
dbgprint(L"SetPolicySecurityInfo: ConvertStringSecurityDescriptorToSecurityDescriptor failed with %d", dwError);
goto end;
}
//
// Get the DACL
//
if (!GetSecurityDescriptorDacl (pSD, &bAclPresent, &pDacl, &bDefaulted))
{
dwError = GetLastError();
dbgprint(L"SetPolicySecurityInfo: GetSecurityDescriptorDacl failed with %d", dwError);
goto end;
}
//
// Set the access control information for the file system portion
//
dwError = SetNamedSecurityInfo(lpFileSysPath, SE_FILE_OBJECT, si, NULL, NULL, pDacl, NULL);
end:
if (pSD != NULL)
{
LocalFree(pSD);
}
if( dwError != ERROR_SUCCESS)
{
PrintError(dwError);
}
return HRESULT_FROM_WIN32(dwError);
}
HRESULT DeleteContainerFromDS(WCHAR *szContainerName, IADsContainer *pADsContainer)
{
HRESULT hr;
CComPtr<IEnumVARIANT> pEnumVariant;
CComPtr<IUnknown> pUnknown;
VARIANT var;
CComPtr<IDispatch> pDisp;
CComPtr<IADsDeleteOps> pADsDeleteOps;
ULONG uNoEleReturned;
hr = pADsContainer->get__NewEnum( &pUnknown);
if (FAILED(hr))
{
dbgprint(L"dbg: get_NewEnum failed with error %x on %s", hr, szContainerName);
goto end;
}
hr = pUnknown->QueryInterface(IID_IEnumVARIANT, (void **) &pEnumVariant);
if (FAILED(hr))
{
dbgprint(L"dbg: QueryInterface failed with error %x in function DeleteContainerFromDS", hr);
goto end;
}
while(TRUE)
{
hr = pEnumVariant->Next( 1, &var, &uNoEleReturned);
if ( FAILED(hr) )
{
dbgprint(L"dbg: Call to Next failed with error %x", hr);
goto end;
}
else if (0 == uNoEleReturned)
{
break;
}
pDisp = V_DISPATCH( &var );
hr = pDisp->QueryInterface(IID_IADsDeleteOps, (void **) &pADsDeleteOps);
if (FAILED(hr))
{
dbgprint(L"dbg: Could not fetch pointer to interface IID_IADsDeleteOps in function DeleteContainerFromDS- error %x", hr);
goto end;
}
hr = pADsDeleteOps->DeleteObject(0);
if (FAILED(hr))
{
dbgprint(L"dbg: DeleteObject failed with error %x in function DeleteContainerFromDS", hr);
goto end;
}
}
end:
return hr;
}
HRESULT ResetContainerFromDS (
WCHAR *szContainerName,
IADs *pADsParent
)
{
HRESULT hr;
CComPtr<IADsContainer> pADsContainer;
hr = AdminToolsOpenObject(szContainerName, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADsContainer, (void**)&pADsContainer);
if ( FAILED(hr) )
{
CComBSTR GroupPolicyContainerName(L"groupPolicyContainer");
if ( ! GroupPolicyContainerName )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
if (E_ADS_BAD_PATHNAME == hr)
{
CComPtr<IDispatch> pDisp;
CComPtr<IADs> pADs;
hr = pADsParent->QueryInterface(IID_IADsContainer, (void **) &pADsContainer);
if (FAILED(hr))
{
dbgprint(L"dbg: Create failed with %x on parent %s\n", hr, szContainerName);
PrintError(szContainerName, global->DSCreate);
goto end;
}
CComBSTR ContainerNameString(szContainerName);
if ( ! ContainerNameString )
{
hr = E_OUTOFMEMORY;
dbgprint(L"dbg: Create failed %x on %s\n", hr, szContainerName);
PrintError(szContainerName, global->DSCreate);
goto end;
}
hr = pADsContainer->Create(GroupPolicyContainerName, ContainerNameString, &pDisp);
if (FAILED(hr))
{
dbgprint(L"dbg: Create failed %x on %s\n", hr, szContainerName);
PrintError(szContainerName, global->DSCreate);
goto end;
}
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: Query Interface failed %x for Creating IID_IADS\n", hr);
PrintError(szContainerName, global->DSCreate);
goto end;
}
hr = pADs->SetInfo();
if (FAILED(hr))
{
dbgprint(L"SetInfo returned error %x on %s", hr, szContainerName);
PrintError(szContainerName, global->DSCreate);
goto end;
}
}
else
{
dbgprint(L"AdminToolsOpenObject returned error %x on %s", hr, szContainerName);
PrintError(szContainerName, global->GenDSErr);
goto end;
}
}
else
{
hr = DeleteContainerFromDS(szContainerName, pADsContainer);
if( FAILED(hr))
{
dbgprint(L"DeleteContainerFromDS returned error %x on %s", hr, szContainerName);
PrintError(szContainerName, global->DSDelete);
goto end;
}
}
end:
return hr;
}
HRESULT
IsDomainController(
OUT BOOL *pDomainController
)
{
DWORD dwError;
dwError = DsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&global->pDomainInfo );
if (dwError != ERROR_SUCCESS)
{
dbgprint(L"IsDomainController: DsRoleGetPrimaryDomainInformationfailed");
PrintError(dwError);
return( HRESULT_FROM_WIN32(dwError) );
}
if ((global->pDomainInfo->MachineRole == DsRole_RoleBackupDomainController ||
global->pDomainInfo->MachineRole == DsRole_RolePrimaryDomainController) &&
(global->pDomainInfo->Flags & DSROLE_PRIMARY_DS_RUNNING) != 0)
{
*pDomainController = TRUE;
}
else
{
*pDomainController = FALSE;
}
return S_OK;
} // IsDomainController
HRESULT
LookupMembership (
WCHAR *Name,
OUT BOOL *pAdmin
)
{
#define MAX_SID_LENGTH (1024*4)
DWORD dwError;
BOOL bError;
PSID pSid = NULL;
// Initialize the out parameter
*pAdmin = FALSE;
// Get the sid of the domain admin / enterprise admin group.
bError = ConvertStringSidToSid(Name, &pSid);
if (FALSE == bError || NULL == pSid)
{
dwError = GetLastError();
dbgprint(L"LookupMembership: ConvertStringSidToSid failed");
goto end;
}
// check to see if that SID is in our current SD (aka user)
bError = CheckTokenMembership(NULL, pSid, pAdmin);
if (bError == FALSE)
{
dwError = GetLastError();
goto end;
}
dwError = ERROR_SUCCESS;
end:
if (pSid != NULL)
{
LocalFree(pSid);
}
if( dwError != ERROR_SUCCESS)
{
PrintError(dwError);
}
return HRESULT_FROM_WIN32(dwError) ;
} // LookupMembership()
HRESULT
IsAdmin (
OUT BOOL *pAdmin
)
{
HRESULT hr;
WCHAR Name[8];
// Initialize the out parameter
*pAdmin = FALSE;
hr = StringCbCopy(&Name[0], sizeof(Name), L"DA");
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = LookupMembership(Name, pAdmin);
if ( FAILED(hr) )
{
dbgprint(L"IsAdmin: CheckAccountName returned error %x", hr);
PrintError(hr);
goto end;
}
if(TRUE == *pAdmin)
{
goto end;
}
hr = StringCbCopy(&Name[0], sizeof(Name), L"EA");
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = LookupMembership(Name, pAdmin);
if ( FAILED(hr) )
{
// We are not printing error in this case, since this function
// may not be supported in pre wistler servers
dbgprint(L"IsAdmin: CheckAccountName returned error %x", hr);
goto end;
}
end:
return hr;
} // IsAdmin
HRESULT
GLOBALS::Init()
{
HRESULT hr;
hr = _LoadString(this->ErrorBadSysVol, IDS_BADSYSVOL);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->Banner1, IDS_BANNER1);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->Banner2, IDS_BANNER2);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->ErrorContinue, IDS_CONTINUE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->ErrorNoAD, IDS_NOAD);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->ErrorNotAdmin, IDS_NOTADMIN);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DispDDP, IDS_DISPDDP);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DispDDCP, IDS_DISPDDCP);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DispBoth, IDS_DISPBOTH);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->ToolFailed, IDS_TOOLFAILED);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->CreateEFS, IDS_CREATEEFS);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DirCreate, IDS_DIRCREATE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DirDelete, IDS_DIRDELETE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->InvalidEFS, IDS_INVALIDEFS);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DSDelete, IDS_DSDELETE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DSAttrib, IDS_DSATTRIB);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DSLinkDO, IDS_DSLINKDO);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DSLinkDDP, IDS_DSLINKDDP);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DirRead, IDS_DIRREAD);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DirWrite, IDS_DIRWRITE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DDPSuccess, IDS_DDPSUCCESS);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DDCPSuccess, IDS_DDCPSUCCESS);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->WarnURA, IDS_WARNURA);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->IgnSchSwitch, IDS_IGNSCHSWITCH);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->GenDSErr, IDS_GENDSERR);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->DSCreate, IDS_DSCREATE);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->EFSAccessDenied, IDS_EFSACCESSDENIED);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->WrongSchema, IDS_WRONGSCHEMA);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->TargetSwitch, IDS_TARGETSWITCH);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->CharYes, IDS_CHARYES);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = _LoadString(this->RestoreIgnoredGPOFail, IDS_RESTORE_FAIL);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
// all done
hr = S_OK;
end:
if ( FAILED(hr) )
{
PrintError(hr);
}
return hr;
} // GLOBALS::Init
GLOBALS::GLOBALS()
{
EFSAccessDenied = NULL;
Banner1 = NULL;
Banner2 = NULL;
ErrorNotAdmin = NULL;
ErrorNoAD = NULL;
ErrorContinue = NULL;
ErrorBadSysVol = NULL;
DispDDP = NULL;
DispDDCP = NULL;
DispBoth = NULL;
ToolFailed = NULL;
CreateEFS = NULL;
DirCreate = NULL;
DirDelete = NULL;
InvalidEFS = NULL;
DSDelete = NULL;
DSAttrib = NULL;
DSLinkDO = NULL;
DSLinkDDP = NULL;
DirRead = NULL;
DirWrite = NULL;
DDPSuccess = NULL;
DDCPSuccess = NULL;
WarnURA = NULL;
IgnSchSwitch = NULL;
GenDSErr = NULL;
DSCreate = NULL;
CharYes = NULL;
RestoreIgnoredGPOFail = NULL;
pGPO = NULL;
pDDPSecDesc = NULL;
pDDCPSecDesc = NULL;
DomainNamingContext = NULL;
pDomainInfo = NULL;
hasEFSInfo = FALSE;
bIgnoreSchema = FALSE;
}
GLOBALS::~GLOBALS()
{
if (this->pDomainInfo != NULL)
{
DsRoleFreeMemory(this->pDomainInfo);
this->pDomainInfo = NULL;
}
if ( NULL != DomainNamingContext )
{
LocalFree(DomainNamingContext);
}
if ( pDDPSecDesc != NULL )
{
LocalFree(pDDPSecDesc);
}
if ( pDDCPSecDesc != NULL )
{
LocalFree(pDDCPSecDesc);
}
delete [] EFSAccessDenied;
delete [] Banner1;
delete [] Banner2;
delete [] ErrorNotAdmin;
delete [] ErrorNoAD;
delete [] ErrorContinue;
delete [] ErrorBadSysVol;
delete [] DispDDP;
delete [] DispDDCP;
delete [] DispBoth;
delete [] ToolFailed;
delete [] CreateEFS;
delete [] DirCreate;
delete [] DirDelete;
delete [] InvalidEFS;
delete [] DSDelete;
delete [] DSAttrib;
delete [] DSLinkDO;
delete [] DSLinkDDP;
delete [] DirRead;
delete [] DirWrite;
delete [] DDPSuccess;
delete [] DDCPSuccess;
delete [] WarnURA;
delete [] IgnSchSwitch;
delete [] GenDSErr;
delete [] DSCreate;
delete [] WrongSchema;
delete [] TargetSwitch;
delete [] CharYes;
delete [] RestoreIgnoredGPOFail;
}
HRESULT
_LoadString(
OUT WCHAR*& pwsz,
IN UINT nID
)
{
HRESULT hr;
hr = S_OK;
pwsz = new WCHAR [ 2048 ];
if ( ! pwsz )
{
return E_OUTOFMEMORY;
}
UINT nLen = ::LoadString(GetModuleHandle(NULL), nID, pwsz, 2048);
if (nLen == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
delete [] pwsz;
pwsz = NULL;
}
return hr;
}
void
PrintError(
DWORD dwError
)
{
BOOL bResult;
ULONG dwSize = 0;
WCHAR *lpBuffer;
bResult = FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (PWSTR ) &lpBuffer, dwSize, NULL);
if ( 0 == bResult )
{
return;
}
if ( lpBuffer != NULL )
{
DisplayError(lpBuffer);
LocalFree(lpBuffer);
}
return;
} //PrintError
void
PrintError(
WCHAR *lpStr1,
WCHAR *lpStr2
)
{
WCHAR *lpTotStr = NULL;
//
// Here, lpStr2 is a format string. So, no memory is needed for terminating
// since lpStr2 contains %s character.
//
ULONG uSize = lstrlen(lpStr1) + lstrlen(lpStr2) ;
lpTotStr = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * uSize);
if (NULL == lpTotStr)
{
return;
}
//
// Here lpStr2 contains one '%ls'...
// Ignore error here, since error occured while printing error.
//
(void) StringCchPrintf(lpTotStr, uSize, lpStr2, lpStr1);
DisplayError(lpTotStr);
LocalFree(lpTotStr);
return;
}
void
PrintError(
WCHAR *lpMes,
DWORD dwError
)
{
BOOL bResult;
ULONG dwSize = 0;
WCHAR *lpBuffer;
bResult = FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), (PWSTR ) &lpBuffer, dwSize, NULL);
if ( 0 == bResult )
{
return;
}
if ( lpBuffer != NULL )
{
WCHAR *lpTotBuf;
ULONG uSize;
//
// lpMes + lpBuffer + ' ' + ':' + '\0'
//
uSize = lstrlen(lpMes) + lstrlen(lpBuffer) + 1 + 1 + 1;
lpTotBuf = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR)*uSize);
if(NULL == lpTotBuf)
{
LocalFree(lpBuffer);
return;
}
//
// Ignore error here, since error occured while printing error.
//
(void) StringCchPrintf(lpTotBuf, uSize, L"%s :%s", lpMes, lpBuffer);
DisplayError(lpTotBuf);
LocalFree(lpBuffer);
LocalFree(lpTotBuf);
}
return;
} //PrintError
void
DisplayError (
WCHAR *lpBuffer
)
{
BOOL bError;
CONSOLE_SCREEN_BUFFER_INFO Info;
BOOL RestoreColor = FALSE;
HANDLE ErrorOut = NULL;
ULONG Length;
ErrorOut = GetStdHandle(STD_ERROR_HANDLE);
if (ErrorOut == INVALID_HANDLE_VALUE)
{
ErrorOut = NULL;
}
if (ErrorOut != NULL)
{
bError = GetConsoleScreenBufferInfo(ErrorOut, &Info);
if (bError != FALSE)
{
bError = SetConsoleTextAttribute( ErrorOut, FOREGROUND_RED | FOREGROUND_INTENSITY |
((Info.wAttributes & BACKGROUND_RED) ? 0 : (Info.wAttributes & 0xf0) ) );
if (bError != FALSE)
{
RestoreColor = TRUE;
}
}
bError = WriteConsole(ErrorOut, lpBuffer, lstrlen(lpBuffer), &Length, NULL);
// ignore error
}
bError = MessageBeep(MB_ICONEXCLAMATION);
// ignore error
if (RestoreColor)
{
bError = SetConsoleTextAttribute(ErrorOut, Info.wAttributes);
// ignore error
}
} // DisplayError
HRESULT SaveEFSCerts()
{
HRESULT hr;
GUID g_guidRegExt = REGISTRY_EXTENSION_GUID;
GUID clsidDomain;
hr = CLSIDFromString(DOMAIN_GUID,
&clsidDomain);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = global->pGPO->Save(TRUE, TRUE, &g_guidRegExt, &clsidDomain);
if ( FAILED(hr) )
{
PrintError(DDP, global->CreateEFS);
goto end;
}
//
// The Save method automatically increases the version number value in the DS.
// So, increment this value so that DS and sysvol will have the same version number
global->lDDPVersionNo++;
hr = S_OK;
end:
return hr;
} // SaveEFSCerts
HRESULT CreateEFSCerts(void)
{
DWORD dwError;
HRESULT hr;
PUCHAR pRecoveryPolicyBlob = NULL;
ULONG ulBlobSize;
PCCERT_CONTEXT pCertContext = NULL;
HKEY hKeyPolicyRoot;
HKEY hKey;
ULONG dwDisposition;
HCERTSTORE hCertStore = NULL;
WCHAR *szAdsiPath = NULL;
PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
hr = CoCreateInstance(CLSID_GroupPolicyObject,
NULL,
CLSCTX_SERVER,
IID_IGroupPolicyObject,
(void **)&(global->pGPO));
if ( FAILED(hr) )
{
PrintError(hr);
goto end;
}
//
// Get the current DC name
//
dwError = DsGetDcName(NULL,
global->pDomainInfo->DomainNameDns,
NULL,
NULL,
DS_IS_DNS_NAME,
&pDcInfo);
if(dwError != ERROR_SUCCESS)
{
PrintError(dwError);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
if (*(pDcInfo->DomainControllerName) != L'\\' || *(pDcInfo->DomainControllerName + 1) != L'\\')
{
hr = E_FAIL;
goto end;
}
ULONG ulNoChars = sizeof(L"LDAP://%s/CN=%s,CN=Policies,CN=System,%s")/sizeof(WCHAR) +
lstrlen(pDcInfo->DomainControllerName+2) +
sizeof(DOMAIN_GUID)/sizeof(WCHAR) +
lstrlen(global->DomainNamingContext);
szAdsiPath = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * ulNoChars);
if (!szAdsiPath)
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
hr = StringCchPrintf(szAdsiPath,
ulNoChars,
L"LDAP://%s/CN=%s,CN=Policies,CN=System,%s",
pDcInfo->DomainControllerName+2,
DOMAIN_GUID,
global->DomainNamingContext);
ASSERT(SUCCEEDED(hr));
//
// Open the GPO Object
//
hr = global->pGPO->OpenDSGPO(szAdsiPath,
GPO_OPEN_LOAD_REGISTRY);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
//
// Get the registry key for the machine section
//
hr = global->pGPO->GetRegistryKey(GPO_SECTION_MACHINE, &hKeyPolicyRoot);
if (FAILED(hr))
{
PrintError(DDP, global->InvalidEFS);
dbgprint(L"dbg: CreateEFSCerts: GetRegistryKey failed with 0x%x\n", hr);
goto end;
}
dwError = GenerateDefaultEFSRecoveryPolicy (&pRecoveryPolicyBlob,
&ulBlobSize,
&pCertContext);
if (dwError != ERROR_SUCCESS)
{
dbgprint(L"dbg: CreateEFSCerts: GenerateDefaultEFSRecoveryPolicy failed with 0x%x\n", dwError);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
//
// Add the EFS cert to the cert store of this GPO
//
CERT_SYSTEM_STORE_RELOCATE_PARA paraRelocate;
paraRelocate.hKeyBase = hKeyPolicyRoot;
paraRelocate.pwszSystemStore = L"EFS";
hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY |
CERT_SYSTEM_STORE_RELOCATE_FLAG,
(void *)&paraRelocate
);
if ( hCertStore )
{
BOOL bError;
bError = CertAddCertificateContextToStore(
hCertStore,
pCertContext, // pCertContext,
CERT_STORE_ADD_ALWAYS,
NULL
);
if (!bError)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
}
else
{
hr = HRESULT_FROM_WIN32 (GetLastError());
}
dwError = RegCreateKeyEx (hKeyPolicyRoot,
CERT_EFSBLOB_REGPATH,
0,
TEXT("REG_SZ"),
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
NULL);
if (dwError != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32 (dwError);
goto end;
}
dwError = RegSetValueEx (hKey,
CERT_EFSBLOB_VALUE_NAME,
0,
REG_BINARY,
(PBYTE) pRecoveryPolicyBlob, // EfsBlob
ulBlobSize);
hr = HRESULT_FROM_WIN32 (dwError);
end:
if (szAdsiPath)
{
LocalFree(szAdsiPath);
}
if (hCertStore)
{
CertCloseStore(hCertStore, 0);
}
if (pCertContext)
{
CertFreeCertificateContext(pCertContext);
}
if (pRecoveryPolicyBlob)
{
free (pRecoveryPolicyBlob);
}
return hr;
}
HRESULT
CreateFolder(
PWSTR pFolderPath
)
{
DWORD dwError;
dbgprint(L"dbg: CreateFolder(%s)\n", pFolderPath);
if (CreateDirectory(pFolderPath, NULL) == FALSE)
{
dwError = GetLastError();
if (dwError != ERROR_ALREADY_EXISTS)
{
PrintError(pFolderPath, global->DirCreate);
return HRESULT_FROM_WIN32(dwError);
}
}
return S_OK;
} // CreateFolder
HRESULT
CreateSecurityTemplate (
WCHAR *szSrcFile,
WCHAR *szDestFile
)
{
DWORD dwError;
DWORD rc=ERROR_SUCCESS;
PVOID hProfile=NULL;
PSCE_PROFILE_INFO pSceInfo=NULL;
rc = SceOpenProfile(
szSrcFile,
SCE_INF_FORMAT,
&hProfile
);
if (rc != SCESTATUS_SUCCESS)
{
dwError = GetLastError();
goto end;
}
//
// load informatin from the template
//
rc = SceGetSecurityProfileInfo(
hProfile,
SCE_ENGINE_SCP,
AREA_ALL,
&pSceInfo,
NULL
);
if (rc != SCESTATUS_SUCCESS)
{
dwError = GetLastError();
goto end;
}
rc = SceWriteSecurityProfileInfo(
szDestFile,
AREA_ALL,
pSceInfo,
NULL
);
if (rc != SCESTATUS_SUCCESS)
{
dwError = GetLastError();
goto end;
}
rc = SceFreeProfileMemory(pSceInfo);
if (rc != SCESTATUS_SUCCESS)
{
dwError = GetLastError();
goto end;
}
dwError = ERROR_SUCCESS;
end:
if ( NULL != hProfile )
{
SceCloseProfile(&hProfile);
}
if ( dwError != ERROR_SUCCESS )
{
PrintError(dwError);
}
return HRESULT_FROM_WIN32(dwError);
}
HRESULT
CreateSysVolDomain(
)
{
DWORD dwError;
HRESULT hr;
WCHAR *TempPath = NULL;
HANDLE PolFile = NULL;
HMODULE Module = NULL;
ULONG uTempPathLen = 0;
BOOL bError;
//
// The string that TempPath will be like
// <sysvolpath>\<domain name>\policies\<domain guid>\Microsoft\windows NT\\secedit
// Memory is allocated for each directory name and for '\' if needed.
//
uTempPathLen = lstrlen(global->SysVolPath) + 1 + lstrlen(global->pDomainInfo->DomainNameDns) + lstrlen(L"\\policies")
+ 1+lstrlen(DOMAIN_GUID)+ lstrlen(L"\\MACHINE\\registry.pol") + lstrlen(L"\\Microsoft\\Windows NT\\secedit")
+ lstrlen(L"\\USER\\Microsoft\\RemoteInstll\\oscfilter.ini") + 1;
TempPath = (WCHAR*) LocalAlloc ( LPTR, uTempPathLen * sizeof(WCHAR));
if(NULL == TempPath)
{
hr = E_OUTOFMEMORY;
goto end;
}
hr = StringCchPrintf(TempPath,
uTempPathLen,
L"%s\\%s\\Policies",
global->SysVolPath,
global->pDomainInfo->DomainNameDns);
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = SetPolicySecurityInfo(TempPath);
if ( FAILED(hr) )
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\");
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, DOMAIN_GUID);
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
// Set security info for this directory
dwError = SetSysvolSecurityFromDSSecurity(
TempPath,
DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION ,
global->pDDPSecDesc);
if (dwError != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\MACHINE");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\Microsoft");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\Windows NT");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\SecEdit");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchPrintf(TempPath, uTempPathLen, L"%s\\%s\\Policies\\%s\\USER", global->SysVolPath, global->pDomainInfo->DomainNameDns , DOMAIN_GUID);
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\Microsoft");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\RemoteInstall");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\oscfilter.ini");
if (FAILED(hr))
{
goto end;
}
bError = WritePrivateProfileString(L"choice", L"custom", L"0", TempPath);
if (bError == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
bError = WritePrivateProfileString(L"choice", L"tools", L"0", TempPath);
if (bError == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
bError = WritePrivateProfileString(L"choice", L"restart", L"0", TempPath);
if (bError == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto end;
}
hr = S_OK;
end:
if (NULL != TempPath)
{
LocalFree (TempPath);
}
if (PolFile != NULL)
{
CloseHandle(PolFile);
PolFile = NULL;
}
if (Module != NULL)
{
FreeLibrary(Module);
Module = NULL;
}
if (FAILED(hr))
{
PrintError(hr);
}
return hr;
} // CreateSysVolDomain
HRESULT
CreateSysVolController(
)
{
DWORD dwError;
HRESULT hr;
WCHAR *TempPath = NULL;
ULONG uTempPathLen = 0;
//
// The string that TempPath will be holding will be like
// <sysvolpath>\domain name>\policies\<guid>\MACHINE\Microsoft\windows NT\SecEdit
// Memory is allocated for each directory name and for '\' if needed.
//
uTempPathLen = lstrlen(global->SysVolPath) + 1 + lstrlen(global->pDomainInfo->DomainNameDns ) + lstrlen(L"\\Policies")
+ 1 + lstrlen(DC_GUID) + lstrlen (L"\\MACHINE\\Microsoft\\windows NT\\SecEdit") + lstrlen(L"\\USER") + 1;
TempPath = (WCHAR *) LocalAlloc( LPTR, sizeof(WCHAR) * uTempPathLen);
if ( NULL == TempPath )
{
hr = E_OUTOFMEMORY;
goto end;
}
hr = StringCchPrintf(TempPath,
uTempPathLen,
L"%s\\%s\\Policies\\%s",
global->SysVolPath,
global->pDomainInfo->DomainNameDns ,
DC_GUID);
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
// Set security info for this directory
dwError = SetSysvolSecurityFromDSSecurity(
TempPath,
DACL_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION ,
global->pDDCPSecDesc);
if (dwError != ERROR_SUCCESS)
{
PrintError(dwError);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\MACHINE");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\Microsoft");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\Windows NT");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchCat(TempPath, uTempPathLen, L"\\SecEdit");
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
hr = StringCchPrintf(TempPath,
uTempPathLen,
L"%s\\%s\\Policies\\%s\\USER",
global->SysVolPath,
global->pDomainInfo->DomainNameDns ,
DC_GUID);
if (FAILED(hr))
{
goto end;
}
hr = CreateFolder(TempPath);
if (FAILED(hr))
{
goto end;
}
end:
if ( TempPath != NULL)
{
LocalFree (TempPath);
}
return hr;
} // CreateSysVolController
HRESULT
BackupEfsCert(
)
{
HRESULT hr;
WCHAR sz[1024];
HKEY hKey = 0;
DWORD dwError;
FILETIME fileTime;
DWORD dwSubKeySize;
ULONG uEnumIndex=0;
WCHAR *TempPath = NULL;
ULONG uLength;
BOOL bError;
PDOMAIN_CONTROLLER_INFO pDcInfo = NULL;
hr = CoCreateInstance(CLSID_GroupPolicyObject,
NULL,
CLSCTX_SERVER,
IID_IGroupPolicyObject,
(void **)&(global->pGPO));
if ( FAILED(hr) )
{
PrintError(hr);
goto end;
}
//
// Get the current DC name
//
dwError = DsGetDcName(NULL,
global->pDomainInfo->DomainNameDns,
NULL,
NULL,
DS_IS_DNS_NAME,
&pDcInfo);
if(dwError != ERROR_SUCCESS)
{
PrintError(dwError);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
//
// Create the USER subdirectory under defaultdomainpolicy, if that don't exist
// This will make sure that opendsgpo will not fail due to the obsence of USER directory
// Here, the temppath will hold a string like \\machine\\registry.pol, or \\user\\registry.pol
// Memory is allocated for each directory name and for '\' if needed.
// More memory is assigned then actually needed
//
uLength = lstrlen(global->SysVolPath) + 1 + lstrlen(global->pDomainInfo->DomainNameDns) + lstrlen( L"\\Policies")
+ 1 + lstrlen(DOMAIN_GUID) + lstrlen(L"\\USER") + lstrlen(L"\\MACHINE\\Registry.pol") + 1;
TempPath = (WCHAR *) LocalAlloc( LPTR, sizeof(WCHAR) * uLength);
if ( NULL == TempPath )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
hr = StringCchPrintf(TempPath,
uLength,
L"%s\\%s\\Policies\\%s\\USER",
global->SysVolPath,
global->pDomainInfo->DomainNameDns ,
DOMAIN_GUID);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
bError = CreateDirectory(TempPath, NULL);
if ( FALSE == bError )
{
dwError = GetLastError();
if(ERROR_ALREADY_EXISTS == dwError )
{
hr = StringCchCat (TempPath, uLength, L"\\Registry.pol");
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
//
// Delete so that corrupt registry.pol does not cause an error
//
(void) DeleteFile (TempPath);
}
else if (dwError != ERROR_PATH_NOT_FOUND)
{
if ( ERROR_ACCESS_DENIED == dwError )
{
PrintError(TempPath, global->DirCreate);
}
else
{
PrintError(dwError);
}
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
}
//
// Open the GPO Object
//
if (*(pDcInfo->DomainControllerName) != L'\\' || *(pDcInfo->DomainControllerName + 1) != L'\\')
{
hr = E_FAIL;
goto end;
}
hr = StringCchPrintf(sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://%s/CN=%s,CN=Policies,CN=System,%s",
pDcInfo->DomainControllerName+2,
DOMAIN_GUID,
global->DomainNamingContext);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = global->pGPO->OpenDSGPO(sz,
GPO_OPEN_LOAD_REGISTRY);
if (FAILED(hr))
{
if ((HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr) || (HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) == hr))
{
//
// ERROR_INVALID_PARAMETER is returned when registry key is bigger than maximum
// acceptable value: bug 631804
// ERROR_PATH_NOT_FOUND is returned when sysvol\policies or sysvol\policies\<GPO>
// directory is not present
//
//
global->pGPO->Release();
global->pGPO = NULL;
global->hasEFSInfo = FALSE;
hr = S_OK;
}
else if (HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED) == hr)
{
WCHAR *szAccessDenied = NULL;
hr = StringCchPrintf(TempPath,
uLength,
L"%s\\%s\\Policies\\%s\\MACHINE\\Registry.pol",
global->SysVolPath,
global->pDomainInfo->DomainNameDns ,
DOMAIN_GUID);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
//
// No memory for terminating \0 is required since global->EFSAccessDenied is a format string.
// global->EFSAccessDenied + TempPath + sz
uLength = lstrlen(global->EFSAccessDenied) + lstrlen(TempPath) + sizeof(sz)/sizeof(sz[0]) ;
szAccessDenied = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * uLength);
if ( NULL == szAccessDenied )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
hr = StringCchPrintf(szAccessDenied, uLength, global->EFSAccessDenied, TempPath, sz);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
DisplayError(szAccessDenied);
LocalFree(szAccessDenied);
}
else
{
PrintError(DDP, global->InvalidEFS);
PrintError(hr);
}
goto end;
}
//
// Get the registry key for the machine section
//
hr = global->pGPO->GetRegistryKey(GPO_SECTION_MACHINE, &hKey);
if (FAILED(hr))
{
PrintError(DDP, global->InvalidEFS);
PrintError(hr);
goto end;
}
//
// Delete all the keys except EFS certs
//
hr = RegDelnodeExceptEFS(hKey, global->hasEFSInfo);
if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
{
global->hasEFSInfo = FALSE;
global->pGPO->Release();
global->pGPO = NULL;
hr = S_OK;
}
if ( hr != S_OK )
{
PrintError(DDP, global->InvalidEFS);
PrintError(hr);
}
end:
if (pDcInfo)
{
NetApiBufferFree(pDcInfo);
}
if(TempPath != NULL)
{
LocalFree(TempPath);
}
if( hKey != 0)
{
RegCloseKey(hKey);
}
return hr;
} // BackupEfsCert
HRESULT
DeleteTree(
PWSTR pPath
)
{
DWORD dwError;
BOOL bError;
HRESULT hr;
WCHAR *TempPath = NULL;
HANDLE FindHandle = NULL;
WIN32_FIND_DATA FindData;
ULONG ulSize;
//
// TempPath will be in the form <pPath>\<File Name>
// pPath + '\' + File Name + '\0'
//
ulSize = lstrlen(pPath)+ 1 + MAX_PATH + 1;
TempPath = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * ulSize );
if ( NULL == TempPath)
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
dbgprint(L"dbg: DeleteTree(%s)\n", pPath);
hr = StringCchPrintf(TempPath, ulSize, L"%s\\*", pPath);
if (FAILED(hr))
{
goto end;
}
FindHandle = FindFirstFile(TempPath, &FindData);
if (FindHandle == INVALID_HANDLE_VALUE)
{
FindHandle = NULL;
}
if (NULL == FindHandle )
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
if ( HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) == hr )
{
hr = S_OK;
}
else
{
PrintError(TempPath, global->DirDelete);
}
goto end;
}
while (TRUE) {
// is this a special file?
if (FindData.cFileName[0] == L'.' )
{
goto next_file;
}
// no? delete it
hr = StringCchPrintf(TempPath, ulSize, L"%s\\%s", pPath, FindData.cFileName);
if (FAILED(hr))
{
goto end;
}
if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
// recurse.
hr = DeleteTree(TempPath);
if (FAILED(hr))
{
goto end;
}
}
else
{
// delete
dbgprint(L"dbg: DeleteFile(%s)\n", TempPath);
SetFileAttributes(TempPath, FILE_ATTRIBUTE_NORMAL);
bError = DeleteFile(TempPath);
if (bError == FALSE)
{
dwError = GetLastError();
PrintError(TempPath, global->DirDelete);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
}
next_file:
bError = FindNextFile(FindHandle, &FindData);
if (bError == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_FILES))
{
hr = S_OK;
break;
}
else
{
goto end;
}
}
}
// and remove the directory now
dbgprint(L"dbg: RemoveDirectory(%s)\n", pPath);
bError = RemoveDirectory(pPath);
if (bError == FALSE)
{
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
if (hr == HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) || hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY))
{
hr = S_OK;
}
else
{
PrintError(pPath, global->DirDelete);
goto end;
}
}
hr = S_OK;
end:
LocalFree(TempPath);
if (FindHandle != NULL)
{
FindClose(FindHandle);
FindHandle = NULL;
}
return hr;
} // DeleteTree
HRESULT
CheckDSSchemaVersion(
BOOL *bResult
)
{
WCHAR sz[256];
WCHAR szSchema[256];
CComPtr<IADs> pADs;
CComVariant Var;
HRESULT hr;
CComBSTR ObjectVersion(L"objectVersion");
CComBSTR SchemaNamingContext( L"schemaNamingContext" );
if ( ! SchemaNamingContext ||
! ObjectVersion )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
hr = StringCchCopy(sz, sizeof(sz)/sizeof(sz[0]), L"LDAP://rootDSE");
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(sz, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz, global->GenDSErr);
goto end;
}
hr = pADs->GetInfo();
if (FAILED(hr))
{
dbgprint(L"dbg: GetInfo failed on rootDSE %x\n", hr);
PrintError(sz, global->GenDSErr);
goto end;
}
hr = pADs->Get(SchemaNamingContext, &Var);
if (FAILED(hr))
{
dbgprint(L"dbg: failed to get rootDomainNamingContext %x \n", hr);
PrintError(sz, global->GenDSErr);
goto end;
}
hr = Var.ChangeType(VT_BSTR);
if (FAILED(hr))
{
dbgprint(L"dbg: ChangeType failed to BSTR %x\n", hr);
PrintError(hr);
goto end;
}
hr = StringCchPrintf(szSchema, sizeof(szSchema)/sizeof(szSchema[0]), L"LDAP://%s", Var.bstrVal);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(szSchema, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, szSchema);
PrintError(hr);
PrintError(szSchema, global->GenDSErr);
goto end;
}
hr = pADs->GetInfo();
if (FAILED(hr))
{
dbgprint(L"dbg: GetInfo failed on rootDSE %x\n", hr);
PrintError(szSchema, global->GenDSErr);
goto end;
}
Var.Clear();
hr = pADs->Get(ObjectVersion, &Var);
if (FAILED(hr))
{
dbgprint(L"dbg: failed to get schemaDomainNamingContext %x \n", hr);
PrintError(hr);
PrintError(szSchema, global->GenDSErr);
goto end;
}
if (SCHEMA_VERSION == Var.lVal)
{
*bResult = TRUE;
}
else
{
*bResult = FALSE;
}
end:
return hr;
}
// clean the domains GPO
// clean the controller GPO
HRESULT
CleanPolicyObjects(
)
{
HRESULT hr;
WCHAR sz[1024];
CComPtr<IADs> pADs;
CComVariant Var;
CComBSTR GroupPolicyContainerName(L"groupPolicyContainer");
CComBSTR DisplayName(L"displayName");
CComBSTR GPOFlags(L"flags");
CComBSTR GPCFileSysPath(L"gPCFileSysPath");
CComBSTR GPCFunctionalityVersion(L"gPCFunctionalityVersion");
CComBSTR VersionNumber(L"VersionNumber");
CComBSTR GPCUserExtensionNames(L"gPCUserExtensionNames");
CComBSTR GPCMachineExtensionNames(L"gPCMachineExtensionNames");
CComBSTR GPCWQLFilter(L"gPCWQLFilter");
if ( ! GroupPolicyContainerName ||
! DisplayName ||
! GPCFileSysPath ||
! GPCFunctionalityVersion ||
! VersionNumber ||
! GPCUserExtensionNames ||
! GPCMachineExtensionNames ||
! GPCWQLFilter )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=%s,CN=Policies,CN=System,%s",
DOMAIN_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
pADs.Release();
hr = AdminToolsOpenObject(sz, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADs, (void**)&pADs);
if ( FAILED(hr) && hr != (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT)))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz, global->GenDSErr);
goto end;
}
else
{
CComPtr<IADsContainer> pFolder;
CComPtr<IDispatch> pDisp;
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=Policies,CN=System,%s",
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(sz, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADsContainer, (void**)&pFolder);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz, global->DSCreate);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"CN=%s",
DOMAIN_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
{
CComBSTR ContainerPath(sz);
if ( ContainerPath )
{
hr = pFolder->Create(GroupPolicyContainerName, ContainerPath, &pDisp);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Create failed %x on %s\n", hr, sz);
PrintError(sz, global->DSCreate);
goto end;
}
}
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: Query Interface failed %x for Creating IID_IADS\n", hr);
PrintError(sz, global->DSCreate);
goto end;
}
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=Machine,CN=%s,CN=Policies,CN=System,%s",
DOMAIN_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ResetContainerFromDS(sz, pADs);
if (FAILED(hr))
{
dbgprint(L"ResetContainerFromDS failed %x on %s\n", hr, sz);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=User,CN=%s,CN=Policies,CN=System,%s",
DOMAIN_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ResetContainerFromDS(sz, pADs);
if (FAILED(hr))
{
dbgprint(L"ResetContainerFromDS failed %x on %s\n", hr, sz);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=%s,CN=Policies,CN=System,%s",
DOMAIN_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ADsGetObject(sz, IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz,global->GenDSErr);
goto end;
}
// clean the display name (displayName)
// strip any WQL filters to <not set> (gPCWQLFilter)
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(L"Default Domain Policy");
if ( Var.bstrVal )
{
hr = pADs->Put(DisplayName, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on displayName %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// reset flags to 0 (flags)
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = 0;
hr = pADs->Put(GPOFlags, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on flags %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// set the filesys path (gPCFileSysPath)
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"\\\\%s\\sysvol\\%s\\Policies\\%s",
global->pDomainInfo->DomainNameDns,
global->pDomainInfo->DomainNameDns,
DOMAIN_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(sz);
if ( Var.bstrVal )
{
hr = pADs->Put(GPCFileSysPath, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCFileSysPath %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// set the version to 2 (gPCFunctionalityVersion)
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = 2;
hr = pADs->Put(GPCFunctionalityVersion, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCFunctionalityVersion %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// Increment the version number
//
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = global->lDDPVersionNo;
hr = pADs->Put(VersionNumber, Var);
if( FAILED(hr))
{
dbgprint(L"dbg: Put failed on version number %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// set the extensions (gPCUserExtensionNames)
//
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(DDP_USEREXT);
if ( Var.bstrVal )
{
hr = pADs->Put(GPCUserExtensionNames, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if( FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCUserExtensionNames %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// set the extensions (gPCMachineExtensionNames)
//
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(DDP_MACHEXT);
if ( Var.bstrVal )
{
hr = pADs->Put(GPCMachineExtensionNames, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if( FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCMachineExtensionNames %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// strip any WQL filters to <not set> (gPCWQLFilter)
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = NULL;
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, GPCWQLFilter, Var);
if (FAILED(hr))
{
dbgprint(L"Put failed on gPCWQLFilter %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// and update it
hr = pADs->SetInfo();
if (FAILED(hr))
{
dbgprint(L"dbg: SetInfo failed %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=%s,CN=Policies,CN=System,%s",
DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(sz, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADs, (void**)&pADs);
if ( FAILED(hr) && hr != (HRESULT_FROM_WIN32(ERROR_DS_NO_SUCH_OBJECT)) )
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz,global->GenDSErr);
goto end;
}
else
{
CComPtr<IADsContainer> pFolder;
CComPtr<IDispatch> pDisp;
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=Policies,CN=System,%s",
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = AdminToolsOpenObject(sz, NULL, NULL, ADS_SECURE_AUTHENTICATION | ADS_SERVER_BIND, IID_IADsContainer, (void**)&pFolder);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz,global->GenDSErr);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"CN=%s",
DC_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
{
CComBSTR ContainerPath(sz);
if ( ContainerPath )
{
hr = pFolder->Create(GroupPolicyContainerName, ContainerPath, &pDisp);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Create failed %x on %s\n", hr, sz);
PrintError(sz,global->DSCreate);
goto end;
}
}
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: Query Interface failed %x for Creating IID_IADS\n", hr);
PrintError(sz,global->DSCreate);
goto end;
}
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=Machine,CN=%s,CN=Policies,CN=System,%s",
DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ResetContainerFromDS(sz, pADs);
if (FAILED(hr))
{
dbgprint(L"ResetContainerFromDS failed %x on %s\n", hr, sz);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=User,CN=%s,CN=Policies,CN=System,%s",
DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ResetContainerFromDS(sz, pADs);
if (FAILED(hr))
{
dbgprint(L"ResetContainerFromDS failed %x on %s\n", hr, sz);
goto end;
}
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"LDAP://CN=%s,CN=Policies,CN=System,%s",
DC_GUID,
global->DomainNamingContext) ;
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = ADsGetObject(sz, IID_IADs, (void**)&pADs);
if (FAILED(hr))
{
dbgprint(L"dbg: AdminToolsOpenObject failed %x on %s\n", hr, sz);
PrintError(sz,global->GenDSErr);
goto end;
}
// clean the display name (displayName)
// strip any WQL filters to <not set> (gPCWQLFilter)
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(DEFAULT_DC_POLICY_NAME);
if ( Var.bstrVal )
{
hr = pADs->Put(DisplayName, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on displayName %x\n", hr);
PrintError(sz, global->DSAttrib);
goto end;
}
// reset flags to 0 (flags)
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = 0;
hr = pADs->Put(GPOFlags, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on flags %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// set the filesys path (gPCFileSysPath)
hr = StringCchPrintf( sz,
sizeof(sz)/sizeof(sz[0]),
L"\\\\%s\\sysvol\\%s\\Policies\\%s",
global->pDomainInfo->DomainNameDns,
global->pDomainInfo->DomainNameDns,
DC_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(sz);
if ( Var.bstrVal )
{
hr = pADs->Put(GPCFileSysPath, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCFileSysPath %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// set the version to 2 (gPCFunctionalityVersion)
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = 2;
hr = pADs->Put(GPCFunctionalityVersion, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCFunctionalityVersion %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// Increment the version number
//
Var.Clear();
Var.ChangeType(VT_I4);
Var.lVal = global->lDDCPVersionNo;
hr = pADs->Put(VersionNumber, Var);
if( FAILED(hr))
{
dbgprint(L"dbg: Put failed on version number %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// Set the (gPCUserExtensionNames) to <not set>
//
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = NULL ;
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, GPCUserExtensionNames, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCUserExtensionNames %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
//
// set the extensions (gPCMachineExtensionNames)
//
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = SysAllocString(DDC_MACHEXT);
if ( Var.bstrVal )
{
hr = pADs->Put(GPCMachineExtensionNames, Var);
}
else
{
hr = E_OUTOFMEMORY;
}
if( FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCMachineExtensionNames %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// strip any WQL filters to <not set> (gPCWQLFilter)
Var.Clear();
Var.ChangeType(VT_BSTR);
Var.bstrVal = NULL;
hr = pADs->PutEx(ADS_PROPERTY_CLEAR, GPCWQLFilter, Var);
if (FAILED(hr))
{
dbgprint(L"dbg: Put failed on gPCWQLFilter %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
// and update it
hr = pADs->SetInfo();
if (FAILED(hr))
{
dbgprint(L"dbg: SetInfo failed %x\n", hr);
PrintError(sz,global->DSAttrib);
goto end;
}
}
hr = S_OK;
end:
return hr;
} // CleanPolicyObjects
CIgnoredGPO::CIgnoredGPO(
WCHAR* wszGPOID,
WCHAR* wszGPOName ) :
_pGptIniFile( NULL ),
_pGptTmplFile( NULL ),
_wszError( NULL )
{
//
// Note -- we handle errors in the constructor by leaving members
// set to NULL -- if these are NULL, other methods will fail
//
WCHAR* wszGptTmplPath = NULL;
WCHAR* wszGptIniPath = NULL;
ULONG uLength = 0;
uLength = lstrlen(global->SysVolPath) + 1 + lstrlen(global->pDomainInfo->DomainNameDns) + lstrlen(L"\\Policies")
+ 1 + lstrlen(wszGPOID) + lstrlen(FILE_GPTTMPLINF)
+ lstrlen(FILE_GPTINI) + 1;
wszGptTmplPath = (WCHAR*) LocalAlloc( LPTR, uLength * sizeof(WCHAR) );
if( NULL == wszGptTmplPath )
{
goto CIgnoredGPO_CIgnoredGPO_Exit;
}
wszGptIniPath = (WCHAR*) LocalAlloc( LPTR, uLength * sizeof(WCHAR) );
if( NULL == wszGptIniPath )
{
goto CIgnoredGPO_CIgnoredGPO_Exit;
}
HRESULT hr;
hr = StringCchPrintf(
wszGptTmplPath,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTTMPLINF,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
wszGPOID);
ASSERT( SUCCEEDED(hr) );
hr = StringCchPrintf(
wszGptIniPath,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTINI,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
wszGPOID );
ASSERT( SUCCEEDED(hr) );
_pGptTmplFile = new CGPOFile( wszGptTmplPath );
if ( _pGptTmplFile )
{
DWORD Status = InitializeErrorText(
wszGPOName );
if ( ERROR_SUCCESS == Status )
{
_pGptIniFile = new CGPOFile( wszGptIniPath );
}
}
CIgnoredGPO_CIgnoredGPO_Exit:
if ( wszGptIniPath )
{
LocalFree( wszGptIniPath );
}
if ( wszGptTmplPath )
{
LocalFree( wszGptTmplPath );
}
} // CIgnoredGPO::CIgnoredGPO
CIgnoredGPO::~CIgnoredGPO()
{
delete _pGptIniFile;
delete _pGptTmplFile;
LocalFree( _wszError );
}
DWORD
CIgnoredGPO::Backup()
{
DWORD Status = ERROR_SUCCESS;
//
// Detect failure in the constructor by checking
// that necessary members are properly initialized to non-NULL values
//
if ( ! _pGptIniFile || ! _pGptTmplFile )
{
Status = ERROR_OUTOFMEMORY;
goto CIgnoredGPO_Backup_CleanupAndExit;
}
Status = _pGptIniFile->Backup();
if ( ERROR_SUCCESS != Status )
{
dbgprint(L"Failed to back up gpt.ini file\n");
goto CIgnoredGPO_Backup_CleanupAndExit;
}
Status = _pGptTmplFile->Backup();
if ( ERROR_SUCCESS != Status )
{
dbgprint(L"Failed to back up gpttmpl.inf file\n");
goto CIgnoredGPO_Backup_CleanupAndExit;
}
CIgnoredGPO_Backup_CleanupAndExit:
return Status;
} // CIgnoredGPO::Backup
DWORD
CIgnoredGPO::Restore()
{
DWORD Status = ERROR_SUCCESS;
DWORD StatusIniFile;
DWORD StatusTmplFile;
StatusIniFile = _pGptIniFile->Restore();
StatusTmplFile = _pGptTmplFile->Restore();
if ( ERROR_SUCCESS != StatusIniFile )
{
Status = StatusIniFile;
dbgprint(L"Failed to restore gpt.ini");
}
else if ( ERROR_SUCCESS != StatusTmplFile )
{
Status = StatusTmplFile;
DisplayError(_wszError);
}
if ( ERROR_SUCCESS != StatusTmplFile )
{
dbgprint(L"Failed to restore gpttmpl.inf\n");
}
return Status;
} // CIgnoredGPO::Restore
DWORD
CIgnoredGPO::InitializeErrorText(
WCHAR* wszGPOName )
{
//
// global->RestoreIgnoredGPOFail + GPTTmplPath + GPOName + 1
//
DWORD uLength = lstrlen(global->RestoreIgnoredGPOFail) + lstrlen(_pGptTmplFile->GetPath()) + lstrlen(wszGPOName) + 1;
_wszError = (WCHAR *) LocalAlloc(LPTR, sizeof(WCHAR) * uLength);
if ( NULL == _wszError )
{
return ERROR_OUTOFMEMORY;
}
HRESULT hr = StringCchPrintf(_wszError, uLength, global->RestoreIgnoredGPOFail, _pGptTmplFile->GetPath(), wszGPOName);
ASSERT(SUCCEEDED(hr));
return ERROR_SUCCESS;
}
CGPOFile::CGPOFile( WCHAR* wszFilePath ) :
_wszFullPath( NULL ),
_pFileData( NULL ),
_cbFileSize( 0 )
{
//
// Note -- we handle errors in the constructor by leaving the path
// set to NULL -- if this is NULL, other methods will fail
//
DWORD cchPath = lstrlen( wszFilePath ) + 1;
_wszFullPath = (WCHAR*) LocalAlloc( LPTR, cchPath * sizeof( *_wszFullPath ) );
if ( NULL == _wszFullPath )
{
return;
}
HRESULT hr;
hr = StringCchCopy(
_wszFullPath,
cchPath,
wszFilePath );
ASSERT( SUCCEEDED(hr) );
} // CGPOFile::CGPOFile
CGPOFile::~CGPOFile()
{
if ( _wszFullPath )
{
LocalFree( _wszFullPath );
}
if ( _pFileData )
{
LocalFree( _pFileData );
}
}
DWORD
CGPOFile::Backup()
{
DWORD Status = ERROR_SUCCESS;
HANDLE hFile = NULL;
//
// Detect failure in the constructor by checking
// that necessary path members is properly initialized to a non-NULL value
//
if ( NULL == _wszFullPath )
{
Status = ERROR_OUTOFMEMORY;
goto CGPOFile_Backup_CleanupAndExit;
}
hFile = CreateFile(
_wszFullPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( INVALID_HANDLE_VALUE == hFile )
{
Status = GetLastError();
if ( ( ERROR_FILE_NOT_FOUND == Status ) ||
( ERROR_PATH_NOT_FOUND == Status ) )
{
Status = ERROR_SUCCESS;
}
hFile = NULL;
goto CGPOFile_Backup_CleanupAndExit;
}
DWORD cbFileSize;
DWORD cbFileSizeHigh;
cbFileSize = GetFileSize(
hFile,
&cbFileSizeHigh);
if ( -1 == cbFileSize )
{
Status = GetLastError();
goto CGPOFile_Backup_CleanupAndExit;
}
if ( 0 != cbFileSizeHigh )
{
Status = ERROR_INVALID_DATA;
goto CGPOFile_Backup_CleanupAndExit;
}
_pFileData = (BYTE*) LocalAlloc( LPTR, cbFileSize );
if ( NULL == _pFileData )
{
Status = ERROR_OUTOFMEMORY;
goto CGPOFile_Backup_CleanupAndExit;
}
BOOL bReadSucceeded;
DWORD cbRead;
bReadSucceeded = ReadFile(
hFile,
_pFileData,
cbFileSize,
&cbRead,
NULL);
if ( ! bReadSucceeded )
{
Status = GetLastError();
goto CGPOFile_Backup_CleanupAndExit;
}
//
// Don't set this to non-zero until we've successfully read the file --
// this way a call to Restore() will do nothing if any of these operations
// have failed (it won't try to write back bogus data)
//
_cbFileSize = cbFileSize;
CGPOFile_Backup_CleanupAndExit:
if ( NULL != hFile )
{
CloseHandle( hFile );
}
return Status;
} // CGPOFile::Backup
DWORD
CGPOFile::Restore()
{
DWORD Status = ERROR_SUCCESS;
HANDLE hFile = NULL;
//
// Zero sized files are invalid, so if we are called with this, we know
// the file did not exist and does not need to be restored (or we couldn't
// back up the file, in which case we shouldn't try to restore anything)
//
if ( 0 == _cbFileSize )
{
goto RestoreGPOFile_CleanupAndExit;
}
hFile = CreateFile(
_wszFullPath,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL);
if ( INVALID_HANDLE_VALUE == hFile )
{
Status = GetLastError();
goto RestoreGPOFile_CleanupAndExit;
}
BOOL bWriteSucceeded;
//
// First we need to truncate the file to 0 -- otherwise,
// if the file is larger than the data we're about to write, the
// extra data in the current version of the file will still exist
// when we're done.
//
bWriteSucceeded = SetEndOfFile( hFile );
if ( ! bWriteSucceeded )
{
Status = GetLastError();
goto RestoreGPOFile_CleanupAndExit;
}
DWORD dwWritten;
bWriteSucceeded = WriteFile(
hFile,
_pFileData,
_cbFileSize,
&dwWritten,
NULL);
if ( ! bWriteSucceeded )
{
Status = GetLastError();
goto RestoreGPOFile_CleanupAndExit;
}
RestoreGPOFile_CleanupAndExit:
if ( NULL != hFile )
{
CloseHandle( hFile );
}
return Status;
} // CGPOFile::Restore
WCHAR*
CGPOFile::GetPath()
{
return _wszFullPath;
} // CGPOFile::GetPath
int
_cdecl
wmain(
int argc,
WCHAR ** argv
)
{
DWORD dwError;
BOOL bError;
HRESULT hr = E_FAIL;
BOOL bIsDomain;
BOOL bIsAdmin;
WCHAR sz[256];
ULONG Length;
ULONG Type;
WCHAR *TempPath = NULL;
WCHAR *szProfilePath = NULL;
HKEY Key = NULL;
BOOL UnknownArgs = FALSE;
LONG lError;
LPBYTE pShareName = NULL;
WCHAR szVersionNo[MAX_VERSION_LENGTH];
NET_API_STATUS netapiStatus;
dbgprint(L"dbg: wmain started !\n");
WCHAR achCodePage[13] = L".OCP";
UINT CodePage = GetConsoleOutputCP();
//
// Set locale to the default
//
if ( 0 != CodePage )
{
_ultow( CodePage, achCodePage + 1, 10 );
}
_wsetlocale(LC_ALL, achCodePage);
SetThreadUILanguage(0);
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
global->RestoreType = GLOBALS::RESTORE_BOTH;
hr = global->Init();
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
if (argc > 1 && argv[1] != NULL)
{
int iIndex = 1;
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, argv[1], -1, L"/?", -1) == CSTR_EQUAL)
{
wprintf(global->Banner1);
wprintf(global->TargetSwitch);
wprintf(global->IgnSchSwitch);
hr = S_OK;
goto end;
}
Length = lstrlen(argv[1]);
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, argv[1], -1, TARGET_ARG_IGNORE_SCHEMA, -1) == CSTR_EQUAL)
{
global->bIgnoreSchema = TRUE;
iIndex = 2;
}
// check if a target was specified
if (argc == iIndex + 1 && argv[iIndex] != NULL)
{
Length = lstrlen(argv[iIndex]);
if ( Length >= TARGET_ARG_COUNT &&
CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, argv[iIndex], TARGET_ARG_COUNT, TARGET_ARG, TARGET_ARG_COUNT) == CSTR_EQUAL)
{
WCHAR * p = &argv[iIndex][TARGET_ARG_COUNT];
if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, p, -1, TARGET_ARG_DOMAIN, -1) == CSTR_EQUAL)
{
global->RestoreType = GLOBALS::RESTORE_DOMAIN;
}
else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, p, -1, TARGET_ARG_DC, -1) == CSTR_EQUAL)
{
global->RestoreType = GLOBALS::RESTORE_DC;
}
else if (CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, p, -1, TARGET_ARG_BOTH, -1) == CSTR_EQUAL)
{
global->RestoreType = GLOBALS::RESTORE_BOTH;
}
else
{
UnknownArgs = TRUE;
}
}
else
{
UnknownArgs = TRUE;
}
}
else if(argc > iIndex)
{
UnknownArgs = TRUE;
}
}
// print the banner
wprintf(global->Banner1);
wprintf(global->Banner2);
if (UnknownArgs)
{
hr = E_INVALIDARG;
PrintError(hr);
goto end;
}
if ( FALSE == global->bIgnoreSchema)
{
BOOL bSchemaVerCompat;
hr = CheckDSSchemaVersion( &bSchemaVerCompat);
if ( FAILED(hr))
{
dbgprint(L"CheckDSSchemaVersion Failed");
goto end;
}
if (FALSE == bSchemaVerCompat)
{
hr = E_FAIL;
DisplayError(global->WrongSchema);
goto end;
}
}
dbgprint(L"dbg: Choice is %d\n", global->RestoreType);
// check to see if we are on a domain controller.
hr = IsDomainController(&bIsDomain);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
if (bIsDomain == FALSE)
{
DisplayError(global->ErrorNoAD);
hr = S_OK;
goto end;
}
// Copy the domain name
hr = GetDomainFQDN(global->pDomainInfo->DomainNameDns, &(global->DomainNamingContext));
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
// check to see if we are a member of domain/enterprise admins
hr = IsAdmin(&bIsAdmin);
if (FAILED(hr))
{
goto end;
}
if (FALSE == bIsAdmin)
{
DisplayError(global->ErrorNotAdmin);
hr = S_OK;
goto end;
}
switch(global->RestoreType)
{
case GLOBALS::RESTORE_DOMAIN:
wprintf(global->DispDDP);
break;
case GLOBALS::RESTORE_DC:
wprintf(global->DispDDCP);
break;
case GLOBALS::RESTORE_BOTH:
wprintf(global->DispBoth);
break;
default:
break;
}
wprintf(global->pDomainInfo->DomainNameDns);
wprintf(L"\n");
// is he sure ?
WCHAR szFirstChar[2];
// Here the first character of the user's input is converted as a string to compare with another string
szFirstChar[1] = L'\0';
do
{
wprintf(global->ErrorContinue);
szFirstChar[0] = getwchar();
if (L'\n' != szFirstChar[0] )
{
if ( CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, global->CharYes, -1, szFirstChar, -1) != CSTR_EQUAL )
{
// The case where szFirstChar[0] is WEOF is also handled here
hr = S_OK;
goto end;
}
else
{
// Skip until carriage return character
// We do this because we do not want to take the input until the user presses carriage return
do{
szFirstChar[0] = getwchar();
}while( szFirstChar[0] != '\n' && szFirstChar[0] != WEOF);
break;
}
}
// Prompt user again if user enters only carriage return
// This case is handled by going through this while loop again
} while(TRUE);
szFirstChar[1] = '\0';
wprintf(global->WarnURA);
do
{
wprintf(global->ErrorContinue);
szFirstChar[0] = getwchar();
if (L'\n' != szFirstChar[0] )
{
if ( CompareString(LOCALE_INVARIANT, NORM_IGNORECASE, global->CharYes, -1, szFirstChar, -1) != CSTR_EQUAL )
{
hr = S_OK;
goto end;
}
else
{
do{
szFirstChar[0] = getwchar();
}while( szFirstChar[0] != '\n' && szFirstChar[0] != WEOF);
break;
}
}
} while(TRUE);
// check the state of the sysvol
// find out where the sysvol is .
netapiStatus = NetShareGetInfo(NULL, L"sysvol", 2, &pShareName);
if ( NERR_Success == netapiStatus )
{
hr = StringCchCopy(global->SysVolPath, MAX_PATH, ((SHARE_INFO_2 *) pShareName )->shi2_path);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
NetApiBufferFree(pShareName);
}
else
{
DisplayError(global->ErrorBadSysVol);
hr = HRESULT_FROM_WIN32(netapiStatus);
goto end;
}
dbgprint(L"dbg: sysvol = '%s'\n", global->SysVolPath);
//
// Get the version Number from filesystem and DS
//
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
hr = GetVersionNumber(DEFAULT_DOMAIN_POLICY);
if (FAILED(hr))
{
dbgprint(L"GetversionNo failed with error %x\n", hr);
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
hr = GetVersionNumber(DEFAULT_DOMAIN_CONTROLLER_POLICY);
if (FAILED(hr))
{
dbgprint(L"GetversionNo failed with error %x\n", hr);
goto end;
}
}
if ( global->RestoreType & GLOBALS::RESTORE_DOMAIN )
{
hr = SetDSSecurityDescriptor(DEFAULT_DOMAIN_POLICY);
if (FAILED(hr))
{
goto end;
}
}
if ( global->RestoreType & GLOBALS::RESTORE_DC )
{
hr = SetDSSecurityDescriptor(DEFAULT_DOMAIN_CONTROLLER_POLICY);
if (FAILED(hr))
{
goto end;
}
}
// clean the domains GPO
// clean the controller GPO
hr = CleanPolicyObjects();
if (FAILED(hr))
{
goto end;
}
//
// The string that TempPath will be holding will be like
// <sysvolpath>\<domain name>\policies\<guid>
// Memory is allocated for each directory name and for '\' if needed.
//
ULONG uLength = 0;
uLength = lstrlen(global->SysVolPath) + 1 + lstrlen(global->pDomainInfo->DomainNameDns) + lstrlen(L"\\Policies")
+ 1 + lstrlen(DOMAIN_GUID) + lstrlen(FILE_GPTTMPLINF)
+ lstrlen(FILE_GPTINI) + 1;
TempPath = (WCHAR*) LocalAlloc( LPTR, uLength * sizeof(WCHAR) );
if(NULL == TempPath)
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
// now we need to clean + recreate the file system sysvol files+folders
// first, delete the tree's
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
// see if we have an EFS cert to backup
hr = BackupEfsCert();
if ( FAILED(hr) )
{
goto end;
}
hr = StringCchPrintf( TempPath,
uLength,
L"%s\\%s\\Policies\\%s",
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
DOMAIN_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = DeleteTree(TempPath);
if (FAILED(hr))
{
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
hr = StringCchPrintf( TempPath,
uLength,
L"%s\\%s\\Policies\\%s",
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
DC_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = DeleteTree(TempPath);
if (FAILED(hr))
{
goto end;
}
}
// create fresh policy directory
// + put security permisions on these files + folders
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
hr = CreateSysVolDomain();
if (FAILED(hr))
{
goto end;
}
if (!global->hasEFSInfo)
{
hr = CreateEFSCerts();
if (FAILED(hr))
{
PrintError(DDP, global->CreateEFS);
PrintError(hr);
goto end;
}
}
hr = SaveEFSCerts();
if (FAILED(hr))
{
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
hr = CreateSysVolController();
if (FAILED(hr))
{
goto end;
}
}
// for some strange reason the setup helper thinks sysvol should be
// one level higher than it really is
hr = StringCchCopy(TempPath, uLength, global->SysVolPath);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
Length = lstrlen(TempPath);
do {
Length -= 1;
} while (TempPath[Length] != L'\\');
TempPath[Length] = UNICODE_NULL;
{
WCHAR* wszIgnoredGPOId = NULL;
WCHAR* wszIgnoredGPOName = NULL;
CIgnoredGPO* pIgnoredGPO = NULL;
dwError = ERROR_SUCCESS;
if ( ! ( global->RestoreType & GLOBALS::RESTORE_DOMAIN) )
{
wszIgnoredGPOId = DOMAIN_GUID;
wszIgnoredGPOName = DDP;
}
else if ( ! ( global->RestoreType & GLOBALS::RESTORE_DC) )
{
wszIgnoredGPOId = DC_GUID;
wszIgnoredGPOName = DEFAULT_DC_POLICY_NAME;
}
if ( wszIgnoredGPOId )
{
pIgnoredGPO = new CIgnoredGPO( wszIgnoredGPOId, wszIgnoredGPOName );
if ( pIgnoredGPO )
{
dwError = pIgnoredGPO->Backup();
}
else
{
dwError = ERROR_OUTOFMEMORY;
}
}
if ( ERROR_SUCCESS == dwError )
{
dwError = SceDcPromoCreateGPOsInSysvol( global->pDomainInfo->DomainNameDns,
TempPath,
0,
NULL );
if ( pIgnoredGPO )
{
DWORD RestoreError = pIgnoredGPO->Restore();
if ( ERROR_SUCCESS != RestoreError )
{
dbgprint(L"Failed to restore ignored gpo id %s with error %X\n", wszIgnoredGPOId, RestoreError );
if ( ERROR_SUCCESS == dwError )
{
dwError = RestoreError;
}
}
}
delete pIgnoredGPO;
}
}
if (dwError != 0 )
{
PrintError(dwError);
hr = HRESULT_FROM_WIN32(dwError);
dbgprint(L"SceDcPromoCreateGPOsInSysvol failed %X\n", hr);
goto end;
}
if ( global->RestoreType & GLOBALS::RESTORE_DC )
{
ULONG ulProfilePathLength;
//
// profile path + '\inf\defdcgpo' + '\0'
//
ulProfilePathLength = MAX_PATH + lstrlen(L"\\inf\\defdcgpo.inf") + 1;
szProfilePath = (WCHAR *) LocalAlloc( LPTR, sizeof(WCHAR) * ulProfilePathLength);
if ( NULL == szProfilePath )
{
hr = E_OUTOFMEMORY;
PrintError(hr);
goto end;
}
Length = GetWindowsDirectory(szProfilePath, MAX_PATH);
if (0 == Length)
{
hr = HRESULT_FROM_WIN32(dwError);
dbgprint(L"GetWindowsDirectory failed %X\n", hr);
LocalFree(szProfilePath);
goto end;
}
hr = StringCchPrintf(szProfilePath, ulProfilePathLength, L"%s\\inf\\defdcgpo.inf", szProfilePath);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
if ( FilePresent(szProfilePath) )
{
hr = StringCchPrintf(TempPath,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTTMPLINF,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
DC_GUID);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = CreateSecurityTemplate(szProfilePath, TempPath);
if (FAILED(hr))
{
hr = HRESULT_FROM_WIN32(dwError);
dbgprint(L"createSecurityTemplate failed %X\n", hr);
LocalFree(szProfilePath);
goto end;
}
}
LocalFree(szProfilePath);
}
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
hr = StringCchPrintf(TempPath,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTINI,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
DOMAIN_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = StringCchPrintf(szVersionNo,
MAX_VERSION_LENGTH,
L"%d",
global->lDDPVersionNo);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
bError = WritePrivateProfileString(L"General", L"Version", szVersionNo, TempPath);
if (bError == FALSE)
{
dwError = GetLastError();
PrintError(TempPath, global->DirWrite);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
hr = StringCchPrintf(TempPath,
uLength,
L"%s\\%s\\Policies\\%s" FILE_GPTINI,
global->SysVolPath,
global->pDomainInfo->DomainNameDns,
DC_GUID );
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
hr = StringCchPrintf(szVersionNo,
MAX_VERSION_LENGTH,
L"%d",
global->lDDCPVersionNo);
if (FAILED(hr))
{
PrintError(hr);
goto end;
}
bError = WritePrivateProfileString(L"General", L"Version", szVersionNo, TempPath);
if (bError == FALSE)
{
dwError = GetLastError();
PrintError(TempPath, global->DirWrite);
hr = HRESULT_FROM_WIN32(dwError);
goto end;
}
}
if (global->RestoreType & GLOBALS::RESTORE_DOMAIN)
{
wprintf(global->DDPSuccess);
}
if (global->RestoreType & GLOBALS::RESTORE_DC)
{
wprintf(global->DDCPSuccess);
}
hr = S_OK;
end:
if(TempPath != NULL)
{
LocalFree(TempPath);
}
if (Key != NULL)
{
RegCloseKey(Key);
Key = NULL;
}
if (FAILED(hr))
{
wprintf(global->ToolFailed);
}
if (global->pGPO)
{
global->pGPO->Release();
}
CoUninitialize();
return hr;
} // wmain