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.
 
 
 
 
 
 

6131 lines
158 KiB

#include "main.h"
#include <schemamanager.h>
#include "rsoputil.h"
#include <initguid.h>
#include "sddl.h"
#define PCOMMON_IMPL
#include "pcommon.h"
#include <adsopenflags.h>
typedef struct _GPOERRORINFO
{
DWORD dwError;
LPTSTR lpMsg;
} GPOERRORINFO, *LPGPOERRORINFO;
typedef struct _DCOPTION
{
LPTSTR lpDomainName;
INT iOption;
struct _DCOPTION *pNext;
} DCOPTION, *LPDCOPTION;
LPDCOPTION g_DCInfo = NULL;
//
// Help ids
//
DWORD aErrorHelpIds[] =
{
0, 0
};
DWORD aNoDCHelpIds[] =
{
IDC_NODC_PDC, IDH_DC_PDC,
IDC_NODC_INHERIT, IDH_DC_INHERIT,
IDC_NODC_ANYDC, IDH_DC_ANYDC,
0, 0
};
DEFINE_GUID(CLSID_WMIFilterManager,0xD86A8E9B,0xF53F,0x45AD,0x8C,0x49,0x0A,0x0A,0x52,0x30,0xDE,0x28);
DEFINE_GUID(IID_IWMIFilterManager,0x64DCCA00,0x14A6,0x473C,0x90,0x06,0x5A,0xB7,0x9D,0xC6,0x84,0x91);
//*************************************************************
//
// SetWaitCursor()
//
// Purpose: Sets the wait cursor
//
// Parameters: none
//
//
// Return: void
//
//*************************************************************
void SetWaitCursor (void)
{
SetCursor (LoadCursor(NULL, IDC_WAIT));
}
//*************************************************************
//
// ClearWaitCursor()
//
// Purpose: Resets the wait cursor
//
// Parameters: none
//
//
// Return: void
//
//*************************************************************
void ClearWaitCursor (void)
{
SetCursor (LoadCursor(NULL, IDC_ARROW));
}
//*************************************************************
//
// CheckSlash()
//
// Purpose: Checks for an ending slash and adds one if
// it is missing.
//
// Parameters: lpDir - directory
//
// Return: Pointer to the end of the string
//
// Comments:
//
// History: Date Author Comment
// 6/19/95 ericflo Created
//
//*************************************************************
LPTSTR CheckSlash (LPTSTR lpDir)
{
LPTSTR lpEnd;
lpEnd = lpDir + lstrlen(lpDir);
if (*(lpEnd - 1) != TEXT('\\')) {
*lpEnd = TEXT('\\');
lpEnd++;
*lpEnd = TEXT('\0');
}
return lpEnd;
}
//*************************************************************
//
// CreateNestedDirectory()
//
// Purpose: Creates a subdirectory and all it's parents
// if necessary.
//
// Parameters: lpDirectory - Directory name
// lpSecurityAttributes - Security Attributes
//
// Return: > 0 if successful
// 0 if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/08/95 ericflo Created
//
//*************************************************************
UINT CreateNestedDirectory(LPCTSTR lpDirectory, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
{
TCHAR* szDirectory;
LPTSTR lpEnd;
UINT uStatus;
szDirectory = NULL;
//
// Note that this function seems to return 0, 1, and ERROR_ALREADY_EXISTS
// 0 is for failure, 1 is for success, and ERROR_ALREADY_EXISTS is for the
// case that the directory already exists. We should probably just return
// the success code in that case and have an extra parameter for disposition
// or use last error, but current code seems to expect this strange behavior
//
// We initialize to the failure value below
//
uStatus = 0;
//
// Check for NULL pointer
//
if (!lpDirectory || !(*lpDirectory)) {
DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer.")));
goto CreateNestedDirectory_Exit;
}
//
// First, see if we can create the directory without having
// to build parent directories.
//
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) {
uStatus = 1;
goto CreateNestedDirectory_Exit;
}
//
// If this directory exists already, this is OK too.
//
if (GetLastError() == ERROR_ALREADY_EXISTS) {
uStatus = ERROR_ALREADY_EXISTS;
goto CreateNestedDirectory_Exit;
}
//
// No luck, copy the string to a buffer we can munge
//
HRESULT hr;
ULONG ulNoChars;
ulNoChars = lstrlen(lpDirectory) + 1;
szDirectory = (TCHAR*) LocalAlloc( LPTR, ulNoChars * sizeof(*szDirectory) );
if ( ! szDirectory )
{
DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Failed to allocate memory.")));
goto CreateNestedDirectory_Exit;
}
hr = StringCchCopy (szDirectory, ulNoChars, lpDirectory);
ASSERT(SUCCEEDED(hr));
//
// Find the first subdirectory name
//
lpEnd = szDirectory;
if (szDirectory[1] == TEXT(':')) {
lpEnd += 3;
} else if (szDirectory[1] == TEXT('\\')) {
//
// Skip the first two slashes
//
lpEnd += 2;
//
// Find the slash between the server name and
// the share name.
//
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
goto CreateNestedDirectory_Exit;
}
//
// Skip the slash, and find the slash between
// the share name and the directory name.
//
lpEnd++;
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (!(*lpEnd)) {
goto CreateNestedDirectory_Exit;
}
//
// Leave pointer at the beginning of the directory.
//
lpEnd++;
} else if (szDirectory[0] == TEXT('\\')) {
lpEnd++;
}
while (*lpEnd) {
while (*lpEnd && *lpEnd != TEXT('\\')) {
lpEnd++;
}
if (*lpEnd == TEXT('\\')) {
*lpEnd = TEXT('\0');
if (!CreateDirectory (szDirectory, NULL)) {
if (GetLastError() != ERROR_ALREADY_EXISTS) {
DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: CreateDirectory failed for %s with %d."),
szDirectory, GetLastError()));
goto CreateNestedDirectory_Exit;
}
}
*lpEnd = TEXT('\\');
lpEnd++;
}
}
//
// Create the final directory
//
if (CreateDirectory (szDirectory, lpSecurityAttributes)) {
uStatus = 1;
goto CreateNestedDirectory_Exit;
}
if (GetLastError() == ERROR_ALREADY_EXISTS) {
uStatus = ERROR_ALREADY_EXISTS;
}
//
// Failed
//
DebugMsg((DM_VERBOSE, TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
CreateNestedDirectory_Exit:
if ( szDirectory )
{
LocalFree( szDirectory );
}
return uStatus;
}
VOID LoadMessage (DWORD dwID, LPTSTR lpBuffer, DWORD dwSize)
{
HINSTANCE hInstActiveDS;
HINSTANCE hInstWMI;
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
hInstActiveDS = LoadLibrary (TEXT("activeds.dll"));
if (hInstActiveDS)
{
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
hInstActiveDS, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
hInstWMI = LoadLibrary (TEXT("wmiutils.dll"));
if (hInstWMI)
{
if (!FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
hInstWMI, dwID,
MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
lpBuffer, dwSize, NULL))
{
DebugMsg((DM_WARNING, TEXT("LoadMessage: Failed to query error message text for %d due to error %d"),
dwID, GetLastError()));
(void) StringCchPrintf (lpBuffer, dwSize, TEXT("%d (0x%x)"), dwID, dwID);
}
FreeLibrary (hInstWMI);
}
}
FreeLibrary (hInstActiveDS);
}
}
}
//*************************************************************
//
// ErrorDlgProc()
//
// Purpose: Dialog box procedure for errors
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
INT_PTR CALLBACK ErrorDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
TCHAR szError[MAX_PATH];
LPGPOERRORINFO lpEI = (LPGPOERRORINFO) lParam;
HICON hIcon;
hIcon = LoadIcon (NULL, IDI_WARNING);
if (hIcon)
{
SendDlgItemMessage (hDlg, IDC_ERROR_ICON, STM_SETICON, (WPARAM)hIcon, 0);
}
SetDlgItemText (hDlg, IDC_ERRORTEXT, lpEI->lpMsg);
szError[0] = TEXT('\0');
if (lpEI->dwError)
{
LoadMessage (lpEI->dwError, szError, ARRAYSIZE(szError));
}
if (szError[0] == TEXT('\0'))
{
LoadString (g_hInstance, IDS_NONE, szError, ARRAYSIZE(szError));
}
SetDlgItemText (hDlg, IDC_DETAILSTEXT, szError);
return TRUE;
}
case WM_COMMAND:
if (LOWORD(wParam) == IDCLOSE || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, TRUE);
return TRUE;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aErrorHelpIds);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aErrorHelpIds);
return (TRUE);
}
return FALSE;
}
//*************************************************************
//
// ReportError()
//
// Purpose: Displays an error message to the user
//
// Parameters: hParent - Parent window handle
// dwError - Error number
// idMsg - Error message id
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 7/18/95 ericflo Created
//
//*************************************************************
BOOL ReportError (HWND hParent, DWORD dwError, UINT idMsg, ...)
{
GPOERRORINFO ei;
TCHAR szMsg[2*MAX_PATH];
TCHAR szErrorMsg[2*MAX_PATH+40];
va_list marker;
//
// Load the error message
//
if (!LoadString (g_hInstance, idMsg, szMsg, 2*MAX_PATH))
{
return FALSE;
}
//
// Special case access denied errors with a custom message
//
if ((dwError == ERROR_ACCESS_DENIED) || (dwError == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED)))
{
if ((idMsg != IDS_EXECFAILED_USER) && (idMsg != IDS_EXECFAILED_COMPUTER) &&
(idMsg != IDS_EXECFAILED) && (idMsg != IDS_EXECFAILED_BOTH))
{
if (!LoadString (g_hInstance, IDS_ACCESSDENIED, szMsg, 2*MAX_PATH))
{
return FALSE;
}
}
}
else if ( dwError == WBEM_E_INVALID_NAMESPACE )
{
if (!LoadString (g_hInstance, IDS_INVALID_NAMESPACE, szMsg, 2*MAX_PATH))
{
return FALSE;
}
}
//
// Plug in the arguments
//
va_start(marker, idMsg);
wvnsprintf(szErrorMsg, sizeof(szErrorMsg) / sizeof(TCHAR) - 1, szMsg, marker);
va_end(marker);
//
// Display the message
//
ei.dwError = dwError;
ei.lpMsg = szErrorMsg;
DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_ERROR), hParent,
ErrorDlgProc, (LPARAM) &ei);
return TRUE;
}
//*************************************************************
//
// Delnode_Recurse()
//
// Purpose: Recursive delete function for Delnode
//
// Parameters: lpDir - Directory
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 8/10/95 ericflo Created
//
//*************************************************************
BOOL Delnode_Recurse (LPTSTR lpDir)
{
WIN32_FIND_DATA fd;
HANDLE hFile;
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Entering, lpDir = <%s>"), lpDir));
//
// Setup the current working dir
//
if (!SetCurrentDirectory (lpDir)) {
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to set current working directory. Error = %d"), GetLastError()));
return FALSE;
}
//
// Find the first file
//
hFile = FindFirstFile(TEXT("*.*"), &fd);
if (hFile == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
return TRUE;
} else {
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: FindFirstFile failed. Error = %d"),
GetLastError()));
return FALSE;
}
}
do {
//
// Verbose output
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: FindFile found: <%s>"),
fd.cFileName));
//
// Check for "." and ".."
//
if (!lstrcmpi(fd.cFileName, TEXT("."))) {
continue;
}
if (!lstrcmpi(fd.cFileName, TEXT(".."))) {
continue;
}
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
//
// Found a directory.
//
if (!Delnode_Recurse(fd.cFileName)) {
FindClose(hFile);
return FALSE;
}
if (fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
fd.dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
SetFileAttributes (fd.cFileName, fd.dwFileAttributes);
}
if (!RemoveDirectory (fd.cFileName)) {
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete directory <%s>. Error = %d"),
fd.cFileName, GetLastError()));
}
} else {
//
// We found a file. Set the file attributes,
// and try to delete it.
//
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)) {
SetFileAttributes (fd.cFileName, FILE_ATTRIBUTE_NORMAL);
}
if (!DeleteFile (fd.cFileName)) {
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to delete <%s>. Error = %d"),
fd.cFileName, GetLastError()));
}
}
//
// Find the next entry
//
} while (FindNextFile(hFile, &fd));
//
// Close the search handle
//
FindClose(hFile);
//
// Reset the working directory
//
if (!SetCurrentDirectory (TEXT(".."))) {
DebugMsg((DM_WARNING, TEXT("Delnode_Recurse: Failed to reset current working directory. Error = %d"), GetLastError()));
return FALSE;
}
//
// Success.
//
DebugMsg((DM_VERBOSE, TEXT("Delnode_Recurse: Leaving <%s>"), lpDir));
return TRUE;
}
//*************************************************************
//
// Delnode()
//
// Purpose: Recursive function that deletes files and
// directories.
//
// Parameters: lpDir - Directory
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 6/23/95 ericflo Created
//
//*************************************************************
BOOL Delnode (LPTSTR lpDir)
{
TCHAR szCurWorkingDir[MAX_PATH];
if (GetCurrentDirectory(MAX_PATH, szCurWorkingDir)) {
Delnode_Recurse (lpDir);
SetCurrentDirectory (szCurWorkingDir);
if (!RemoveDirectory (lpDir)) {
DebugMsg((DM_VERBOSE, TEXT("Delnode: Failed to delete directory <%s>. Error = %d"),
lpDir, GetLastError()));
return FALSE;
}
} else {
DebugMsg((DM_WARNING, TEXT("Delnode: Failed to get current working directory. Error = %d"), GetLastError()));
return FALSE;
}
return TRUE;
}
/*******************************************************************
NAME: StringToNum
SYNOPSIS: Converts string value to numeric value
NOTES: Calls atoi() to do conversion, but first checks
for non-numeric characters
EXIT: Returns TRUE if successful, FALSE if invalid
(non-numeric) characters
********************************************************************/
BOOL StringToNum(TCHAR *pszStr,UINT * pnVal)
{
TCHAR *pTst = pszStr;
if (!pszStr) return FALSE;
// verify that all characters are numbers
while (*pTst)
{
if (!(*pTst >= TEXT('0') && *pTst <= TEXT('9')))
{
if (*pTst != TEXT('-'))
return FALSE;
}
pTst = CharNext(pTst);
}
*pnVal = _ttoi(pszStr);
return TRUE;
}
//*************************************************************
//
// DSDelnodeRecurse()
//
// Purpose: Delnodes a tree in the DS
//
// Parameters: pADsContainer - IADSContainer interface
//
// Return: S_OK if successful
//
//*************************************************************
HRESULT DSDelnodeRecurse (IADsContainer * pADsContainer)
{
HRESULT hr;
BSTR bstrRelativeName;
BSTR bstrClassName;
IEnumVARIANT *pVar = NULL;
IADsContainer * pADsChild = NULL;
IADs * pDSObject = NULL;
IDispatch * pDispatch;
VARIANT var;
ULONG ulResult;
//
// Enumerate the children and delete them first
//
hr = ADsBuildEnumerator (pADsContainer, &pVar);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed to get enumerator with 0x%x"), hr));
goto Exit;
}
while (TRUE)
{
VariantInit(&var);
hr = ADsEnumerateNext(pVar, 1, &var, &ulResult);
if (FAILED(hr))
{
DebugMsg((DM_VERBOSE, TEXT("DSDelnodeRecurse: Failed to enumerator with 0x%x"), hr));
VariantClear (&var);
break;
}
if (S_FALSE == hr)
{
VariantClear (&var);
break;
}
//
// If var.vt isn't VT_DISPATCH, we're finished.
//
if (var.vt != VT_DISPATCH)
{
VariantClear (&var);
break;
}
//
// We found something, get the IDispatch interface
//
pDispatch = var.pdispVal;
if (!pDispatch)
{
VariantClear (&var);
goto Exit;
}
//
// Now query for the IADsContainer interface so we can recurse
// if necessary. Note it is ok if this fails because not
// everything is a container.
//
hr = pDispatch->QueryInterface(IID_IADsContainer, (LPVOID *)&pADsChild);
if (SUCCEEDED(hr)) {
hr = DSDelnodeRecurse (pADsChild);
if (FAILED(hr)) {
goto Exit;
}
pADsChild->Release();
}
//
// Now query for the IADs interface so we can get some
// properties from this object
//
hr = pDispatch->QueryInterface(IID_IADs, (LPVOID *)&pDSObject);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("AddGPOsForDomain: QI for IADs failed with 0x%x"), hr));
VariantClear (&var);
goto Exit;
}
//
// Get the relative and class names
//
hr = pDSObject->get_Name (&bstrRelativeName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed get relative name with 0x%x"), hr));
pDSObject->Release();
VariantClear (&var);
goto Exit;
}
hr = pDSObject->get_Class (&bstrClassName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed get class name with 0x%x"), hr));
SysFreeString (bstrRelativeName);
pDSObject->Release();
VariantClear (&var);
goto Exit;
}
pDSObject->Release();
//
// Delete the object
//
hr = pADsContainer->Delete (bstrClassName,
bstrRelativeName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnodeRecurse: Failed to delete object with 0x%x"), hr));
SysFreeString (bstrRelativeName);
SysFreeString (bstrClassName);
VariantClear (&var);
goto Exit;
}
SysFreeString (bstrRelativeName);
SysFreeString (bstrClassName);
VariantClear (&var);
}
Exit:
if (pVar)
{
ADsFreeEnumerator (pVar);
}
return hr;
}
//*************************************************************
//
// DSDelnodeRecurse()
//
// Purpose: Delnodes a tree in the DS
//
// Parameters: lpDSPath - Path of DS object to delete
//
// Return: S_OK if successful
//
//*************************************************************
HRESULT DSDelnode (LPTSTR lpDSPath)
{
HRESULT hr;
BSTR bstrParent = NULL;
BSTR bstrRelativeName = NULL;
BSTR bstrClassName = NULL;
IADsContainer * pADsContainer = NULL;
IADs * pDSObject = NULL;
VARIANT var;
ULONG ulResult;
//
// Enumerate the children and delete them first
//
hr = OpenDSObject(lpDSPath, IID_IADsContainer, (void **)&pADsContainer);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to get gpo container interface with 0x%x"), hr));
goto Exit;
}
hr = DSDelnodeRecurse (pADsContainer);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to delete children with 0x%x"), hr));
goto Exit;
}
pADsContainer->Release();
pADsContainer = NULL;
//
// Bind to the object
//
hr = OpenDSObject (lpDSPath, IID_IADs, (void **)&pDSObject);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed bind to the object %s with 0x%x"),
lpDSPath, hr));
goto Exit;
}
//
// Get the parent's name
//
hr = pDSObject->get_Parent (&bstrParent);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get parent's name with 0x%x"), hr));
goto Exit;
}
//
// Get this object's relative and class names
//
hr = pDSObject->get_Name (&bstrRelativeName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get relative name with 0x%x"), hr));
goto Exit;
}
hr = pDSObject->get_Class (&bstrClassName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed get class name with 0x%x"), hr));
goto Exit;
}
pDSObject->Release();
pDSObject = NULL;
//
// Bind to the parent object
//
hr = OpenDSObject(bstrParent, IID_IADsContainer, (void **)&pADsContainer);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to get parent container interface with 0x%x"), hr));
goto Exit;
}
//
// Delete the object
//
hr = pADsContainer->Delete (bstrClassName,
bstrRelativeName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("DSDelnode: Failed to delete object with 0x%x"), hr));
goto Exit;
}
Exit:
if (pADsContainer)
{
pADsContainer->Release();
}
if (pDSObject)
{
pDSObject->Release();
}
if (bstrParent)
{
SysFreeString (bstrParent);
}
if (bstrRelativeName)
{
SysFreeString (bstrRelativeName);
}
if (bstrClassName)
{
SysFreeString (bstrClassName);
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: CreateGPOLink
//
// Synopsis: Creates a GPO link for a domain, site or OU
//
// Arguments: [lpGPO] - LDAP path to the GPO
// [lpContainer] - LDAP path to the container object
// [fHighPriority] - FALSE (default) - adds GPO to the bottom
// of the prioritized list
// TRUE - adds GPO to the top of the list
//
// Returns: S_OK on success
//
// History: 5-08-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT CreateGPOLink(LPOLESTR lpGPO, LPOLESTR lpContainer, BOOL fHighPriority)
{
IADs * pADs = NULL;
LPTSTR lpNamelessGPO;
HRESULT hr;
lpNamelessGPO = MakeNamelessPath (lpGPO);
if (lpNamelessGPO)
{
hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
if (SUCCEEDED(hr))
{
VARIANT var;
BSTR bstr = NULL;
ULONG ulNoChars = 1 + wcslen(lpNamelessGPO) + 3 + 1;
LPOLESTR szLink = new OLECHAR[ulNoChars];
if (szLink)
{
hr = StringCchCopy(szLink, ulNoChars, L"[");
if (SUCCEEDED(hr))
{
hr = StringCchCat(szLink, ulNoChars, lpNamelessGPO);
}
if (SUCCEEDED(hr))
{
hr = StringCchCat(szLink, ulNoChars, L";0]");
}
if (SUCCEEDED(hr))
{
VariantInit(&var);
bstr = SysAllocString(GPM_LINK_PROPERTY);
if (bstr)
{
hr = pADs->Get(bstr, &var);
if (SUCCEEDED(hr))
{
ulNoChars = wcslen(var.bstrVal) + wcslen(szLink) + 1;
LPOLESTR szTemp = new OLECHAR[ulNoChars];
if (szTemp)
{
if (fHighPriority)
{
// Highest priority is at the END of the list
hr = StringCchCopy(szTemp, ulNoChars, var.bstrVal);
ASSERT(SUCCEEDED(hr));
hr = StringCchCat(szTemp, ulNoChars, szLink);
ASSERT(SUCCEEDED(hr));
}
else
{
hr = StringCchCopy(szTemp, ulNoChars, szLink);
ASSERT(SUCCEEDED(hr));
hr = StringCchCat(szTemp, ulNoChars, var.bstrVal);
ASSERT(SUCCEEDED(hr));
}
delete [] szLink;
szLink = szTemp;
}
else
{
hr = ERROR_OUTOFMEMORY;
goto Cleanup;
}
}
else
{
if (hr != E_ADS_PROPERTY_NOT_FOUND)
{
goto Cleanup;
}
}
}
else
{
hr = ERROR_OUTOFMEMORY;
goto Cleanup;
}
VariantClear(&var);
VariantInit(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(szLink);
if (var.bstrVal)
{
hr = pADs->Put(bstr, var);
if (SUCCEEDED(hr))
{
hr = pADs->SetInfo();
}
}
else
{
hr = ERROR_OUTOFMEMORY;
}
Cleanup:
VariantClear(&var);
if (bstr)
{
SysFreeString(bstr);
}
}
delete [] szLink;
}
else
hr = ERROR_OUTOFMEMORY;
pADs->Release();
}
LocalFree (lpNamelessGPO);
}
else
{
hr = ERROR_OUTOFMEMORY;
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: DeleteAllGPOLinks
//
// Synopsis: Deletes all GPO links for a domain, OU or site
//
// Arguments: [lpContainer] - LDAP to the container object
//
// Returns: S_OK on success
//
// History: 5-08-1998 stevebl Created
//
//---------------------------------------------------------------------------
HRESULT DeleteAllGPOLinks(LPOLESTR lpContainer)
{
IADs * pADs = NULL;
HRESULT hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
if (SUCCEEDED(hr))
{
VARIANT var;
BSTR bstr;
bstr = SysAllocString(GPM_LINK_PROPERTY);
if (bstr)
{
VariantInit(&var);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(L" ");
if (var.bstrVal)
{
hr = pADs->Put(bstr, var);
if (SUCCEEDED(hr))
{
pADs->SetInfo();
}
}
else
{
hr = ERROR_OUTOFMEMORY;
}
VariantClear(&var);
SysFreeString(bstr);
}
else
{
hr = ERROR_OUTOFMEMORY;
}
pADs->Release();
}
return hr;
}
//+--------------------------------------------------------------------------
//
// Function: DeleteGPOLink
//
// Synopsis: Deletes a GPO link from a domain, OU or site
// (if there is one).
//
// Arguments: [lpGPO] - LDAP to the GPO
// [lpContainer] - LDAP to the container object
//
// Returns: S_OK - success
//
// History: 5-08-1998 stevebl Created
//
// Notes: If a GPO is linked more than once, this will remove
// only the first link.
//
// If a GPO is NOT linked with this object, then this
// routine will still return S_OK.
//
//---------------------------------------------------------------------------
HRESULT DeleteGPOLink(LPOLESTR lpGPO, LPOLESTR lpContainer)
{
IADs * pADs = NULL;
HRESULT hr = OpenDSObject(lpContainer, IID_IADs, (void **)&pADs);
if (SUCCEEDED(hr))
{
VARIANT var;
BSTR bstr;
ULONG ulNoChars;
// Build the substring to look for.
// This is the first part of the link, the link ends with ]
ulNoChars = 1 + wcslen(lpGPO) + 1;
LPOLESTR szLink = new OLECHAR[ulNoChars];
if (szLink)
{
hr = StringCchCopy(szLink, ulNoChars, L"[");
ASSERT(SUCCEEDED(hr));
hr = StringCchCat(szLink, ulNoChars, lpGPO);
ASSERT(SUCCEEDED(hr));
bstr = SysAllocString(GPM_LINK_PROPERTY);
if (bstr)
{
VariantInit(&var);
hr = pADs->Get(bstr, &var);
if (SUCCEEDED(hr))
{
// find the link and remove it
ulNoChars = wcslen(var.bstrVal)+1;
LPOLESTR sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, var.bstrVal);
ASSERT(SUCCEEDED(hr));
OLECHAR * pch = wcsstr(sz, szLink);
if (pch)
{
OLECHAR * pchEnd = pch;
// look for the ']'
while (*pchEnd && (*pchEnd != L']'))
pchEnd++;
// skip it
if (*pchEnd)
pchEnd++;
// copy over the rest of the string
while (*pchEnd)
*pch++ = *pchEnd++;
*pch = L'\0';
VariantClear(&var);
VariantInit(&var);
var.vt = VT_BSTR;
if (wcslen(sz))
{
var.bstrVal = SysAllocString(sz);
}
else
{
// Put will gag if this is an empty string
// so we need to put a space here if we've
// deleted all the entries.
var.bstrVal = SysAllocString(L" ");
}
if (var.bstrVal)
{
// set the link property again
hr = pADs->Put(bstr, var);
if (SUCCEEDED(hr))
{
hr = pADs->SetInfo();
}
}
else
{
hr = ERROR_OUTOFMEMORY;
}
}
delete [] sz;
}
else
{
hr = ERROR_OUTOFMEMORY;
}
}
VariantClear(&var);
SysFreeString(bstr);
}
else
{
hr = ERROR_OUTOFMEMORY;
}
delete [] szLink;
}
else
hr = ERROR_OUTOFMEMORY;
pADs->Release();
}
return hr;
}
//*************************************************************
//
// CreateSecureDirectory()
//
// Purpose: Creates a secure directory that only domain admins
// and the OS have read / write access. Everyone else has
// read access only.
//
// Parameters: lpDirectory - Directory name
//
// Return: > 0 if successful
// 0 if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 5/28/98 ericflo Created
//
//*************************************************************
UINT CreateSecureDirectory (LPTSTR lpDirectory)
{
SECURITY_DESCRIPTOR sd;
SECURITY_ATTRIBUTES sa;
SID_IDENTIFIER_AUTHORITY authNT = SECURITY_NT_AUTHORITY;
PACL pAcl = NULL;
PSID psidSystem = NULL, psidAdmin = NULL, psidAuthUsers = NULL;
DWORD cbAcl, aceIndex;
ACE_HEADER * lpAceHeader;
UINT uRet = 0;
//
// Get the system sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_LOCAL_SYSTEM_RID,
0, 0, 0, 0, 0, 0, 0, &psidSystem)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize system sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Get the Admin sid
//
if (!AllocateAndInitializeSid(&authNT, 2, SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS, 0, 0,
0, 0, 0, 0, &psidAdmin)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize admin sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Get the authenticated users sid
//
if (!AllocateAndInitializeSid(&authNT, 1, SECURITY_AUTHENTICATED_USER_RID,
0, 0, 0, 0, 0, 0, 0, &psidAuthUsers)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize world sid. Error = %d"), GetLastError()));
goto Exit;
}
//
// Allocate space for the ACL
//
cbAcl = (2 * GetLengthSid (psidAuthUsers)) + (2 * GetLengthSid (psidSystem)) +
(2 * GetLengthSid (psidAdmin)) + sizeof(ACL) +
(6 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)));
pAcl = (PACL) GlobalAlloc(GMEM_FIXED, cbAcl);
if (!pAcl) {
goto Exit;
}
if (!InitializeAcl(pAcl, cbAcl, ACL_REVISION)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize acl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add Aces. Non-inheritable ACEs first
//
aceIndex = 0;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidSystem)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, FILE_ALL_ACCESS, psidAdmin)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidAuthUsers)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
//
// Now the inheritable ACEs
//
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidSystem)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, psidAdmin)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
aceIndex++;
if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_READ | GENERIC_EXECUTE, psidAuthUsers)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to add ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
if (!GetAce(pAcl, aceIndex, (LPVOID *)&lpAceHeader)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to get ace (%d). Error = %d"), aceIndex, GetLastError()));
goto Exit;
}
lpAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
//
// Put together the security descriptor
//
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to initialize security descriptor. Error = %d"), GetLastError()));
goto Exit;
}
if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) {
DebugMsg((DM_WARNING, TEXT("CreateSecureDirectory: Failed to set security descriptor dacl. Error = %d"), GetLastError()));
goto Exit;
}
//
// Add the security descriptor to the sa structure
//
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
//
// Attempt to create the directory
//
uRet = CreateNestedDirectory(lpDirectory, &sa);
if ( uRet ) {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Created the directory <%s>"), lpDirectory));
} else {
DebugMsg((DM_VERBOSE, TEXT("CreateSecureDirectory: Failed to created the directory <%s>"), lpDirectory));
}
Exit:
if (psidSystem) {
FreeSid(psidSystem);
}
if (psidAdmin) {
FreeSid(psidAdmin);
}
if (psidAuthUsers) {
FreeSid(psidAuthUsers);
}
if (pAcl) {
GlobalFree (pAcl);
}
return uRet;
}
//*************************************************************
//
// ConvertToDotStyle()
//
// Purpose: Converts an LDAP path to a DN path
//
// Parameters: lpName - LDAP name
// lpResult - pointer to a buffer with the DN name
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
HRESULT ConvertToDotStyle (LPOLESTR lpName, LPOLESTR *lpResult)
{
LPTSTR lpNewName;
LPTSTR lpSrc, lpDest;
TCHAR lpProvider[] = TEXT("LDAP://");
DWORD dwStrLen = lstrlen (lpProvider);
lpNewName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpName) + 1) * sizeof(TCHAR));
if (!lpNewName)
{
DebugMsg((DM_WARNING, TEXT("ConvertToDotStyle: Failed to allocate memory with 0x%x"),
GetLastError()));
return E_FAIL;
}
lpSrc = lpName;
lpDest = lpNewName;
LPTSTR lpStopChecking = (lstrlen(lpSrc) - 2) + lpSrc;
//
// Skip the LDAP:// if found
//
if (CompareString (LOCALE_USER_DEFAULT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpProvider, dwStrLen, lpSrc, dwStrLen) == CSTR_EQUAL)
{
lpSrc += dwStrLen;
}
//
// Parse through the name replacing all the XX= with .
// Skip server name (if any)
//
BOOL fMightFindServer = TRUE;
while (*lpSrc)
{
if (lpSrc < lpStopChecking)
{
if (*(lpSrc+2) == TEXT('='))
{
lpSrc += 3;
// no need to look for a server name any more because we've found an XX= string
fMightFindServer = FALSE;
}
}
while (*lpSrc && (*lpSrc != TEXT(',')))
{
*lpDest++ = *lpSrc++;
if (fMightFindServer && TEXT('/') == *(lpSrc-1))
{
// Found a server name
// reset lpDest so the rest gets put in the front of the buffer (leaving off the server name)
lpDest = lpNewName;
break;
}
}
fMightFindServer = FALSE; // don't check any more
if (*lpSrc == TEXT(','))
{
*lpDest++ = TEXT('.');
lpSrc++;
}
}
*lpDest = 0;
*lpResult = lpNewName;
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Function: GetDomainFromLDAPPath
//
// Synopsis: returns a freshly allocated string containing the LDAP path
// to the domain name contained with an arbitrary LDAP path.
//
// Arguments: [szIn] - LDAP path to the initial object
//
// Returns: NULL - if no domain could be found or if OOM
//
// History: 5-06-1998 stevebl Created
// 10-20-1998 stevebl modified to preserve server names
//
// Notes: This routine works by repeatedly removing leaf elements from
// the LDAP path until an element with the "DC=" prefix is
// found, indicating that a domain name has been located. If a
// path is given that is not rooted in a domain (is that even
// possible?) then NULL would be returned.
//
// The caller must free this path using the standard c++ delete
// operation. (I/E this isn't an exportable function.)
//
//---------------------------------------------------------------------------
LPOLESTR GetDomainFromLDAPPath(LPOLESTR szIn)
{
LPOLESTR sz = NULL;
IADsPathname * pADsPathname = NULL;
HRESULT hr = CoCreateInstance(CLSID_Pathname,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsPathname,
(LPVOID*)&pADsPathname);
if (SUCCEEDED(hr))
{
BSTR bstrIn = SysAllocString( szIn );
if ( bstrIn != NULL )
{
hr = pADsPathname->Set(bstrIn, ADS_SETTYPE_FULL);
if (SUCCEEDED(hr))
{
BSTR bstr;
BOOL fStop = FALSE;
while (!fStop)
{
hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
if (SUCCEEDED(hr))
{
// keep peeling them off until we find something
// that is a domain name
fStop = (0 == _wcsnicmp(L"DC=", bstr, 3));
SysFreeString(bstr);
}
else
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
}
if (!fStop)
{
hr = pADsPathname->RemoveLeafElement();
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to remove leaf with 0x%x."), hr));
fStop = TRUE;
}
}
}
hr = pADsPathname->Retrieve(ADS_FORMAT_X500, &bstr);
if (SUCCEEDED(hr))
{
ULONG ulNoChars = wcslen(bstr)+1;
sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, bstr);
ASSERT(SUCCEEDED(hr));
}
SysFreeString(bstr);
}
else
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve full path with 0x%x."), hr));
}
}
else
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr));
}
SysFreeString( bstrIn );
}
else
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to allocate BSTR memory.")));
}
pADsPathname->Release();
}
else
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
}
return sz;
}
//+--------------------------------------------------------------------------
//
// Function: GetContainerFromLDAPPath
//
// Synopsis: returns a the container name from an LDAP path
//
// Arguments: [szIn] - LDAP path to the initial object
//
// Returns: NULL - if no domain could be found or if OOM
//
// History: 3-17-2000 ericflo Created
//
// The caller must free this path using the standard c++ delete
// operation. (I/E this isn't an exportable function.)
//
//---------------------------------------------------------------------------
LPOLESTR GetContainerFromLDAPPath(LPOLESTR szIn)
{
LPOLESTR sz = NULL;
IADsPathname * pADsPathname = NULL;
HRESULT hr = CoCreateInstance(CLSID_Pathname,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsPathname,
(LPVOID*)&pADsPathname);
if (SUCCEEDED(hr))
{
BSTR bstrIn = SysAllocString( szIn );
if ( bstrIn != NULL )
{
hr = pADsPathname->put_EscapedMode(ADS_ESCAPEDMODE_OFF);
if (SUCCEEDED(hr))
{
hr = pADsPathname->Set(bstrIn, ADS_SETTYPE_DN);
if (SUCCEEDED(hr))
{
hr = pADsPathname->put_EscapedMode(ADS_ESCAPEDMODE_OFF_EX);
if (SUCCEEDED(hr))
{
BSTR bstr;
BOOL fStop = FALSE;
hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr);
if (SUCCEEDED(hr))
{
ULONG ulNoChars = wcslen(bstr)+1;
sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, (bstr+3));
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to copy leaf name with 0x%x."), hr));
delete [] sz;
sz = NULL;
}
}
SysFreeString(bstr);
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr));
}
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to put escape mode with 0x%x."), hr));
}
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to set pathname with 0x%x."), hr));
}
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to put escape mode with 0x%x."), hr));
}
SysFreeString( bstrIn );
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to allocate BSTR memory.")));
}
pADsPathname->Release();
}
else
{
DebugMsg((DM_WARNING, TEXT("GetContainerFromLDAPPath: Failed to CoCreateInstance for IID_IADsPathname with 0x%x."), hr));
}
return sz;
}
//*************************************************************
//
// DCDlgProc()
//
// Purpose: Dialog box procedure for DC selection
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
INT_PTR CALLBACK DCDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_INITDIALOG:
{
TCHAR szTitle[100];
TCHAR szBuffer[350];
LPDCSELINFO lpSelInfo = (LPDCSELINFO) lParam;
HICON hIcon;
if (lpSelInfo->bError)
{
hIcon = LoadIcon (NULL, IDI_ERROR);
if (hIcon)
{
SendDlgItemMessage (hDlg, IDC_NODC_ERROR, STM_SETICON, (WPARAM)hIcon, 0);
}
LoadString (g_hInstance, IDS_NODC_ERROR_TEXT, szBuffer, ARRAYSIZE(szBuffer));
SetDlgItemText (hDlg, IDC_NODC_TEXT, szBuffer);
LoadString (g_hInstance, IDS_NODC_ERROR_TITLE, szTitle, ARRAYSIZE(szTitle));
(void) StringCchPrintf (szBuffer, ARRAYSIZE(szBuffer), szTitle, lpSelInfo->lpDomainName);
SetWindowText (hDlg, szBuffer);
}
else
{
LoadString (g_hInstance, IDS_NODC_OPTIONS_TEXT, szBuffer, ARRAYSIZE(szBuffer));
SetDlgItemText (hDlg, IDC_NODC_TEXT, szBuffer);
LoadString (g_hInstance, IDS_NODC_OPTIONS_TITLE, szBuffer, ARRAYSIZE(szBuffer));
SetWindowText (hDlg, szBuffer);
}
if (!lpSelInfo->bAllowInherit)
{
EnableWindow (GetDlgItem(hDlg, IDC_NODC_INHERIT), FALSE);
}
if (lpSelInfo->iDefault == 2)
{
if (lpSelInfo->bAllowInherit)
{
CheckDlgButton (hDlg, IDC_NODC_INHERIT, BST_CHECKED);
}
else
{
CheckDlgButton (hDlg, IDC_NODC_PDC, BST_CHECKED);
}
}
else if (lpSelInfo->iDefault == 3)
{
CheckDlgButton (hDlg, IDC_NODC_ANYDC, BST_CHECKED);
}
else
{
CheckDlgButton (hDlg, IDC_NODC_PDC, BST_CHECKED);
}
return TRUE;
}
case WM_COMMAND:
if (LOWORD(wParam) == IDOK)
{
if (IsDlgButtonChecked (hDlg, IDC_NODC_PDC) == BST_CHECKED)
{
EndDialog(hDlg, 1);
}
else if (IsDlgButtonChecked (hDlg, IDC_NODC_INHERIT) == BST_CHECKED)
{
EndDialog(hDlg, 2);
}
else
{
EndDialog(hDlg, 3);
}
return TRUE;
}
if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, 0);
return TRUE;
}
break;
case WM_HELP: // F1
WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, HELP_FILE, HELP_WM_HELP,
(ULONG_PTR) (LPSTR) aNoDCHelpIds);
break;
case WM_CONTEXTMENU: // right mouse click
WinHelp((HWND) wParam, HELP_FILE, HELP_CONTEXTMENU,
(ULONG_PTR) (LPSTR) aNoDCHelpIds);
return (TRUE);
}
return FALSE;
}
//*************************************************************
//
// AddDCSelection()
//
// Purpose: Adds a DC selection to the array
//
// Parameters: lpDomainName - Domain name
// iOption - Option
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL AddDCSelection (LPTSTR lpDomainName, INT iOption)
{
LPDCOPTION lpTemp;
UINT uiSize;
//
// Check to see if we already have an entry first
//
EnterCriticalSection(&g_DCCS);
lpTemp = g_DCInfo;
while (lpTemp)
{
if (!lstrcmpi(lpDomainName, lpTemp->lpDomainName))
{
lpTemp->iOption = iOption;
LeaveCriticalSection(&g_DCCS);
return TRUE;
}
lpTemp = lpTemp->pNext;
}
//
// Add a new entry
//
uiSize = sizeof(DCOPTION);
uiSize += ((lstrlen(lpDomainName) + 1) * sizeof(TCHAR));
lpTemp = (LPDCOPTION) LocalAlloc (LPTR, uiSize);
if (!lpTemp)
{
DebugMsg((DM_WARNING, TEXT("AddDCSelection: Failed to allocate memory with %d"),
GetLastError()));
LeaveCriticalSection(&g_DCCS);
return FALSE;
}
lpTemp->lpDomainName = (LPTSTR)((LPBYTE) lpTemp + sizeof(DCOPTION));
HRESULT hr;
ULONG ulNoChars = (uiSize - sizeof(DCOPTION))/sizeof(WCHAR);
hr = StringCchCopy(lpTemp->lpDomainName, ulNoChars, lpDomainName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("AddDCSelection: Failed to copy domain name with %d"), hr));
LocalFree(lpTemp);
LeaveCriticalSection(&g_DCCS);
return FALSE;
}
lpTemp->iOption = iOption;
if (g_DCInfo)
{
lpTemp->pNext = g_DCInfo;
g_DCInfo = lpTemp;
}
else
{
g_DCInfo = lpTemp;
}
LeaveCriticalSection(&g_DCCS);
return TRUE;
}
//*************************************************************
//
// FreeDCSelections()
//
// Purpose: Frees the cached DC selections
//
// Parameters: none
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
VOID FreeDCSelections (void)
{
LPDCOPTION lpTemp, lpNext;
EnterCriticalSection(&g_DCCS);
lpTemp = g_DCInfo;
while (lpTemp)
{
lpNext = lpTemp->pNext;
LocalFree (lpTemp);
lpTemp = lpNext;
}
g_DCInfo = NULL;
LeaveCriticalSection(&g_DCCS);
}
//*************************************************************
//
// CheckForCachedDCSelection()
//
// Purpose: Checks if the DC selection for this domain is in
// the cache
//
// Parameters: lpDomainName - Domain name
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
INT CheckForCachedDCSelection (LPTSTR lpDomainName)
{
INT iResult = 0;
LPDCOPTION lpTemp;
EnterCriticalSection(&g_DCCS);
lpTemp = g_DCInfo;
while (lpTemp)
{
if (!lstrcmpi(lpDomainName, lpTemp->lpDomainName))
{
iResult = lpTemp->iOption;
break;
}
lpTemp = lpTemp->pNext;
}
LeaveCriticalSection(&g_DCCS);
return iResult;
}
//*************************************************************
//
// ValidateInheritServer()
//
// Purpose: Tests if the given DC name is in the given domain
//
// Parameters: lpDomainName -- Domain name
// lpDCName -- Domain controller name
//
//
// Return: ERROR_SUCCESS if successful
// Error code otherwise
//
//*************************************************************
DWORD ValidateInheritServer (LPTSTR lpDomainName, LPTSTR lpDCName)
{
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBasic;
DWORD dwResult;
dwResult = DsRoleGetPrimaryDomainInformation (lpDCName, DsRolePrimaryDomainInfoBasic,
(LPBYTE *) &pBasic);
if (dwResult == ERROR_SUCCESS) {
if (lstrcmpi(lpDomainName, pBasic->DomainNameDns))
{
dwResult = ERROR_NO_SUCH_DOMAIN;
DebugMsg((DM_VERBOSE, TEXT("ValidateInheritServer: DC %s is not part of domain %s, it is part of %s. This server will not be used for inheritance."),
lpDCName, lpDomainName, pBasic->DomainNameDns));
}
DsRoleFreeMemory (pBasic);
}
return dwResult;
}
//*************************************************************
//
// TestDC()
//
// Purpose: Tests if a DC is available
//
// Parameters:
//
//
// Return: ERROR_SUCCESS if successful
// Error code otherwise
//
//*************************************************************
DWORD TestDC (LPTSTR lpDCName)
{
LPTSTR lpTest;
HANDLE hFile;
WIN32_FIND_DATA fd;
BOOL bResult = FALSE;
HRESULT hr;
ULONG ulNoChars;
ulNoChars = lstrlen(lpDCName) + 25;
lpTest = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpTest)
{
DebugMsg((DM_WARNING, TEXT("TestDC: Failed to allocate memory with %d"),
GetLastError()));
return GetLastError();
}
hr = StringCchCopy (lpTest, ulNoChars, TEXT("\\\\"));
if (SUCCEEDED(hr))
{
hr = StringCchCat(lpTest, ulNoChars, lpDCName);
}
if (SUCCEEDED(hr))
{
hr = StringCchCat(lpTest, ulNoChars, TEXT("\\sysvol\\*.*"));
}
if (FAILED(hr))
{
LocalFree(lpTest);
return HRESULT_CODE(hr);
}
hFile = FindFirstFile (lpTest, &fd);
if (hFile == INVALID_HANDLE_VALUE)
{
DebugMsg((DM_WARNING, TEXT("TestDC: Failed to access <%s> with %d"),
lpTest, GetLastError()));
LocalFree (lpTest);
return GetLastError();
}
FindClose (hFile);
LocalFree (lpTest);
return ERROR_SUCCESS;
}
//*************************************************************
//
// QueryForForestName()
//
// Purpose: Queries for a domain controller name
//
// Parameters:
//
//
// Return: ERROR_SUCCESS if successful
// Error code otherwise
//
//*************************************************************
DWORD QueryForForestName (LPTSTR lpServerName, LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpForestFound)
{
PDOMAIN_CONTROLLER_INFO pDCI;
DWORD dwResult;
LPTSTR lpTemp, lpEnd;
//
// Call for a DC name
//
dwResult = DsGetDcName (lpServerName, lpDomainName, NULL, NULL,
ulFlags,
&pDCI);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("QueryForForestName: Failed to query <%s> for a DC name with %d"),
lpDomainName, dwResult));
return dwResult;
}
if (!(pDCI->Flags & DS_DS_FLAG))
{
DebugMsg((DM_WARNING, TEXT("QueryForForestName: %s doesn't have Active Directory support (downlevel domain)"),
lpDomainName));
NetApiBufferFree(pDCI);
return ERROR_DS_UNAVAILABLE;
}
ULONG ulNoChars;
HRESULT hr;
ulNoChars = lstrlen(pDCI->DnsForestName) + 1;
lpTemp = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpTemp)
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("QueryForForestName: Failed to allocate memory for forest name with %d"),
dwResult));
NetApiBufferFree(pDCI);
return dwResult;
}
hr = StringCchCopy(lpTemp, ulNoChars, pDCI->DnsForestName);
ASSERT(SUCCEEDED(hr));
NetApiBufferFree(pDCI);
LocalFree(*lpForestFound);
*lpForestFound = lpTemp;
return ERROR_SUCCESS;
}
//*************************************************************
//
// QueryForDCName()
//
// Purpose: Queries for a domain controller name
//
// Parameters:
//
//
// Return: ERROR_SUCCESS if successful
// Error code otherwise
//
//*************************************************************
DWORD QueryForDCName (LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpDCName)
{
PDOMAIN_CONTROLLER_INFO pDCI;
DWORD dwResult;
LPTSTR lpTemp, lpEnd;
//
// Call for a DC name
//
dwResult = DsGetDcName (NULL, lpDomainName, NULL, NULL,
ulFlags, &pDCI);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("QueryForDCName: Failed to query <%s> for a DC name with %d"),
lpDomainName, dwResult));
return dwResult;
}
if (!(pDCI->Flags & DS_DS_FLAG))
{
DebugMsg((DM_WARNING, TEXT("QueryForDCName: %s doesn't not have Active Directory support (downlevel domain)"),
lpDomainName));
return ERROR_DS_UNAVAILABLE;
}
//
// Save the DC name
//
ULONG ulNoChars;
HRESULT hr;
ulNoChars = lstrlen (pDCI->DomainControllerName) + 1;
lpTemp = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpTemp)
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("QueryForDCName: Failed to allocate memory for DC name with %d"),
dwResult));
NetApiBufferFree(pDCI);
return dwResult;
}
hr = StringCchCopy (lpTemp, ulNoChars, (pDCI->DomainControllerName + 2));
if (SUCCEEDED(hr))
{
//
// Remove the trailing .
//
lpEnd = lpTemp + lstrlen(lpTemp) - 1;
if (*lpEnd == TEXT('.'))
{
*lpEnd = TEXT('\0');
}
*lpDCName = lpTemp;
dwResult = ERROR_SUCCESS;
}
else
{
DebugMsg((DM_WARNING, TEXT("QueryForDCName: Failed to allocate memory for DC name with 0x%x"),hr));
LocalFree(lpTemp);
dwResult = HRESULT_CODE(hr);
}
NetApiBufferFree(pDCI);
return dwResult;
}
//*************************************************************
//
// GetDCHelper()
//
// Purpose: Queries for a domain controller based upon
// the flags and then rediscovers if necessary
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
DWORD GetDCHelper (LPTSTR lpDomainName, ULONG ulFlags, LPTSTR *lpDCName)
{
DWORD dwError;
//
// Query for a DC name
//
SetWaitCursor();
ulFlags |= DS_DIRECTORY_SERVICE_PREFERRED;
dwError = QueryForDCName (lpDomainName, ulFlags, lpDCName);
if (dwError == ERROR_SUCCESS)
{
//
// Test if the DC is available
//
dwError = TestDC (*lpDCName);
if (dwError != ERROR_SUCCESS)
{
//
// The DC isn't available. Query for another one
//
LocalFree (*lpDCName);
ulFlags |= DS_FORCE_REDISCOVERY;
dwError = QueryForDCName (lpDomainName, ulFlags, lpDCName);
if (dwError == ERROR_SUCCESS)
{
//
// Test if this DC is available
//
dwError = TestDC (*lpDCName);
if (dwError != ERROR_SUCCESS)
{
LocalFree (*lpDCName);
*lpDCName = NULL;
}
}
}
}
ClearWaitCursor();
return dwError;
}
//*************************************************************
//
// GetDCName()
//
// Purpose: Gets a domain controller name
//
// Parameters: lpDomainName - Domain name
// lpInheritServer - Inheritable server name
// hParent - Parent window handle for prompt dialog
// bAllowUI - Displaying UI is ok
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Notes: DC Option values in the registry
//
// Not specified 0
// PDC 1
// Inherit 2
// Any Writable 3
//
// Rules for finding a DC:
// Inherit
// Preference Policy DC Avail Result
// ========== ====== ======== ======
// Undefined Undefined 1) PDC 2) Prompt
// PDC Undefined 1) PDC 2) Prompt
// Inherit Undefined Yes Inhert
// Inherit Undefined No Any DC
// Any Undefined Any DC
//
// n/a PDC PDC only
// n/a Inherit Yes Inhert
// n/a Inherit No Any DC
// n/a Any Any DC
//
//
//*************************************************************
LPTSTR GetDCName (LPTSTR lpDomainName, LPTSTR lpInheritServer,
HWND hParent, BOOL bAllowUI, DWORD dwFlags, ULONG ulRetFlags)
{
LPTSTR lpDCName;
ULONG ulFlags;
DWORD dwDCPref = 1;
DWORD dwDCPolicy = 0;
HKEY hKey;
DWORD dwSize, dwType, dwError;
dwError = ERROR_SUCCESS;
DCSELINFO SelInfo;
INT iResult;
ulFlags = ulRetFlags;
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Entering for: %s"), lpDomainName));
DebugMsg((DM_VERBOSE, TEXT("GetDCName: lpInheritServer is: %s"), lpInheritServer));
if (-1 == CheckForCachedDCSelection (lpDomainName))
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Known dead domain. Exiting.")));
return NULL;
}
//
// Check for a user DC preference
//
if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_KEY, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(dwDCPref);
RegQueryValueEx (hKey, DCOPTION_VALUE, NULL, &dwType,
(LPBYTE) &dwDCPref, &dwSize);
if (dwDCPref > 3)
{
dwDCPref = 1;
}
RegCloseKey (hKey);
}
//
// Check for a user DC policy
//
if (RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0,
KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(dwDCPolicy);
RegQueryValueEx (hKey, DCOPTION_VALUE, NULL, &dwType,
(LPBYTE) &dwDCPolicy, &dwSize);
if (dwDCPolicy > 3)
{
dwDCPolicy = 1;
}
RegCloseKey (hKey);
}
DebugMsg((DM_VERBOSE, TEXT("GetDCName: User preference is: %d"), dwDCPref));
DebugMsg((DM_VERBOSE, TEXT("GetDCName: User policy is: %d"), dwDCPolicy));
//
// Validate that the inherit DC name is part of the domain name
//
if (lpInheritServer && (dwFlags & VALIDATE_INHERIT_DC))
{
if (ValidateInheritServer (lpDomainName, lpInheritServer) != ERROR_SUCCESS)
{
lpInheritServer = NULL;
}
}
//
// Based upon the rules, try to get a DC name
//
if (dwDCPolicy == 0)
{
//
// The user doesn't have a preference or they have
// a preference of using the PDC
//
if ((dwDCPref == 0) || (dwDCPref == 1))
{
ulFlags = DS_PDC_REQUIRED | ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
//
// The user has a preference of inheriting
//
else if (dwDCPref == 2)
{
if (lpInheritServer)
{
ULONG ulNoChars = lstrlen (lpInheritServer) + 1;
lpDCName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpDCName)
{
DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
GetLastError()));
return NULL;
}
HRESULT hr;
hr = StringCchCopy (lpDCName, ulNoChars, lpInheritServer);
ASSERT(SUCCEEDED(hr));
dwError = TestDC (lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
LocalFree (lpDCName);
}
else
{
ulFlags = ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
}
//
// The user has a preference of using any DC
//
else if (dwDCPref == 3)
{
ulFlags = ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
}
else
{
//
// Policy says to use PDC
//
if (dwDCPolicy == 1)
{
ulFlags = DS_PDC_REQUIRED | ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
//
// Policy says to inherit
//
else if (dwDCPolicy == 2)
{
if (lpInheritServer)
{
ULONG ulNoChars;
HRESULT hr;
ulNoChars = lstrlen (lpInheritServer) + 1;
lpDCName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpDCName)
{
DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
GetLastError()));
return NULL;
}
hr = StringCchCopy (lpDCName, ulNoChars, lpInheritServer);
ASSERT(SUCCEEDED(hr));
dwError = TestDC (lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
LocalFree (lpDCName);
}
else
{
ulFlags = ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
}
//
// Policy says to use any DC
//
else if (dwDCPolicy == 3)
{
ulFlags = ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
return lpDCName;
}
}
}
DebugMsg((DM_VERBOSE, TEXT("GetDCName: First attempt at DC name failed with %d"), dwError));
//
// The first attempt at getting a DC name failed
//
// In 2 cases, we will prompt the user for what to do and try again.
//
if (bAllowUI && (dwError != ERROR_DS_UNAVAILABLE) && (dwDCPolicy == 0) && ((dwDCPref == 0) || (dwDCPref == 1)))
{
iResult = CheckForCachedDCSelection (lpDomainName);
if (iResult == 0)
{
//
// Display the message
//
SelInfo.bError = TRUE;
SelInfo.bAllowInherit = (lpInheritServer != NULL) ? TRUE : FALSE;
SelInfo.iDefault = 1;
SelInfo.lpDomainName = lpDomainName;
iResult = (INT)DialogBoxParam (g_hInstance, MAKEINTRESOURCE(IDD_NODC), hParent,
DCDlgProc, (LPARAM) &SelInfo);
}
//
// Based upon the return value, try for another DC
//
if (iResult == 1)
{
ulFlags = DS_PDC_REQUIRED | ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
AddDCSelection (lpDomainName, iResult);
return lpDCName;
}
else
{
AddDCSelection (lpDomainName, -1);
}
}
else if (iResult == 2)
{
HRESULT hr;
ULONG ulNoChars;
ulNoChars = lstrlen (lpInheritServer) + 1;
lpDCName = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpDCName)
{
DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"),
GetLastError()));
return NULL;
}
hr = StringCchCopy (lpDCName, ulNoChars, lpInheritServer);
ASSERT(SUCCEEDED(hr));
dwError = TestDC (lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
AddDCSelection (lpDomainName, iResult);
return lpDCName;
}
else
{
AddDCSelection (lpDomainName, -1);
}
LocalFree (lpDCName);
}
else if (iResult == 3)
{
ulFlags = 0 | ulRetFlags;
dwError = GetDCHelper (lpDomainName, ulFlags, &lpDCName);
if (dwError == ERROR_SUCCESS)
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: Domain controller is: %s"), lpDCName));
AddDCSelection (lpDomainName, iResult);
return lpDCName;
}
else
{
AddDCSelection (lpDomainName, -1);
}
}
else
{
DebugMsg((DM_VERBOSE, TEXT("GetDCName: User cancelled the dialog box")));
return NULL;
}
}
DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to find a domain controller")));
if (bAllowUI)
{
if (dwError == ERROR_DS_UNAVAILABLE)
{
ReportError(NULL, dwError, IDS_NODSDC, lpDomainName);
}
else
{
ReportError(NULL, dwError, IDS_NODC);
}
}
SetLastError(dwError);
return NULL;
}
//*************************************************************
//
// MyGetUserName()
//
// Purpose: Gets the user name in the requested format
//
// Parameters: NameFormat - GetUserNameEx naming format
//
// Return: lpUserName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR MyGetUserName (EXTENDED_NAME_FORMAT NameFormat)
{
DWORD dwError = ERROR_SUCCESS;
LPTSTR lpUserName = NULL, lpTemp;
ULONG ulUserNameSize;
//
// Allocate a buffer for the user name
//
ulUserNameSize = 75;
if (NameFormat == NameFullyQualifiedDN) {
ulUserNameSize = 200;
}
lpUserName = (LPTSTR) LocalAlloc (LPTR, ulUserNameSize * sizeof(TCHAR));
if (!lpUserName) {
dwError = GetLastError();
DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to allocate memory with %d"),
dwError));
goto Exit;
}
//
// Special case NameUnknown to just get the simple user logon name
//
if (NameFormat == NameUnknown)
{
if (!GetUserName (lpUserName, &ulUserNameSize))
{
dwError = GetLastError();
DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserName failed with %d"),
dwError));
LocalFree (lpUserName);
lpUserName = NULL;
}
goto Exit;
}
//
// Get the username in the requested format
//
if (!GetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
//
// If the call failed due to insufficient memory, realloc
// the buffer and try again. Otherwise, exit now.
//
dwError = GetLastError();
if (dwError != ERROR_INSUFFICIENT_BUFFER) {
DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserNameEx failed with %d"),
dwError));
LocalFree (lpUserName);
lpUserName = NULL;
goto Exit;
}
lpTemp = (LPTSTR) LocalReAlloc (lpUserName, (ulUserNameSize * sizeof(TCHAR)),
LMEM_MOVEABLE);
if (!lpTemp) {
dwError = GetLastError();
DebugMsg((DM_WARNING, TEXT("MyGetUserName: Failed to realloc memory with %d"),
dwError));
LocalFree (lpUserName);
lpUserName = NULL;
goto Exit;
}
lpUserName = lpTemp;
if (!GetUserNameEx (NameFormat, lpUserName, &ulUserNameSize)) {
dwError = GetLastError();
DebugMsg((DM_WARNING, TEXT("MyGetUserName: GetUserNameEx failed with %d"),
dwError));
LocalFree (lpUserName);
lpUserName = NULL;
goto Exit;
}
dwError = ERROR_SUCCESS;
}
Exit:
SetLastError(dwError);
return lpUserName;
}
//*************************************************************
//
// GuidToString, StringToGuid, ValidateGuid
//
// Purpose: Guid utility routines
//
//*************************************************************
void GuidToString( GUID *pGuid, TCHAR * szValue )
{
(void) StringCchPrintf( szValue,
GUID_LEN+1,
TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
pGuid->Data1,
pGuid->Data2,
pGuid->Data3,
pGuid->Data4[0], pGuid->Data4[1],
pGuid->Data4[2], pGuid->Data4[3],
pGuid->Data4[4], pGuid->Data4[5],
pGuid->Data4[6], pGuid->Data4[7] );
}
void StringToGuid( TCHAR * szValue, GUID * pGuid )
{
WCHAR wc;
INT i;
//
// If the first character is a '{', skip it
//
if ( szValue[0] == L'{' )
szValue++;
//
// Since szValue may be used again, no permanent modification to
// it is be made.
//
wc = szValue[8];
szValue[8] = 0;
pGuid->Data1 = wcstoul( &szValue[0], 0, 16 );
szValue[8] = wc;
wc = szValue[13];
szValue[13] = 0;
pGuid->Data2 = (USHORT)wcstoul( &szValue[9], 0, 16 );
szValue[13] = wc;
wc = szValue[18];
szValue[18] = 0;
pGuid->Data3 = (USHORT)wcstoul( &szValue[14], 0, 16 );
szValue[18] = wc;
wc = szValue[21];
szValue[21] = 0;
pGuid->Data4[0] = (unsigned char)wcstoul( &szValue[19], 0, 16 );
szValue[21] = wc;
wc = szValue[23];
szValue[23] = 0;
pGuid->Data4[1] = (unsigned char)wcstoul( &szValue[21], 0, 16 );
szValue[23] = wc;
for ( i = 0; i < 6; i++ )
{
wc = szValue[26+i*2];
szValue[26+i*2] = 0;
pGuid->Data4[2+i] = (unsigned char)wcstoul( &szValue[24+i*2], 0, 16 );
szValue[26+i*2] = wc;
}
}
BOOL ValidateGuid( TCHAR *szValue )
{
//
// Check if szValue is of form {19e02dd6-79d2-11d2-a89d-00c04fbbcfa2}
//
if ( lstrlen(szValue) < GUID_LENGTH )
return FALSE;
if ( szValue[0] != TEXT('{')
|| szValue[9] != TEXT('-')
|| szValue[14] != TEXT('-')
|| szValue[19] != TEXT('-')
|| szValue[24] != TEXT('-')
|| szValue[37] != TEXT('}') )
{
return FALSE;
}
return TRUE;
}
INT CompareGuid( GUID * pGuid1, GUID * pGuid2 )
{
INT i;
if ( pGuid1->Data1 != pGuid2->Data1 )
return ( pGuid1->Data1 < pGuid2->Data1 ? -1 : 1 );
if ( pGuid1->Data2 != pGuid2->Data2 )
return ( pGuid1->Data2 < pGuid2->Data2 ? -1 : 1 );
if ( pGuid1->Data3 != pGuid2->Data3 )
return ( pGuid1->Data3 < pGuid2->Data3 ? -1 : 1 );
for ( i = 0; i < 8; i++ )
{
if ( pGuid1->Data4[i] != pGuid2->Data4[i] )
return ( pGuid1->Data4[i] < pGuid2->Data4[i] ? -1 : 1 );
}
return 0;
}
BOOL IsNullGUID (GUID *pguid)
{
return ( (pguid->Data1 == 0) &&
(pguid->Data2 == 0) &&
(pguid->Data3 == 0) &&
(pguid->Data4[0] == 0) &&
(pguid->Data4[1] == 0) &&
(pguid->Data4[2] == 0) &&
(pguid->Data4[3] == 0) &&
(pguid->Data4[4] == 0) &&
(pguid->Data4[5] == 0) &&
(pguid->Data4[6] == 0) &&
(pguid->Data4[7] == 0) );
}
//*************************************************************
//
// SpawnGPE()
//
// Purpose: Spawns GPE for a GPO
//
// Parameters: lpGPO - ADSI path to the GPO
// gpHint - GPO hint type
// lpDC - GPO DC name to use (or NULL)
// hParent - Parent window handle
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL SpawnGPE (LPTSTR lpGPO, GROUP_POLICY_HINT_TYPE gpHint, LPTSTR lpDC, HWND hParent)
{
LPTSTR lpArgs, lpFullPath, lpDomainName, lpGPODCName;
UINT uiSize;
SHELLEXECUTEINFO ExecInfo;
LPOLESTR pszDomain;
HRESULT hr;
//
// If a DC was given, we need to build a full path to the GPO on that DC.
// If a DC was not given, then we need to query for a DC and then build a
// full path.
//
if (lpDC)
{
//
// Make the full path
//
lpFullPath = MakeFullPath (lpGPO, lpDC);
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to build new DS object path")));
return FALSE;
}
}
else
{
//
// Get the friendly domain name
//
pszDomain = GetDomainFromLDAPPath(lpGPO);
if (!pszDomain)
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to get domain name")));
return FALSE;
}
//
// Convert LDAP to dot (DN) style
//
hr = ConvertToDotStyle (pszDomain, &lpDomainName);
delete [] pszDomain;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::CreatePropertyPages: Failed to convert domain name with 0x%x"), hr));
return FALSE;
}
//
// Get the GPO DC for this domain
//
lpGPODCName = GetDCName (lpDomainName, lpDC, hParent, TRUE, VALIDATE_INHERIT_DC);
if (!lpGPODCName)
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to get DC name for %s"),
lpDomainName));
LocalFree (lpDomainName);
return FALSE;
}
LocalFree (lpDomainName);
//
// Make the full path
//
lpFullPath = MakeFullPath (lpGPO, lpGPODCName);
LocalFree (lpGPODCName);
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to build new DS object path")));
return FALSE;
}
}
uiSize = lstrlen (lpFullPath) + 30;
lpArgs = (LPTSTR) LocalAlloc (LPTR, uiSize * sizeof(TCHAR));
if (!lpArgs)
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to allocate memory with %d"),
GetLastError()));
return FALSE;
}
//
// Build the command line arguments
//
hr = StringCchPrintf (lpArgs, uiSize, TEXT("/s /gphint:%d /gpobject:\"%s\""), gpHint, lpFullPath);
if (FAILED(hr))
{
LocalFree(lpArgs);
DebugMsg((DM_WARNING, TEXT("SpawnGPE: Failed to build command line arguements with 0x%x"), hr));
return FALSE;
}
DebugMsg((DM_VERBOSE, TEXT("SpawnGPE: Starting GPE with %s"), lpArgs));
ZeroMemory (&ExecInfo, sizeof(ExecInfo));
ExecInfo.cbSize = sizeof(ExecInfo);
ExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ExecInfo.lpVerb = TEXT("open");
ExecInfo.lpFile = TEXT("gpedit.msc");
ExecInfo.lpParameters = lpArgs;
ExecInfo.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx (&ExecInfo))
{
SetWaitCursor();
WaitForInputIdle (ExecInfo.hProcess, 10000);
ClearWaitCursor();
CloseHandle (ExecInfo.hProcess);
}
else
{
DebugMsg((DM_WARNING, TEXT("SpawnGPE: ShellExecuteEx failed with %d"),
GetLastError()));
ReportError(NULL, ( (GetLastError() == -1) ? 0 : GetLastError()), IDS_SPAWNGPEFAILED);
LocalFree (lpArgs);
return FALSE;
}
LocalFree (lpArgs);
LocalFree (lpFullPath);
return TRUE;
}
//*************************************************************
//
// MakeFullPath()
//
// Purpose: Builds a fully qualified ADSI path consisting
// of server and DN name
//
// Parameters: lpDN - DN path, must start with LDAP://
// lpServer - Server name
//
// Return: lpFullPath if success
// NULL if an error occurs
//
//*************************************************************
LPTSTR MakeFullPath (LPTSTR lpDN, LPTSTR lpServer)
{
IADsPathname * pADsPathname;
LPTSTR lpFullPath;
BSTR bstr;
HRESULT hr;
ULONG ulNoChars;
//
// Make sure the incoming path is nameless first
//
hr = CoCreateInstance(CLSID_Pathname,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsPathname,
(LPVOID*)&pADsPathname);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to create IAdsPathName object with = 0x%x"), hr));
SetLastError(HRESULT_CODE(hr));
return NULL;
}
BSTR bstrDN = SysAllocString( lpDN );
if ( bstrDN == NULL )
{
DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to allocate BSTR memory.")));
pADsPathname->Release();
SetLastError(HRESULT_CODE(E_OUTOFMEMORY));
return NULL;
}
hr = pADsPathname->Set(bstrDN, ADS_SETTYPE_FULL);
SysFreeString( bstrDN );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to set <%s> in IAdsPathName object with = 0x%x"),
lpDN, hr));
pADsPathname->Release();
SetLastError(HRESULT_CODE(hr));
return NULL;
}
hr = pADsPathname->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstr);
pADsPathname->Release();
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to retrieve pathname with = 0x%x"), hr));
SetLastError(HRESULT_CODE(hr));
return NULL;
}
//
// Allocate a new buffer for the named path including LDAP://
//
ulNoChars = 7 + lstrlen(bstr) + (lpServer ? lstrlen(lpServer) : 0) + 3;
lpFullPath = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to allocate memory with = %d"), GetLastError()));
SysFreeString (bstr);
return NULL;
}
hr = StringCchCopy (lpFullPath, ulNoChars, TEXT("LDAP://"));
if (SUCCEEDED(hr))
{
if (lpServer)
{
hr = StringCchCat (lpFullPath, ulNoChars, lpServer);
if (SUCCEEDED(hr))
{
hr = StringCchCat(lpFullPath, ulNoChars, TEXT("/"));
}
}
}
if (SUCCEEDED(hr))
{
hr = StringCchCat (lpFullPath, ulNoChars, (LPTSTR)(bstr + 7));
}
if (FAILED(hr))
{
LocalFree(lpFullPath);
lpFullPath = NULL;
}
SysFreeString (bstr);
return lpFullPath;
}
//*************************************************************
//
// MakeNamelessPath()
//
// Purpose: Builds a server nameless ADSI path
//
// Parameters: lpDN - DN path, must start with LDAP://
//
// Return: lpPath if success
// NULL if an error occurs
//
//*************************************************************
LPTSTR MakeNamelessPath (LPTSTR lpDN)
{
IADsPathname * pADsPathname;
LPTSTR lpPath;
BSTR bstr;
HRESULT hr;
//
// Create a pathname object to work with
//
hr = CoCreateInstance(CLSID_Pathname,
NULL,
CLSCTX_INPROC_SERVER,
IID_IADsPathname,
(LPVOID*)&pADsPathname);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to create IAdsPathName object with = 0x%x"), hr));
return NULL;
}
BSTR bstrDN = SysAllocString( lpDN );
if ( bstrDN == NULL )
{
DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to allocate BSTR memory.")));
pADsPathname->Release();
return NULL;
}
hr = pADsPathname->Set(bstrDN, ADS_SETTYPE_FULL);
SysFreeString( bstrDN );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to set <%s> in IAdsPathName object with = 0x%x"),
lpDN, hr));
pADsPathname->Release();
return NULL;
}
hr = pADsPathname->Retrieve(ADS_FORMAT_X500_NO_SERVER, &bstr);
pADsPathname->Release();
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to retrieve pathname with = 0x%x"), hr));
return NULL;
}
//
// Allocate a new buffer for the path
//
ULONG ulNoChars = lstrlen(bstr) + 1;
lpPath = (LPTSTR) LocalAlloc (LPTR, ulNoChars * sizeof(TCHAR));
if (!lpPath)
{
DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to allocate memory with = %d"), GetLastError()));
SysFreeString (bstr);
return NULL;
}
hr = StringCchCopy (lpPath, ulNoChars, bstr);
ASSERT(SUCCEEDED(hr));
SysFreeString (bstr);
return lpPath;
}
//*************************************************************
//
// ExtractServerName()
//
// Purpose: Extracts the server name from a ADSI path
//
// Parameters: lpPath - ADSI path, must start with LDAP://
//
// Return: lpServerName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR ExtractServerName (LPTSTR lpPath)
{
LPTSTR lpServerName = NULL;
LPTSTR lpEnd, lpTemp;
//
// Check the path to see if it has a server name
//
if (*(lpPath + 9) != TEXT('='))
{
//
// Allocate memory for the server name
//
lpServerName = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpPath) + 1) * sizeof(TCHAR));
if (!lpServerName)
{
DebugMsg((DM_WARNING, TEXT("ExtractServerName: Failed to allocate memory for name with 0xd"),
GetLastError()));
return NULL;
}
lpTemp = (lpPath + 7);
lpEnd = lpServerName;
while (*lpTemp && (*lpTemp != TEXT('/')) && (*lpTemp != TEXT(',')))
{
*lpEnd = *lpTemp;
lpEnd++;
lpTemp++;
}
if (*lpTemp != TEXT('/'))
{
DebugMsg((DM_WARNING, TEXT("ExtractServerName: Failed to parse server name from ADSI path")));
LocalFree (lpServerName);
lpServerName = NULL;
}
}
return lpServerName;
}
//*************************************************************
//
// DoesPathContainAServerName()
//
// Purpose: Checks the given ADSI path to see if it
// contains a server name
//
// Parameters: lpPath - ADSI path
//
// Return: True if the path contains a server name
// FALSE if not
//
//*************************************************************
BOOL DoesPathContainAServerName (LPTSTR lpPath)
{
BOOL bResult = FALSE;
//
// Skip over LDAP:// if found
//
if ( CompareString( LOCALE_INVARIANT, NORM_IGNORECASE | NORM_STOP_ON_NULL,
lpPath, 7, L"LDAP://", 7 ) == CSTR_EQUAL )
{
lpPath += 7;
}
//
// Check if the 3rd character in the path is an equal sign.
// If so, this path does not contain a server name
//
if ((lstrlen(lpPath) > 2) && (*(lpPath + 2) != TEXT('=')))
{
bResult = TRUE;
}
return bResult;
}
//*************************************************************
//
// OpenDSObject()
//
// Purpose: Checks the given ADSI path to see if it
// contains a server name
//
// Parameters: lpPath - ADSI path
//
// Return: True if the path contains a server name
// FALSE if not
//
//*************************************************************
HRESULT OpenDSObject (LPTSTR lpPath, REFIID riid, void FAR * FAR * ppObject)
{
DWORD dwFlags = ADS_SECURE_AUTHENTICATION;
if (DoesPathContainAServerName (lpPath))
{
dwFlags |= ADS_SERVER_BIND;
}
return AdminToolsOpenObject(lpPath, NULL, NULL, dwFlags,riid, ppObject);
}
HRESULT CheckDSWriteAccess (LPUNKNOWN punk, LPTSTR lpProperty)
{
HRESULT hr;
IDirectoryObject *pDO = NULL;
PADS_ATTR_INFO pAE = NULL;
LPWSTR lpAttributeNames[2];
DWORD dwResult, dwIndex;
//
// Get the IDirectoryObject interface
//
hr = punk->QueryInterface(IID_IDirectoryObject, (void**)&pDO);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("CheckDSWriteAccess: Failed to get the IDirectoryObject interface with 0x%x"), hr));
goto Exit;
}
//
// Get the property value
//
lpAttributeNames[0] = L"allowedAttributesEffective";
hr = pDO->GetObjectAttributes(lpAttributeNames, 1, &pAE, &dwResult);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CheckDSWriteAccess: Failed to get object attributes with 0x%x"), hr));
goto Exit;
}
//
// Set the default return value
//
hr = HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
//
// Go through the list of effective attributes
//
if (dwResult != 0) {
for (dwIndex = 0; dwIndex < pAE[0].dwNumValues; dwIndex++)
{
if (lstrcmpi(pAE[0].pADsValues[dwIndex].CaseIgnoreString,
lpProperty) == 0)
{
hr = HRESULT_FROM_WIN32(ERROR_SUCCESS);
}
}
}
else {
DebugMsg((DM_VERBOSE, TEXT("CheckDSWriteAccess: Couldn't get allowedAttributesEffective")));
}
Exit:
if (pAE)
{
FreeADsMem (pAE);
}
if (pDO)
{
pDO->Release();
}
return hr;
}
LPTSTR GetFullGPOPath (LPTSTR lpGPO, HWND hParent)
{
LPTSTR lpFullPath = NULL, lpDomainName = NULL;
LPTSTR lpGPODCName;
LPOLESTR pszDomain;
HRESULT hr;
//
// Get the friendly domain name
//
pszDomain = GetDomainFromLDAPPath(lpGPO);
if (!pszDomain)
{
DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to get domain name")));
return NULL;
}
//
// Convert LDAP to dot (DN) style
//
hr = ConvertToDotStyle (pszDomain, &lpDomainName);
delete [] pszDomain;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::CreatePropertyPages: Failed to convert domain name with 0x%x"), hr));
return NULL;
}
//
// Get the GPO DC for this domain
//
lpGPODCName = GetDCName (lpDomainName, NULL, hParent, TRUE, 0);
if (!lpGPODCName)
{
DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to get DC name for %s"),
lpDomainName));
goto Exit;
}
//
// Make the full path
//
lpFullPath = MakeFullPath (lpGPO, lpGPODCName);
LocalFree (lpGPODCName);
if (!lpFullPath)
{
DebugMsg((DM_WARNING, TEXT("GetFullGPOPath: Failed to build new DS object path")));
goto Exit;
}
Exit:
if (lpDomainName)
{
LocalFree (lpDomainName);
}
return lpFullPath;
}
//*************************************************************
//
// ConvertName()
//
// Purpose: Converts the user / computer name from SAM style
// to fully qualified DN
//
// Parameters: lpName - name in sam style
//
//
// Return: lpDNName if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR ConvertName (LPTSTR lpName)
{
LPTSTR lpDNName = NULL, lpSAMName = NULL;
LPTSTR lpTemp, lpDCName = NULL;
DWORD dwResult;
HANDLE hDS = NULL;
PDS_NAME_RESULT pNameResult = NULL;
PDS_NAME_RESULT_ITEM pNameResultItem;
HRESULT hr;
ULONG ulNoChars;
//
// Check the argument
//
if (!lpName)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: lpName is null")));
SetLastError(ERROR_INVALID_DATA);
goto Exit;
}
//
// Make a copy of the name so we can edit it
//
ulNoChars = lstrlen(lpName) + 1;
lpSAMName = new TCHAR[ulNoChars];
if (!lpSAMName)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError()));
goto Exit;
}
hr = StringCchCopy (lpSAMName, ulNoChars, lpName);
ASSERT(SUCCEEDED(hr));
//
// Find the slash between the domain name and the account name and replace
// it with a null
//
lpTemp = lpSAMName;
while (*lpTemp && (*lpTemp != TEXT('\\')))
{
lpTemp++;
}
if (!(*lpTemp))
{
DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to find backslash in %s"), lpSAMName));
SetLastError(ERROR_INVALID_DATA);
goto Exit;
}
*lpTemp = TEXT('\0');
//
// Call DsGetDcName to convert the netbios name to a FQDN name
//
dwResult = GetDCHelper (lpSAMName, DS_IS_FLAT_NAME | DS_RETURN_DNS_NAME, &lpDCName);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: GetDCHelper failed with %d"), dwResult));
SetLastError(dwResult);
goto Exit;
}
//
// Bind to the domain controller
//
dwResult = DsBind (lpDCName, NULL, &hDS);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: DsBind failed with %d"), dwResult));
SetLastError(dwResult);
goto Exit;
}
//
// Use DsCrackNames to convert the name FQDN
//
dwResult = DsCrackNames (hDS, DS_NAME_NO_FLAGS, DS_NT4_ACCOUNT_NAME, DS_FQDN_1779_NAME,
1, &lpName, &pNameResult);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: DsCrackNames failed with %d"), dwResult));
SetLastError(dwResult);
goto Exit;
}
//
// Setup a pointer to the first item
//
pNameResultItem = &pNameResult->rItems[0];
if (pNameResultItem->status != DS_NAME_NO_ERROR)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: DsCrackNames failed to convert name with %d"), pNameResultItem->status));
SetLastError(pNameResultItem->status);
goto Exit;
}
//
// Save the name in a new buffer so it can returned
//
ulNoChars = lstrlen(pNameResultItem->pName) + 1;
lpDNName = new TCHAR[ulNoChars];
if (!lpDNName)
{
DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError()));
goto Exit;
}
hr = StringCchCopy (lpDNName, ulNoChars, pNameResultItem->pName);
ASSERT(SUCCEEDED(hr));
Exit:
if (pNameResult)
{
DsFreeNameResult (pNameResult);
}
if (hDS)
{
DsUnBind (&hDS);
}
if (lpDCName)
{
LocalFree (lpDCName);
}
if (lpSAMName)
{
delete [] lpSAMName;
}
return lpDNName;
}
//*************************************************************
//
// CreateTempFile()
//
// Purpose: Creates a temp file
//
// Parameters: void
//
// Return: filename if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR CreateTempFile (void)
{
TCHAR szTempDir[MAX_PATH];
TCHAR szTempFile[MAX_PATH];
LPTSTR lpFileName;
//
// Query for the temp directory
//
if (!GetTempPath (MAX_PATH, szTempDir))
{
DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: GetTempPath failed with %d"), GetLastError()));
return NULL;
}
//
// Query for a temp filename
//
if (!GetTempFileName (szTempDir, TEXT("RSP"), 0, szTempFile))
{
DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: GetTempFile failed with %d"), GetLastError()));
return NULL;
}
//
// Allocate a new buffer for the filename
//
ULONG ulNoChars;
HRESULT hr;
ulNoChars = lstrlen(szTempFile) + 1;
lpFileName = new TCHAR[ulNoChars];
if (!lpFileName)
{
DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: Failed to allocate memory for temp filename with %d"), GetLastError()));
return NULL;
}
hr = StringCchCopy (lpFileName, ulNoChars, szTempFile);
ASSERT(SUCCEEDED(hr));
return lpFileName;
}
//+--------------------------------------------------------------------------
//
// Function: NameToPath
//
// Synopsis: converts a dot-format domain name to an LDAP:// style path
//
// Arguments: [szPath] - (out) buffer to hold the path
// [szName] - (in) dot-format domain name
// [cch] - (in) size of the out buffer
//
// History: 10-15-1998 stevebl Created
//
// Note: Currently, this routine will truncate if it doesn't get a
// large enough buffer so you'd better be sure your
// buffer's large enough. (The formula is string size + 10 + 3
// for each dot in the string.)
//
// That's good enough to avoid an AV but could have some really
// wierd side effects so beware.
//
//---------------------------------------------------------------------------
void NameToPath(WCHAR * szPath, WCHAR *szName, UINT cch)
{
WCHAR * szOut = szPath;
WCHAR * szIn = szName;
HRESULT hr;
hr = StringCchCopy(szOut, cch, TEXT("LDAP://DC="));
if (FAILED(hr))
{
return;
}
szOut += 10;
while ((*szIn) && (szOut + 1 < szPath + cch))
{
if (*szIn == TEXT('.') && (szOut + 4 < szPath + cch))
{
++szIn;
if (*szIn && *szIn != TEXT('.'))
{
*szOut = TEXT(',');
++szOut;
*szOut = TEXT('D');
++szOut;
*szOut = TEXT('C');
++szOut;
*szOut = TEXT('=');
++szOut;
}
}
else
{
*szOut = *szIn;
++szOut;
++szIn;
}
}
*szOut = TEXT('\0');
}
//+--------------------------------------------------------------------------
//
// Function: GetPathToForest
//
// Synopsis: given a domain, return a pointer to its forest
//
// Arguments: [szServer] - DOT style path to a server (may be NULL)
//
// Returns: LDAP style path to the forest's Configuration container
//
// History: 03-31-2000 stevebl Created
//
// Notes: return value is allocated with new
//
//---------------------------------------------------------------------------
LPTSTR GetPathToForest(LPOLESTR szServer)
{
LPOLESTR szReturn = NULL;
LPOLESTR lpForest = NULL;
LPOLESTR lpTemp = NULL;
LPOLESTR lpDCName = NULL;
IADsPathname * pADsPathname = NULL;
BSTR bstrForest = NULL;
HRESULT hr = 0;
int cch, n;
DWORD dwResult = QueryForForestName(szServer,
NULL,
DS_PDC_REQUIRED | DS_RETURN_DNS_NAME,
&lpTemp);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: QueryForestName failed for domain name %s with %d"),
szServer, dwResult));
hr = HRESULT_FROM_WIN32(dwResult);
goto Exit;
}
cch = 0;
n = 0;
// count the dots in lpTemp;
while (lpTemp[n])
{
if (L'.' == lpTemp[n])
{
cch++;
}
n++;
}
cch *= 3; // multiply the number of dots by 3;
cch += 11; // add 10 + 1 (for the null)
cch += n; // add the string size;
lpForest = (LPTSTR) LocalAlloc(LPTR, sizeof(WCHAR) * cch);
if (!lpForest)
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to allocate memory for forest name with %d"),
GetLastError()));
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
NameToPath(lpForest, lpTemp, cch);
LocalFree(lpTemp);
lpTemp = NULL;
// See if we need to put a specific server on this.
//
if (szServer)
{
// we have a path to a specific DC
// need to prepend it to the forest name
lpTemp = MakeFullPath(lpForest, szServer);
if (!lpTemp)
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to combine server name with Forest path")));
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
// clean up the variables we just borrowed so they can be used later
LocalFree(lpForest);
lpForest = lpTemp;
lpTemp = NULL;
}
// at this point we have the path to the forest's DC in lpForest
// we still need to add "CN=Configuration" to this
//
// Create a pathname object we can work with
//
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER,
IID_IADsPathname, (LPVOID*)&pADsPathname);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to create adspathname instance with 0x%x"), hr));
goto Exit;
}
//
// Add the domain name
//
bstrForest = SysAllocString( lpForest );
if ( bstrForest == NULL )
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPathname->Set (bstrForest, ADS_SETTYPE_FULL);
SysFreeString( bstrForest );
bstrForest = NULL;
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to set pathname with 0x%x"), hr));
goto Exit;
}
//
// Add the Configuration folder to the path
//
BSTR bstrCNConfiguration = SysAllocString( TEXT("CN=Configuration") );
if ( bstrCNConfiguration == NULL )
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to allocate BSTR memory.")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPathname->AddLeafElement (bstrCNConfiguration);
SysFreeString( bstrCNConfiguration );
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to add configuration folder with 0x%x"), hr));
goto Exit;
}
//
// Retreive the GPC path
//
hr = pADsPathname->Retrieve (ADS_FORMAT_X500, &bstrForest);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetPathToForest: Failed to retreive container path with 0x%x"), hr));
goto Exit;
}
DebugMsg((DM_VERBOSE, TEXT("GetPathToForest: conatiner path is: %s"), bstrForest));
ULONG ulNoChars = SysStringLen(bstrForest)+1;
szReturn = new OLECHAR[ulNoChars];
hr = StringCchCopy(szReturn, ulNoChars, bstrForest);
ASSERT(SUCCEEDED(hr));
Exit:
if (bstrForest)
{
SysFreeString(bstrForest);
}
if (pADsPathname)
{
pADsPathname->Release();
}
if (lpForest)
{
LocalFree(lpForest);
}
if (lpDCName)
{
LocalFree(lpDCName);
}
if (lpTemp)
{
LocalFree(lpTemp);
}
if (!szReturn)
{
SetLastError(hr);
}
return szReturn;
}
BOOL IsForest(LPOLESTR szLDAPPath)
{
#if FGPO_SUPPORT
return ((StrStrI(szLDAPPath, TEXT("CN=Configuration"))) ? TRUE : FALSE);
#else
return FALSE;
#endif
}
//*************************************************************
//
// IsStandaloneComputer()
//
// Purpose: Determines if the computer is not a member of a domain
//
// Parameters: none
//
//
// Return: TRUE if the computer is running standalone
// FALSE if not
//
//*************************************************************
BOOL IsStandaloneComputer (VOID)
{
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pBasic;
DWORD dwResult;
BOOL bRetVal = FALSE;
//
// Ask for the role of this machine
//
dwResult = DsRoleGetPrimaryDomainInformation(NULL, DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pBasic);
if (dwResult == ERROR_SUCCESS)
{
//
// Check for standalone flags
//
if ((pBasic->MachineRole == DsRole_RoleStandaloneWorkstation) ||
(pBasic->MachineRole == DsRole_RoleStandaloneServer))
{
bRetVal = TRUE;
}
DsRoleFreeMemory (pBasic);
}
else
{
DebugMsg((DM_WARNING, TEXT("IsStandaloneComputer: DsRoleGetPrimaryDomainInformation failed with %d."),
dwResult));
}
return bRetVal;
}
//*************************************************************
//
// GetNewGPODisplayName()
//
// Purpose: Gets the new GPO display name
//
// Parameters: lpDisplayName - Receives the display name
// dwDisplayNameSize - Size of lpDisplayName
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
BOOL GetNewGPODisplayName (LPTSTR lpDisplayName, DWORD dwDisplayNameSize)
{
TCHAR szName[256];
LONG lResult;
HKEY hKey;
DWORD dwSize, dwType;
//
// Load the default string
//
LoadString(g_hInstance, IDS_NEWGPO, szName, ARRAYSIZE(szName));
//
// Check for a user preference
//
lResult = RegOpenKeyEx (HKEY_CURRENT_USER, GPE_KEY, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS)
{
dwSize = sizeof(szName);
RegQueryValueEx (hKey, GPO_DISPLAY_NAME_VALUE, NULL, &dwType,
(LPBYTE) szName, &dwSize);
RegCloseKey (hKey);
}
//
// Check for a user policy
//
lResult = RegOpenKeyEx (HKEY_CURRENT_USER, GPE_POLICIES_KEY, 0, KEY_READ, &hKey);
if (lResult == ERROR_SUCCESS)
{
dwSize = sizeof(szName);
RegQueryValueEx (hKey, GPO_DISPLAY_NAME_VALUE, NULL, &dwType,
(LPBYTE) szName, &dwSize);
RegCloseKey (hKey);
}
//
// Expand the string to resolve any environment variables
//
if (!ExpandEnvironmentStrings (szName, lpDisplayName, dwDisplayNameSize))
{
return FALSE;
}
return TRUE;
}
HRESULT GetWMIFilterName (LPTSTR lpFilter, BOOL bDSFormat, BOOL bRetRsopFormat, LPTSTR *lpName)
{
IWbemLocator * pLocator = NULL;
IWbemServices * pNamespace = NULL;
IWbemClassObject *pObject = NULL;
BSTR bstrParam = NULL;
BSTR bstrObject = NULL;
HRESULT hr;
LPTSTR lpID, lpDSPath, lpTemp, lpFullFilter = NULL, lpObject = NULL;
LPTSTR lpDomain = NULL;
ULONG ulNoChars;
*lpName = NULL;
hr = E_OUTOFMEMORY;
if (bDSFormat)
{
//
// Parse the filter path
//
ulNoChars = lstrlen(lpFilter) + 1;
lpFullFilter = new TCHAR [ulNoChars];
if (!lpFullFilter)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for full filter path")));
goto Cleanup;
}
hr = StringCchCopy (lpFullFilter, ulNoChars, lpFilter);
ASSERT(SUCCEEDED(hr));
lpTemp = lpFullFilter;
//
// Skip over the opening [ character
//
lpTemp++;
lpDSPath = lpTemp;
//
// Find the semi-colon. This is the end of the DS Path
//
while (*lpTemp && (*lpTemp != TEXT(';')))
lpTemp++;
if (!(*lpTemp))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Filter parsing problem")));
goto Cleanup;
}
*lpTemp = TEXT('\0');
lpTemp++;
//
// Next is the ID (a guid). Find the next semi-colon and the ID is complete
//
lpID = lpTemp;
while (*lpTemp && (*lpTemp != TEXT(';')))
lpTemp++;
if (!(*lpTemp))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Filter parsing problem")));
goto Cleanup;
}
*lpTemp = TEXT('\0');
//
// Now build the query
//
ulNoChars = lstrlen(lpDSPath) + lstrlen(lpID) + 50;
lpObject = new TCHAR [ulNoChars];
if (!lpObject)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path")));
goto Cleanup;
}
hr = StringCchPrintf (lpObject, ulNoChars, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to copy object path")));
goto Cleanup;
}
}
else
{
//
// The filter is already in the correct format. Just dup it and go.
//
ulNoChars = lstrlen(lpFilter) + 1;
lpObject = new TCHAR [ulNoChars];
if (!lpObject)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path")));
goto Cleanup;
}
hr = StringCchCopy (lpObject, ulNoChars, lpFilter);
ASSERT(SUCCEEDED(hr));
}
//
// Get a locator instance
//
hr = CoCreateInstance(CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(LPVOID *) &pLocator);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: CoCreateInstance failed with 0x%x"), hr));
goto Cleanup;
}
//
// Build a path to the policy provider
//
bstrParam = SysAllocString(TEXT("\\\\.\\root\\policy"));
if (!bstrParam)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate bstr for namespace path")));
goto Cleanup;
}
//
// Connect to the namespace
//
hr = pLocator->ConnectServer(bstrParam,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&pNamespace);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: ConnectServer failed with 0x%x"), hr));
goto Cleanup;
}
//
// Set the proper security to prevent the GetObject call from failing and to enable encryption
//
hr = CoSetProxyBlanket(pNamespace,
RPC_C_AUTHN_DEFAULT,
RPC_C_AUTHZ_DEFAULT,
COLE_DEFAULT_PRINCIPAL,
RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
RPC_C_IMP_LEVEL_IMPERSONATE,
NULL,
0);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: CoSetProxyBlanket failed with 0x%x"), hr));
goto Cleanup;
}
bstrObject = SysAllocString(lpObject);
if (!bstrObject)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate bstr for namespace path")));
goto Cleanup;
}
hr = pNamespace->GetObject(bstrObject,
WBEM_FLAG_RETURN_WBEM_COMPLETE,
NULL,
&pObject,
NULL);
if (FAILED(hr))
{
TCHAR szDefault[100];
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetObject for %s failed with 0x%x"), bstrObject, hr));
goto Cleanup;
}
hr = GetParameter(pObject, TEXT("Name"), *lpName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetParameter failed with 0x%x"), hr));
}
if (bRetRsopFormat) {
LPTSTR lpTemp1;
TCHAR szRsopQueryFormat[200];
hr = GetParameter(pObject, TEXT("Domain"), lpDomain);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetParameter failed with 0x%x"), hr));
}
if (lpDomain) {
szRsopQueryFormat[0] = TEXT('\0');
LoadString(g_hInstance, IDS_RSOPWMIQRYFMT, szRsopQueryFormat, ARRAYSIZE(szRsopQueryFormat));
ulNoChars = lstrlen(szRsopQueryFormat)+lstrlen(*lpName)+lstrlen(lpDomain)+2;
lpTemp1 = new TCHAR[ulNoChars];
if (!lpTemp1) {
hr = HRESULT_FROM_WIN32(GetLastError());
delete [] *lpName;
*lpName = NULL;
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to allocate memory with 0x%x"), hr));
goto Cleanup;
}
hr = StringCchPrintf(lpTemp1,
ulNoChars,
szRsopQueryFormat,
*lpName,
lpDomain);
if (FAILED(hr))
{
delete [] *lpName;
*lpName = NULL;
delete [] lpTemp1;
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to copy rsop query with 0x%x"), hr));
goto Cleanup;
}
delete [] *lpName;
*lpName = lpTemp1;
delete [] lpDomain;
}
}
Cleanup:
SysFreeString(bstrParam);
if (pObject)
{
pObject->Release();
}
if (pNamespace)
{
pNamespace->Release();
}
if (pLocator)
{
pLocator->Release();
}
if (bstrParam)
{
SysFreeString (bstrParam);
}
if (bstrObject)
{
SysFreeString (bstrParam);
}
if (lpFullFilter)
{
delete [] lpFullFilter;
}
if (lpObject)
{
delete [] lpObject;
}
return hr;
}
//*************************************************************
//
// GetWMIFilter()
//
// Purpose: Displays the WMI filter UI and returns back a dspath, id,
// and friendly display name if the user selects OK.
//
// Parameters: bBrowser - Browser or full manager.
// hwndParent - Hwnd of parent window
// bDSFormat - Boolean that states DS vs WMI format
// lpDisplayName - Address of pointer to friendly display name
// lpFilter - Address of pointer to filter
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Notes: The filter is returned in either DS or WMI format.
// The DS format is: [DSPath;id;flags] flags is always 0
// The WMI format is: MSFT_SomFilter.ID="<id>",Domain="<context>"
//
//*************************************************************
BOOL GetWMIFilter( BOOL bBrowser,
HWND hwndParent,
BOOL bDSFormat,
LPTSTR *lpDisplayName,
LPTSTR * lpFilter,
BSTR bstrDomain )
{
HRESULT hr;
VARIANT var;
IWMIFilterManager * pWMIFilterManager;
IWbemClassObject * pFilter;
LPTSTR lpName = NULL, lpDSPath = NULL, lpID = NULL;
VariantInit (&var);
//
// Display the appropriate WMI filter UI
//
hr = CoCreateInstance (CLSID_WMIFilterManager, NULL,
CLSCTX_SERVER, IID_IWMIFilterManager,
(void**)&pWMIFilterManager);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: CoCreateInstance failed with 0x%x."),hr));
return FALSE;
}
if (bBrowser)
{
hr = pWMIFilterManager->RunBrowser( hwndParent,
bstrDomain,
&var );
}
else
{
hr = pWMIFilterManager->RunManager( hwndParent,
bstrDomain,
&var);
}
pWMIFilterManager->Release();
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: RunBrowser / RunManager failed with 0x%x."),hr));
return FALSE;
}
if (hr == S_FALSE)
{
if (*lpFilter) {
hr = GetWMIFilterName (*lpFilter, TRUE, FALSE, lpDisplayName);
if (!(*lpDisplayName)) {
DebugMsg((DM_VERBOSE, TEXT("GetWMIFilter: Currently attached WMI filter doesn't exist.")));
if (hwndParent)
{
ReportError(hwndParent, 0, IDS_WMIFILTERFORCEDNONE);
}
delete [] *lpFilter;
*lpFilter = NULL;
}
}
return TRUE;
}
if (var.vt != VT_UNKNOWN)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: variant isn't of type VT_UNKNOWN.")));
VariantClear (&var);
return FALSE;
}
//
// Get the IWbemClassobject interface pointer
//
hr = var.punkVal->QueryInterface (IID_IWbemClassObject, (void**)&pFilter);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: QueryInterface failed with 0x%x."),hr));
VariantClear (&var);
return FALSE;
}
//
// Get the display name
//
hr = GetParameter (pFilter, TEXT("Name"), lpName);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for Name failed with 0x%x."),hr));
pFilter->Release();
VariantClear (&var);
return FALSE;
}
//
// Get the DS Path (Domain)
//
hr = GetParameter (pFilter, TEXT("Domain"), lpDSPath);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for DsContext failed with 0x%x."),hr));
delete [] lpName;
pFilter->Release();
VariantClear (&var);
return FALSE;
}
//
// Get the ID
//
hr = GetParameter (pFilter, TEXT("ID"), lpID);
if (FAILED(hr))
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: GetParameter for ID failed with 0x%x."),hr));
delete [] lpDSPath;
delete [] lpName;
pFilter->Release();
VariantClear (&var);
return FALSE;
}
//
// Put the path together
//
LPTSTR lpTemp = NULL;
ULONG ulNoChars = lstrlen(lpDSPath) + lstrlen(lpID) + 50;
lpTemp = new TCHAR[ulNoChars];
if (!lpTemp)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilter: New failed")));
delete [] lpID;
delete [] lpDSPath;
delete [] lpName;
pFilter->Release();
VariantClear (&var);
return FALSE;
}
if (bDSFormat)
{
hr = StringCchPrintf (lpTemp, ulNoChars, TEXT("[%s;%s;0]"), lpDSPath, lpID);
}
else
{
hr = StringCchPrintf (lpTemp, ulNoChars, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath);
}
//
// Save the display name
//
delete [] lpID;
delete [] lpDSPath;
pFilter->Release();
VariantClear (&var);
if (SUCCEEDED(hr))
{
*lpDisplayName = lpName;
delete [] *lpFilter;
*lpFilter = lpTemp;
DebugMsg((DM_VERBOSE, TEXT("GetWMIFilter: Name: %s Filter: %s"), *lpDisplayName, *lpFilter));
return TRUE;
}
else
{
delete [] lpTemp;
delete [] lpName;
return FALSE;
}
}
//*************************************************************
//
// GetWMIFilterDisplayName()
//
// Purpose: Gets the friendly display name for the specified
// WMI filter link
//
// Parameters: lpFilter - filter string
// bDSFormat - in ds format or wmi format
//
//
// Return: Pointer to display name if successful
// NULL if an error occurs
//
//*************************************************************
LPTSTR GetWMIFilterDisplayName (HWND hParent, LPTSTR lpFilter, BOOL bDSFormat, BOOL bRetRsopFormat)
{
LPTSTR lpName = NULL;
HRESULT hr;
hr = GetWMIFilterName(lpFilter, bDSFormat, bRetRsopFormat, &lpName);
if (FAILED(hr) || (lpName == NULL ) || ((*lpName) == NULL)) {
TCHAR szDefault[100];
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: GetObject for %s failed with 0x%x"), lpFilter, hr));
if (hParent)
{
ReportError(hParent, hr, IDS_WMIFILTERMISSING);
}
LoadString(g_hInstance, IDS_MISSINGFILTER, szDefault, ARRAYSIZE(szDefault));
ULONG ulNoChars = lstrlen(szDefault) + 1;
lpName = new TCHAR [ulNoChars];
if (!lpName)
{
DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for default name")));
goto Cleanup;
}
hr = StringCchCopy (lpName, ulNoChars, szDefault);
ASSERT(SUCCEEDED(hr));
}
Cleanup:
return lpName;
}
//*************************************************************
//
// SaveString()
//
// Purpose: Saves the given string to the stream
//
// Parameters:
//
//
// Return: TRUE if successful
// FALSE if an error occurs
//
//*************************************************************
HRESULT SaveString(IStream *pStm, LPTSTR lpString)
{
ULONG nBytesWritten;
DWORD dwBufferSize;
HRESULT hr;
//
// Check to see if there is a string to save or what its length is
//
if ( lpString == NULL )
{
dwBufferSize = 0;
}
else
{
dwBufferSize = ( lstrlen (lpString) + 1 ) * sizeof(TCHAR);
}
//
// Save the buffer size - (string length+1)*sizeof(TCHAR)
//
hr = pStm->Write(&dwBufferSize, sizeof(dwBufferSize), &nBytesWritten);
if ((hr != S_OK) || (nBytesWritten != sizeof(dwBufferSize)))
{
DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string length with %d."), hr));
goto Exit;
}
//
// Save the string
//
if ( dwBufferSize != 0 )
{
hr = pStm->Write(lpString, dwBufferSize, &nBytesWritten);
if ((hr != S_OK) || (nBytesWritten != dwBufferSize))
{
DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string with %d."), hr));
goto Exit;
}
}
Exit:
return hr;
}
HRESULT ReadString(IStream *pStm, LPTSTR *lpString, BOOL bUseLocalAlloc /*= FALSE*/)
{
HRESULT hr;
DWORD dwBufferSize;
ULONG nBytesRead;
//
// Read in the buffer size - (string length+1)*sizeof(TCHAR)
//
hr = pStm->Read(&dwBufferSize, sizeof(dwBufferSize), &nBytesRead);
if ((hr != S_OK) || (nBytesRead != sizeof(dwBufferSize)))
{
DebugMsg((DM_WARNING, TEXT("ReadString: Failed to read string size with 0x%x."), hr));
hr = E_FAIL;
goto Exit;
}
//
// Read in the string if there is one
//
if (dwBufferSize > 0)
{
if ( bUseLocalAlloc )
{
*lpString = (TCHAR*)LocalAlloc( LPTR, dwBufferSize );
}
else
{
*lpString = new TCHAR[(dwBufferSize/sizeof(TCHAR))];
}
if (!(*lpString))
{
DebugMsg((DM_WARNING, TEXT("ReadString: Failed to allocate memory with %d."),
GetLastError()));
hr = E_FAIL;
goto Exit;
}
hr = pStm->Read(*lpString, dwBufferSize, &nBytesRead);
if ((hr != S_OK) || (nBytesRead != dwBufferSize))
{
DebugMsg((DM_WARNING, TEXT("ReadString: Failed to read String with 0x%x."), hr));
hr = E_FAIL;
if ( bUseLocalAlloc )
{
LocalFree( *lpString );
}
else
{
delete [] (*lpString);
}
*lpString = NULL;
goto Exit;
}
DebugMsg((DM_VERBOSE, TEXT("ReadString: String is: <%s>"), *lpString));
}
Exit:
return hr;
}
//*************************************************************
//
// GetSiteFriendlyName()
//
// Purpose: Returns the sites friendly name
//
// Parameters:
//
// szSitePath - Path to the site
// pszSiteName - Friendly name of the site
//
// Return: currently it always returns true, if it
// couldn't get the sitename, returns itself
//
//*************************************************************
BOOL GetSiteFriendlyName (LPWSTR szSitePath, LPWSTR *pszSiteName)
{
HRESULT hr;
ULONG ulNoChars;
ULONG ulNoCharsSiteName;
ulNoCharsSiteName = wcslen(szSitePath)+1;
*pszSiteName = new WCHAR[ulNoCharsSiteName];
if (!*pszSiteName) {
return FALSE;
}
LPWSTR szData;
//
// Build the LDAP path (serverless)
//
ulNoChars = wcslen(szSitePath)+1+7;
szData = new WCHAR[ulNoChars];
if (szData)
{
hr = StringCchCopy(szData, ulNoChars, TEXT("LDAP://"));
if (SUCCEEDED(hr))
{
hr = StringCchCat(szData, ulNoChars, szSitePath);
}
if (SUCCEEDED(hr))
{
//
// Setup the default friendly name
//
if (*pszSiteName)
{
hr = StringCchCopy(*pszSiteName, ulNoCharsSiteName, szSitePath);
}
}
if (FAILED(hr))
{
delete [] *pszSiteName;
*pszSiteName= NULL;
delete [] szData;
return FALSE;
}
//
// Bind to the site object in the DS to try and get the
// real friendly name
//
IADs * pADs = NULL;
hr = OpenDSObject(szData, IID_IADs, (void **)&pADs);
if (SUCCEEDED(hr))
{
VARIANT varName;
BSTR bstrNameProp;
VariantInit(&varName);
bstrNameProp = SysAllocString(SITE_NAME_PROPERTY);
if (bstrNameProp)
{
hr = pADs->Get(bstrNameProp, &varName);
if (SUCCEEDED(hr))
{
ulNoChars = wcslen(varName.bstrVal) + 1;
LPOLESTR sz = new OLECHAR[ulNoChars];
if (sz)
{
hr = StringCchCopy(sz, ulNoChars, varName.bstrVal);
ASSERT(SUCCEEDED(hr));
if (*pszSiteName)
{
delete [] *pszSiteName;
}
*pszSiteName = sz;
}
}
SysFreeString(bstrNameProp);
}
VariantClear(&varName);
pADs->Release();
}
delete [] szData;
}
return TRUE;
}
//*************************************************************
//
// SetSysvolSecurityFromDSSecurity
//
// Purpose: Convert a DS security access list into a
// file system security access list and actually
// set the security
//
// Parameters:
//
// lpFileSysPath - Path to the gpo subdirectory on the sysvol
// si - information regarding which portion of the security
// descriptor to apply
// pSD DS security descriptor to set on the pFileSysPath directory
//
// Return: ERROR_SUCCESS if successful, other Win32 failure code otherwise
//
//*************************************************************
DWORD
SetSysvolSecurityFromDSSecurity(
LPTSTR lpFileSysPath,
SECURITY_INFORMATION si,
PSECURITY_DESCRIPTOR pSD
)
{
PACL pSacl = NULL, pDacl = NULL;
PSID psidOwner = NULL, psidGroup = NULL;
BOOL bAclPresent, bDefaulted;
DWORD dwResult;
//
// Get the DACL
//
if (si & DACL_SECURITY_INFORMATION)
{
if (!GetSecurityDescriptorDacl (pSD, &bAclPresent, &pDacl, &bDefaulted))
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: GetSecurityDescriptorDacl failed with %d"),
dwResult));
goto Exit;
}
}
//
// Get the SACL
//
if (si & SACL_SECURITY_INFORMATION)
{
if (!GetSecurityDescriptorSacl (pSD, &bAclPresent, &pSacl, &bDefaulted))
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: GetSecurityDescriptorSacl failed with %d"),
dwResult));
goto Exit;
}
}
//
// Get the owner
//
if (si & OWNER_SECURITY_INFORMATION)
{
if (!GetSecurityDescriptorOwner (pSD, &psidOwner, &bDefaulted))
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: GetSecurityDescriptorOwner failed with %d"),
dwResult));
goto Exit;
}
}
//
// Get the group
//
if (si & GROUP_SECURITY_INFORMATION)
{
if (!GetSecurityDescriptorGroup (pSD, &psidGroup, &bDefaulted))
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: GetSecurityDescriptorGroup failed with %d"),
dwResult));
goto Exit;
}
}
//
// Convert the DS access control lists into file system
// access control lists
//
if (pDacl)
{
dwResult = MapSecurityRights (pDacl);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: MapSecurityRights for the DACL failed with %d"),
dwResult));
goto Exit;
}
}
if (pSacl)
{
dwResult = MapSecurityRights (pSacl);
if (dwResult != ERROR_SUCCESS)
{
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::SetSysvolSecurity: MapSecurityRights for the SACL failed with %d"),
dwResult));
goto Exit;
}
}
//
// Switch to using the PROTECTED_DACL_SECURITY_INFORMATION and
// PROTECTED_SACL_SECURITY_INFORMATION flags so that this subdirectory
// does not inherit settings from it's parent (aka: "protect" it)
//
if (si & DACL_SECURITY_INFORMATION)
{
si |= PROTECTED_DACL_SECURITY_INFORMATION;
}
if (si & SACL_SECURITY_INFORMATION)
{
si |= PROTECTED_SACL_SECURITY_INFORMATION;
}
//
// Set the access control information for the file system portion
//
dwResult = SetNamedSecurityInfo(lpFileSysPath, SE_FILE_OBJECT, si, psidOwner,
psidGroup, pDacl, pSacl);
Exit:
return dwResult;
}
//*************************************************************
//
// MapSecurityRights
//
// Purpose: Convert a DS security access list into a
// file system security access list
//
// Parameters:
//
// PACL -- on input, the DS security access list to convert
// on output, it is converted to a file system acl
//
// Return: ERROR_SUCCESS if successful, other Win32 failure code otherwise
//
//*************************************************************
DWORD
MapSecurityRights (PACL pAcl)
{
WORD wIndex;
DWORD dwResult = ERROR_SUCCESS;
ACE_HEADER *pAceHeader;
PACCESS_ALLOWED_ACE pAce;
PACCESS_ALLOWED_OBJECT_ACE pObjectAce;
ACCESS_MASK AccessMask;
#if DBG
PSID pSid;
TCHAR szName[150], szDomain[100];
DWORD dwName, dwDomain;
SID_NAME_USE SidUse;
#endif
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: ACL contains %d ACEs"), pAcl->AceCount));
//
// Loop through the ACL looking at each ACE entry
//
for (wIndex = 0; wIndex < pAcl->AceCount; wIndex++)
{
if (!GetAce (pAcl, (DWORD)wIndex, (LPVOID *)&pAceHeader))
{
dwResult = GetLastError();
DebugMsg((DM_WARNING, TEXT("CGroupPolicyObject::MapSecurityRights: GetAce failed with %d"),
dwResult));
goto Exit;
}
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: ==================")));
switch (pAceHeader->AceType)
{
case ACCESS_ALLOWED_ACE_TYPE:
case ACCESS_DENIED_ACE_TYPE:
case SYSTEM_AUDIT_ACE_TYPE:
{
pAce = (PACCESS_ALLOWED_ACE) pAceHeader;
#if DBG
pSid = (PSID) &pAce->SidStart;
dwName = ARRAYSIZE(szName);
dwDomain = ARRAYSIZE(szDomain);
if (LookupAccountSid (NULL, pSid, szName, &dwName, szDomain,
&dwDomain, &SidUse))
{
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Normal ACE entry for: Name = %s Domain = %s"),
szName, szDomain));
}
#endif
AccessMask = pAce->Mask;
pAce->Mask &= STANDARD_RIGHTS_ALL;
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: DS access mask is 0x%x"),
AccessMask));
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Corresponding sysvol permissions follow:")));
//
// Read
//
if ((AccessMask & ACTRL_DS_READ_PROP) &&
(AccessMask & ACTRL_DS_LIST))
{
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Granting Read permission")));
pAce->Mask |= (SYNCHRONIZE | FILE_LIST_DIRECTORY |
FILE_READ_ATTRIBUTES | FILE_READ_EA |
FILE_READ_DATA | FILE_EXECUTE);
}
//
// Write
//
if (AccessMask & ACTRL_DS_WRITE_PROP)
{
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Granting Write permission")));
pAce->Mask |= (SYNCHRONIZE | FILE_WRITE_DATA |
FILE_APPEND_DATA | FILE_WRITE_EA |
FILE_WRITE_ATTRIBUTES | FILE_ADD_FILE |
FILE_ADD_SUBDIRECTORY);
}
//
// Misc
//
if (AccessMask & ACTRL_DS_CREATE_CHILD)
{
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Granting directory creation permission")));
pAce->Mask |= (FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE);
}
if (AccessMask & ACTRL_DS_DELETE_CHILD)
{
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Granting directory delete permission")));
pAce->Mask |= FILE_DELETE_CHILD;
}
//
// Inheritance
//
pAceHeader->AceFlags |= (OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE);
}
break;
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
case ACCESS_DENIED_OBJECT_ACE_TYPE:
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Clearing access mask in DS object ACE entry")));
pObjectAce = (PACCESS_ALLOWED_OBJECT_ACE) pAceHeader;
pObjectAce->Mask = 0;
break;
default:
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: Unknown ACE type 0x%x"), pAceHeader->AceType));
break;
}
DebugMsg((DM_VERBOSE, TEXT("CGroupPolicyObject::MapSecurityRights: ==================")));
}
Exit:
return dwResult;
}
BOOL GetStringSid(LPTSTR szSamName, LPTSTR *szStringSid)
{
const DOMAIN_BUFFER_LEN_IN_CHARS = 64;
const SID_BUFFER_LEN = 256;
PSID pSid = NULL;
LPWSTR szDomain = NULL;
ULONG uDomainLen = 0;
SID_NAME_USE snuSidType;
BOOL bIsSid = FALSE;
ULONG uSidLen = 0;
BOOL bRet = FALSE;
uSidLen = SID_BUFFER_LEN;
pSid = (SID*) LocalAlloc(LPTR, uSidLen);
if (!pSid) {
DebugMsg((DM_WARNING, L"GetStringSid: LocalAlloc failed."));
goto Exit;
}
uDomainLen = DOMAIN_BUFFER_LEN_IN_CHARS;
szDomain = (LPWSTR) LocalAlloc(LPTR, uDomainLen * sizeof(WCHAR));
if (!szDomain) {
DebugMsg((DM_WARNING, L"GetStringSid: LocalAlloc failed."));
goto Exit;
}
//
// Translate SID. A lot of the out parameters, we don't need, but LookupAccountSid
// can't seem to handle them being NULL.
//
if (!LookupAccountName(NULL, szSamName, pSid, &uSidLen, szDomain, &uDomainLen, &snuSidType)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
//
// Try again with the given buffer sizes.
//
// pSid and szDomain are smart pointers and the orig value will get freed
LocalFree(pSid);
pSid = NULL;
LocalFree(szDomain);
szDomain = NULL;
pSid = (SID*) LocalAlloc(LPTR, uSidLen);
if (!pSid) {
DebugMsg((DM_WARNING, L"GetStringSid: LocalAlloc failed."));
goto Exit;
}
szDomain = (LPWSTR) LocalAlloc(LPTR, uDomainLen * sizeof(WCHAR));
if (!szDomain) {
DebugMsg((DM_WARNING, L"GetStringSid: LocalAlloc failed."));
goto Exit;
}
if (!LookupAccountName(NULL, szSamName, pSid, &uSidLen, szDomain, &uDomainLen, &snuSidType)) {
DebugMsg((DM_WARNING, L"GetStringSid: LookupAccountSid failed with %d.", GetLastError()));
goto Exit;
}
}
else {
DebugMsg((DM_WARNING, L"GetStringSid: LookupAccountSid failed with %d.", GetLastError()));
goto Exit;
}
}
//
// Convert SID to string.
//
if (!ConvertSidToStringSid(pSid, szStringSid)) {
DebugMsg((DM_WARNING, L"GetStringSid: ConvertSidToStringSid failed with %d.", GetLastError()));
goto Exit;
}
bRet = TRUE;
Exit:
if (szDomain) {
LocalFree(szDomain);
}
if (pSid) {
LocalFree(pSid);
}
return bRet;
}
BOOL GetUserNameFromStringSid(LPTSTR szStringSid, LPTSTR *szSamName)
{
const DOMAIN_BUFFER_LEN_IN_CHARS = 64;
const SID_BUFFER_LEN = 256;
const NAME_BUFFER_LEN_IN_CHARS = 64;
LPWSTR szName = NULL;
PSID pSid = NULL;
LPWSTR szDomain = NULL;
ULONG uDomainLen = 0;
SID_NAME_USE snuSidType;
BOOL bIsSid = FALSE;
ULONG uSidLen = 0;
ULONG uNameLen = 0;
BOOL bRet = FALSE;
ULONG ulNoChars;
HRESULT hr;
if (!ConvertStringSidToSid(szStringSid, &pSid))
{
DebugMsg((DM_WARNING, L"GetNameFromStringSid: Cannot ."));
goto Exit;
}
//
// Allocate buffers to map to name.
//
uNameLen = NAME_BUFFER_LEN_IN_CHARS;
szName = (LPWSTR) LocalAlloc(LPTR, uNameLen * sizeof(WCHAR));
if (!szName) {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LocalAlloc failed."));
goto Exit;
}
uDomainLen = DOMAIN_BUFFER_LEN_IN_CHARS;
szDomain = (LPWSTR) LocalAlloc(LPTR, uDomainLen * sizeof(WCHAR));
if (!szDomain) {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LocalAlloc failed."));
goto Exit;
}
//
// Translate SID. A lot of the out parameters, we don't need, but LookupAccountSid
// can't seem to handle them being NULL.
//
if (!LookupAccountSid(NULL, (SID *)pSid, szName, &uNameLen, szDomain, &uDomainLen, &snuSidType)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
//
// Try again with the given buffer sizes.
//
// szName and szDomain are smart pointers and the orig value will get freed
LocalFree(szName);
szName = NULL;
LocalFree(szDomain);
szDomain = NULL;
szName = (LPWSTR) LocalAlloc(LPTR, uNameLen * sizeof(WCHAR));
if (!szName) {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LocalAlloc failed."));
goto Exit;
}
szDomain = (LPWSTR) LocalAlloc(LPTR, uDomainLen * sizeof(WCHAR));
if (!szDomain) {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LocalAlloc failed."));
goto Exit;
}
if (!LookupAccountSid(NULL, pSid, szName, &uNameLen, szDomain, &uDomainLen, &snuSidType)) {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LookupAccountSid failed with 0x%x.", GetLastError()));
goto Exit;
}
}
else {
DebugMsg((DM_WARNING, L"GetNameFromStringSid: LookupAccountSid failed with 0x%x.", GetLastError()));
goto Exit;
}
}
// space for domain\\username
hr = S_OK;
ulNoChars = lstrlen(szName) + (szDomain ? lstrlen(szDomain) : 1) + 3;
*szSamName = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*ulNoChars);
if (!(*szSamName))
{
DebugMsg((DM_WARNING, L"GetNameFromStringSid: failed to allocate memory for samname with 0x%x.", GetLastError()));
goto Exit;
}
if (szDomain && szDomain[0])
{
hr = StringCchCopy((*szSamName), ulNoChars, szDomain);
if (SUCCEEDED(hr))
{
hr = StringCchCat ((*szSamName), ulNoChars, L"\\");
}
}
if (SUCCEEDED(hr))
{
hr = StringCchCat((*szSamName), ulNoChars, szName);
}
if (SUCCEEDED(hr))
{
bRet = TRUE;
}
else
{
DebugMsg((DM_WARNING, L"GetNameFromStringSid: failed to copy sam name with 0x%x.", hr));
LocalFree(*szSamName);
*szSamName = NULL;
goto Exit;
}
Exit:
if (szDomain) {
LocalFree(szDomain);
}
if (szName) {
LocalFree(szName);
}
if (pSid) {
LocalFree(pSid);
}
return bRet;
}
HRESULT UnEscapeLdapPath(LPWSTR szDN, LPWSTR *szUnEscapedPath)
/*++
Routine Description:
Unescapes the given ldap path and returns. Note that the input is LPWSTR
and output is BSTR. Also input should not be prefixed with LDAP:// and output
also will not be prefixxed with LDAP://
Arguments:
[in] szDN - The LDAP path to the object to escape
[out] pbstrEscapedPath - Escaped path
Return Value:
S_OK on success. Error code otherwise
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;
IADsPathname *pADsPath = NULL;
BSTR bstrPath = NULL;
BSTR bstrUnescapedPath = NULL;
*szUnEscapedPath = NULL;
//
// Initialize path
//
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (void**) &pADsPath);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: CoCreateInstance failed with 0x%x"), hr));
goto Exit;
}
bstrPath = SysAllocString(szDN);
if (!bstrPath) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: BSTR allocation failed")));
hr = E_OUTOFMEMORY;
goto Exit;
}
hr = pADsPath->put_EscapedMode(ADS_ESCAPEDMODE_ON);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: Failed to set escaped mode(1) with 0x%x"), hr));
goto Exit;
}
hr = pADsPath->Set(bstrPath, ADS_SETTYPE_DN);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: Set failed with 0x%x"), hr));
goto Exit;
}
//
// Set the escape mode
//
hr = pADsPath->put_EscapedMode(ADS_ESCAPEDMODE_OFF);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: Failed to set escaped mode with 0x%x"), hr));
goto Exit;
}
hr = pADsPath->Retrieve(ADS_FORMAT_X500_DN, &bstrUnescapedPath);
if (FAILED(hr)) {
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: Retrieve failed with 0x%x"), hr));
goto Exit;
}
ULONG ulNoChars = lstrlen(bstrUnescapedPath)+1;
*szUnEscapedPath = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*ulNoChars);
if (!(*szUnEscapedPath))
{
hr = E_OUTOFMEMORY;
DebugMsg((DM_WARNING, TEXT("EscapeLdapPath: Failed to allocate memory with 0x%x"), hr));
goto Exit;
}
hr = StringCchCopy(*szUnEscapedPath, ulNoChars, bstrUnescapedPath);
ASSERT(SUCCEEDED(hr));
Exit:
if (bstrPath)
{
SysFreeString(bstrPath);
}
if (bstrUnescapedPath)
{
SysFreeString(bstrUnescapedPath);
}
if (pADsPath)
{
pADsPath->Release();
}
return S_OK;
}
#if !defined(_WIN64)
/*+-------------------------------------------------------------------------*
* IsWin64
*
* Returns true if we're running on Win64, false otherwise.
*--------------------------------------------------------------------------*/
bool IsWin64()
{
/*
* get a pointer to kernel32!GetSystemWow64Directory
*/
bool bWin64 = false;
DWORD LastError = GetLastError();
HMODULE hmod = GetModuleHandle (_T("kernel32.dll"));
if (hmod == NULL)
goto IsWin64_Exit;
UINT (WINAPI* pfnGetSystemWow64Directory)(LPTSTR, UINT);
(FARPROC&)pfnGetSystemWow64Directory = GetProcAddress (hmod, "GetSystemWow64DirectoryW");
if (pfnGetSystemWow64Directory == NULL)
goto IsWin64_Exit;
/*
* if GetSystemWow64Directory fails and sets the last error to
* ERROR_CALL_NOT_IMPLEMENTED, we're on a 32-bit OS
*/
TCHAR szWow64Dir[MAX_PATH];
if (((pfnGetSystemWow64Directory)(szWow64Dir, ARRAYSIZE(szWow64Dir)) == 0) &&
(GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
{
goto IsWin64_Exit;
}
/*
* if we get here, we're on Win64
*/
bWin64 = true;
IsWin64_Exit:
SetLastError(LastError);
return bWin64;
}
#endif // !defined(_WIN64)