|
|
#include "main.h"
#include <schemamanager.h>
#include "rsoputil.h"
#include <initguid.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; }
//*************************************************************
//
// RegDelnodeRecurse()
//
// Purpose: Deletes a registry key and all it's subkeys / values.
// Called by RegDelnode
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL RegDelnodeRecurse (HKEY hKeyRoot, LPTSTR lpSubKey) { LPTSTR lpEnd; LONG lResult; DWORD dwSize; TCHAR szName[MAX_PATH]; HKEY hKey; FILETIME ftWrite;
//
// First, see if we can delete the key without having
// to recurse.
//
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS) { return TRUE; }
lResult = RegOpenKeyEx (hKeyRoot, lpSubKey, 0, KEY_READ, &hKey);
if (lResult != ERROR_SUCCESS) { return FALSE; }
lpEnd = CheckSlash(lpSubKey);
//
// Enumerate the keys
//
dwSize = MAX_PATH; lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
if (lResult == ERROR_SUCCESS) {
do {
lstrcpy (lpEnd, szName);
if (!RegDelnodeRecurse(hKeyRoot, lpSubKey)) { break; }
//
// Enumerate again
//
dwSize = MAX_PATH;
lResult = RegEnumKeyEx(hKey, 0, szName, &dwSize, NULL, NULL, NULL, &ftWrite);
} while (lResult == ERROR_SUCCESS); }
lpEnd--; *lpEnd = TEXT('\0');
RegCloseKey (hKey);
//
// Try again to delete the key
//
lResult = RegDeleteKey(hKeyRoot, lpSubKey);
if (lResult == ERROR_SUCCESS) { return TRUE; }
return FALSE; }
//*************************************************************
//
// RegDelnode()
//
// Purpose: Deletes a registry key and all it's subkeys / values
//
// Parameters: hKeyRoot - Root key
// lpSubKey - SubKey to delete
//
// Return: TRUE if successful
// FALSE if an error occurs
//
// Comments:
//
// History: Date Author Comment
// 10/3/95 ericflo Created
//
//*************************************************************
BOOL RegDelnode (HKEY hKeyRoot, LPTSTR lpSubKey) { TCHAR szDelKey[2 * MAX_PATH];
lstrcpy (szDelKey, lpSubKey);
return RegDelnodeRecurse(hKeyRoot, szDelKey);
}
//*************************************************************
//
// 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[MAX_PATH]; LPTSTR lpEnd;
//
// Check for NULL pointer
//
if (!lpDirectory || !(*lpDirectory)) { DebugMsg((DM_WARNING, TEXT("CreateNestedDirectory: Received a NULL pointer."))); return 0; }
//
// First, see if we can create the directory without having
// to build parent directories.
//
if (CreateDirectory (lpDirectory, lpSecurityAttributes)) { return 1; }
//
// If this directory exists already, this is OK too.
//
if (GetLastError() == ERROR_ALREADY_EXISTS) { return ERROR_ALREADY_EXISTS; }
//
// No luck, copy the string to a buffer we can munge
//
lstrcpy (szDirectory, lpDirectory);
//
// 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)) { return 0; }
//
// Skip the slash, and find the slash between
// the share name and the directory name.
//
lpEnd++;
while (*lpEnd && *lpEnd != TEXT('\\')) { lpEnd++; }
if (!(*lpEnd)) { return 0; }
//
// 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())); return 0; } }
*lpEnd = TEXT('\\'); lpEnd++; } }
//
// Create the final directory
//
if (CreateDirectory (szDirectory, lpSecurityAttributes)) { return 1; }
if (GetLastError() == ERROR_ALREADY_EXISTS) { return ERROR_ALREADY_EXISTS; }
//
// Failed
//
DebugMsg((DM_VERBOSE, TEXT("CreateNestedDirectory: Failed to create the directory with error %d."), GetLastError()));
return 0;
}
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())); wsprintf (lpBuffer, 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[MAX_PATH]; TCHAR szErrorMsg[2*MAX_PATH+40]; va_list marker;
//
// Load the error message
//
if (!LoadString (g_hInstance, idMsg, szMsg, 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, MAX_PATH)) { return FALSE; } } } else if ( dwError == WBEM_E_INVALID_NAMESPACE ) { if (!LoadString (g_hInstance, IDS_INVALID_NAMESPACE, szMsg, MAX_PATH)) { return FALSE; } }
//
// Plug in the arguments
//
va_start(marker, idMsg); wvsprintf(szErrorMsg, 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; LPOLESTR szLink = new OLECHAR[1 + wcslen(lpNamelessGPO) + 3 + 1]; if (szLink) { wcscpy(szLink, L"["); wcscat(szLink, lpNamelessGPO); wcscat(szLink, L";0]");
VariantInit(&var); bstr = SysAllocString(GPM_LINK_PROPERTY);
if (bstr) { hr = pADs->Get(bstr, &var);
if (SUCCEEDED(hr)) { LPOLESTR szTemp = new OLECHAR[wcslen(var.bstrVal) + wcslen(szLink) + 1]; if (szTemp) { if (fHighPriority) { // Highest priority is at the END of the list
wcscpy(szTemp, var.bstrVal); wcscat(szTemp, szLink); } else { wcscpy(szTemp, szLink); wcscat(szTemp, var.bstrVal); } 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; // Build the substring to look for.
// This is the first part of the link, the link ends with ]
LPOLESTR szLink = new OLECHAR[1 + wcslen(lpGPO) + 1]; if (szLink) { wcscpy(szLink, L"["); wcscat(szLink, lpGPO);
bstr = SysAllocString(GPM_LINK_PROPERTY);
if (bstr) { VariantInit(&var);
hr = pADs->Get(bstr, &var);
if (SUCCEEDED(hr)) { // find the link and remove it
LPOLESTR sz = new OLECHAR[wcslen(var.bstrVal)+1];
if (sz) { wcscpy(sz, var.bstrVal); 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)) { hr = pADsPathname->Set(szIn, 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)) { sz = new OLECHAR[wcslen(bstr)+1]; if (sz) { wcscpy(sz, bstr); } 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)); }
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)) { hr = pADsPathname->Set(szIn, ADS_SETTYPE_DN);
if (SUCCEEDED(hr)) { BSTR bstr; BOOL fStop = FALSE;
hr = pADsPathname->Retrieve(ADS_FORMAT_LEAF, &bstr); if (SUCCEEDED(hr)) { sz = new OLECHAR[wcslen(bstr)+1]; if (sz) { wcscpy(sz, (bstr+3)); } SysFreeString(bstr); } else { DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to retrieve leaf with 0x%x."), hr)); } } else { DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: Failed to set pathname with 0x%x."), hr)); }
pADsPathname->Release(); } else { DebugMsg((DM_WARNING, TEXT("GetDomainFromLDAPPath: 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)); wsprintf (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)); lstrcpy (lpTemp->lpDomainName, lpDomainName); 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;
lpTest = (LPTSTR) LocalAlloc (LPTR, (lstrlen(lpDCName) + 25) * sizeof(TCHAR));
if (!lpTest) { DebugMsg((DM_WARNING, TEXT("TestDC: Failed to allocate memory with %d"), GetLastError())); return GetLastError(); }
lstrcpy (lpTest, TEXT("\\\\")); lstrcat (lpTest, lpDCName); lstrcat (lpTest, TEXT("\\sysvol\\*.*"));
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; }
lpTemp = (LPTSTR) LocalAlloc (LPTR, (lstrlen(pDCI->DnsForestName) + 1) * 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; }
lstrcpy(lpTemp, pDCI->DnsForestName);
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
//
lpTemp = (LPTSTR) LocalAlloc (LPTR, (lstrlen (pDCI->DomainControllerName) + 1) * 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; }
lstrcpy (lpTemp, (pDCI->DomainControllerName + 2));
//
// Remove the trailing .
//
lpEnd = lpTemp + lstrlen(lpTemp) - 1;
if (*lpEnd == TEXT('.')) { *lpEnd = TEXT('\0'); }
*lpDCName = lpTemp;
NetApiBufferFree(pDCI);
return ERROR_SUCCESS; }
//*************************************************************
//
// 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); } } } }
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) { lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
if (!lpDCName) { DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"), GetLastError())); return NULL; }
lstrcpy (lpDCName, lpInheritServer);
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) { lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
if (!lpDCName) { DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"), GetLastError())); return NULL; }
lstrcpy (lpDCName, lpInheritServer);
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) { lpDCName = (LPTSTR) LocalAlloc (LPTR, (lstrlen (lpInheritServer) + 1) * sizeof(TCHAR));
if (!lpDCName) { DebugMsg((DM_WARNING, TEXT("GetDCName: Failed to allocate memory for DC name with %d"), GetLastError())); return NULL; }
lstrcpy (lpDCName, lpInheritServer);
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 ) { wsprintf( szValue, 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
//
wsprintf (lpArgs, TEXT("/s /gphint:%d /gpobject:\"%s\""), gpHint, lpFullPath);
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;
//
// 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(hr); return NULL; }
hr = pADsPathname->Set(lpDN, ADS_SETTYPE_FULL);
if (FAILED(hr)) { DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to set <%s> in IAdsPathName object with = 0x%x"), lpDN, hr)); pADsPathname->Release(); SetLastError(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(hr); return NULL; }
//
// Allocate a new buffer for the named path including LDAP://
//
lpFullPath = (LPTSTR) LocalAlloc (LPTR, (7 + lstrlen(bstr) + (lpServer ? lstrlen(lpServer) : 0) + 3) * sizeof(TCHAR));
if (!lpFullPath) { DebugMsg((DM_WARNING, TEXT("MakeFullPath: Failed to allocate memory with = %d"), GetLastError())); SysFreeString (bstr); return NULL; }
lstrcpy (lpFullPath, TEXT("LDAP://")); if (lpServer) { lstrcat (lpFullPath, lpServer); lstrcat (lpFullPath, TEXT("/")); } lstrcat (lpFullPath, (LPTSTR)(bstr + 7));
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; }
hr = pADsPathname->Set(lpDN, ADS_SETTYPE_FULL);
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
//
lpPath = (LPTSTR) LocalAlloc (LPTR, (lstrlen(bstr) + 1) * sizeof(TCHAR));
if (!lpPath) { DebugMsg((DM_WARNING, TEXT("MakeNamelessPath: Failed to allocate memory with = %d"), GetLastError())); SysFreeString (bstr); return NULL; }
lstrcpy (lpPath, bstr);
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_USER_DEFAULT, 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 + 3) != 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 (ADsOpenObject(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;
//
// 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
//
lpSAMName = new TCHAR[(lstrlen(lpName) + 1)];
if (!lpSAMName) { DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError())); goto Exit; }
lstrcpy (lpSAMName, lpName);
//
// 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
//
lpDNName = new TCHAR[(lstrlen(pNameResultItem->pName) + 1)];
if (!lpDNName) { DebugMsg((DM_WARNING, TEXT("ConvertName: Failed to allocate memory with %d"), GetLastError())); goto Exit; }
lstrcpy (lpDNName, pNameResultItem->pName);
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
//
lpFileName = new TCHAR[(lstrlen(szTempFile) + 1)];
if (!lpFileName) { DebugMsg((DM_WARNING, TEXT("CRSOPComponentData::CreateTempFile: Failed to allocate memory for temp filename with %d"), GetLastError())); return NULL; }
lstrcpy (lpFileName, szTempFile);
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; wcscpy(szOut, TEXT("LDAP://DC=")); 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
//
hr = pADsPathname->Set (lpForest, ADS_SETTYPE_FULL);
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
//
hr = pADsPathname->AddLeafElement (TEXT("CN=Configuration"));
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));
szReturn = new OLECHAR[SysStringLen(bstrForest)+1]; lstrcpy(szReturn, bstrForest);
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;
*lpName = NULL;
hr = E_OUTOFMEMORY;
if (bDSFormat) { //
// Parse the filter path
//
lpFullFilter = new TCHAR [lstrlen(lpFilter) + 1];
if (!lpFullFilter) { DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for full filter path"))); goto Cleanup; }
lstrcpy (lpFullFilter, lpFilter);
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
//
lpObject = new TCHAR [lstrlen(lpDSPath) + lstrlen(lpID) + 50];
if (!lpObject) { DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path"))); goto Cleanup; }
wsprintf (lpObject, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath); } else { //
// The filter is already in the correct format. Just dup it and go.
//
lpObject = new TCHAR [lstrlen(lpFilter) + 1];
if (!lpObject) { DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for object path"))); goto Cleanup; }
lstrcpy (lpObject, lpFilter); }
//
// 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
//
hr = CoSetProxyBlanket(pNamespace, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_DEFAULT, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_CALL, 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));
lpTemp1 = new TCHAR[lstrlen(szRsopQueryFormat)+lstrlen(*lpName)+ lstrlen(lpDomain)+2];
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; }
wsprintf(lpTemp1, szRsopQueryFormat, *lpName, lpDomain); 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; lpTemp = new TCHAR[lstrlen(lpDSPath) + lstrlen(lpID) + 50];
if (!lpTemp) { DebugMsg((DM_WARNING, TEXT("GetWMIFilter: New failed"))); delete [] lpID; delete [] lpDSPath; delete [] lpName; pFilter->Release(); VariantClear (&var); return FALSE; }
delete [] *lpFilter; *lpFilter = lpTemp;
if (bDSFormat) { wsprintf (*lpFilter, TEXT("[%s;%s;0]"), lpDSPath, lpID); } else { wsprintf (*lpFilter, TEXT("MSFT_SomFilter.ID=\"%s\",Domain=\"%s\""), lpID, lpDSPath); }
//
// Save the display name
//
*lpDisplayName = lpName;
delete [] lpID; delete [] lpDSPath; pFilter->Release(); VariantClear (&var);
DebugMsg((DM_VERBOSE, TEXT("GetWMIFilter: Name: %s Filter: %s"), *lpDisplayName, *lpFilter));
return TRUE; }
//*************************************************************
//
// 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)) { 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));
lpName = new TCHAR [lstrlen(szDefault) + 1];
if (!lpName) { DebugMsg((DM_WARNING, TEXT("GetWMIFilterDisplayName: Failed to alloc memory for default name"))); goto Cleanup; }
lstrcpy (lpName, szDefault); }
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 dwTemp; HRESULT hr;
//
// Save the string length
//
dwTemp = lstrlen (lpString);
if (dwTemp) { dwTemp = (dwTemp + 1) * sizeof (TCHAR); }
hr = pStm->Write(&dwTemp, sizeof(dwTemp), &nBytesWritten);
if ((hr != S_OK) || (nBytesWritten != sizeof(dwTemp))) { DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string length with %d."), hr)); goto Exit; }
//
// Save the string
//
if (dwTemp) { hr = pStm->Write(lpString, dwTemp, &nBytesWritten);
if ((hr != S_OK) || (nBytesWritten != dwTemp)) { DebugMsg((DM_WARNING, TEXT("SaveString: Failed to write string with %d."), hr)); goto Exit; } }
Exit:
return hr; }
HRESULT ReadString(IStream *pStm, LPTSTR *lpString) { HRESULT hr; DWORD dwStringLen; ULONG nBytesRead;
//
// Read in the string length (including null terminator)
//
hr = pStm->Read(&dwStringLen, sizeof(dwStringLen), &nBytesRead);
if ((hr != S_OK) || (nBytesRead != sizeof(dwStringLen))) { 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 (dwStringLen > 0) {
*lpString = new TCHAR[(dwStringLen/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, dwStringLen, &nBytesRead);
if ((hr != S_OK) || (nBytesRead != dwStringLen)) { DebugMsg((DM_WARNING, TEXT("ReadString: Failed to read String with 0x%x."), hr)); hr = E_FAIL; 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) { *pszSiteName = new WCHAR[wcslen(szSitePath)+1];
if (!*pszSiteName) { return FALSE; }
LPWSTR szData;
//
// Build the LDAP path (serverless)
//
szData = new WCHAR[wcslen(szSitePath)+1+7];
if (szData) { wcscpy(szData, TEXT("LDAP://")); wcscat(szData, szSitePath);
//
// Setup the default friendly name
//
if (*pszSiteName) { wcscpy(*pszSiteName, szSitePath); }
//
// Bind to the site object in the DS to try and get the
// real friendly name
//
IADs * pADs = NULL;
HRESULT 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)) { LPOLESTR sz = new OLECHAR[wcslen(varName.bstrVal) + 1]; if (sz) { wcscpy(sz, varName.bstrVal); if (*pszSiteName) { delete [] *pszSiteName; } *pszSiteName = sz; } } SysFreeString(bstrNameProp); }
VariantClear(&varName); pADs->Release(); }
delete [] szData; }
return TRUE; }
|