|
|
#include "stdafx.h"
#pragma hdrstop
//
// registry information
//
const WCHAR c_szWinLogon[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\WinLogon";
const WCHAR c_szAutoLogon[] = L"AutoAdminLogon"; const WCHAR c_szDisableCAD[] = L"DisableCAD";
const WCHAR c_szDefUserName[] = L"DefaultUserName"; const WCHAR c_szDefDomain[] = L"DefaultDomainName"; const WCHAR c_szDefPassword[] = L"DefaultPassword";
const WCHAR c_szDefaultPwdKey[] = L"DefaultPassword";
//
// registry helpers
//
BOOL _RegSetSZ(HKEY hk, LPCWSTR pszValueName, LPCWSTR pszValue) { DWORD dwSize = lstrlen(pszValue)*SIZEOF(WCHAR); return ERROR_SUCCESS == RegSetValueEx(hk, pszValueName, 0x0, REG_SZ, (BYTE *)pszValue, dwSize); }
BOOL _RegSetDWORD(HKEY hk, LPCWSTR pszValueName, DWORD dwValue) { DWORD dwSize = SIZEOF(dwValue); return ERROR_SUCCESS == RegSetValueEx(hk, pszValueName, 0x0, REG_DWORD, (BYTE *)&dwValue, dwSize); }
BOOL _RegDelValue(HKEY hk, LPCWSTR pszValueName) { return ERROR_SUCCESS == RegDeleteValue(hk, pszValueName); }
INT_PTR CALLBACK _CredDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
LPCREDINFO pci = (LPCREDINFO)GetWindowLongPtr(hwnd, DWLP_USER);
switch ( uMsg ) { case WM_INITDIALOG: { pci = (LPCREDINFO)lParam; SetWindowLongPtr(hwnd, DWLP_USER, lParam);
SetDlgItemText(hwnd, IDC_USER, pci->pszUser); Edit_LimitText(GetDlgItem(hwnd, IDC_USER), pci->cchUser - 1);
SetDlgItemText(hwnd, IDC_DOMAIN, pci->pszDomain); Edit_LimitText(GetDlgItem(hwnd, IDC_DOMAIN), pci->cchDomain - 1);
SetDlgItemText(hwnd, IDC_PASSWORD, pci->pszPassword); Edit_LimitText(GetDlgItem(hwnd, IDC_PASSWORD), pci->cchPassword - 1);
return TRUE; }
case WM_COMMAND: { switch ( LOWORD(wParam) ) { case IDOK: { FetchText(hwnd, IDC_DOMAIN, pci->pszDomain, pci->cchDomain); FetchText(hwnd, IDC_USER, pci->pszUser, pci->cchUser);
if (StrChr(pci->pszUser, TEXT('@'))) { *(pci->pszDomain) = 0; }
GetDlgItemText(hwnd, IDC_PASSWORD, pci->pszPassword, pci->cchPassword); return EndDialog(hwnd, IDOK); }
case IDCANCEL: return EndDialog(hwnd, IDCANCEL);
case IDC_USER: { if ( HIWORD(wParam) == EN_CHANGE ) { EnableWindow(GetDlgItem(hwnd, IDOK), FetchTextLength(hwnd, IDC_USER) > 0);
EnableDomainForUPN(GetDlgItem(hwnd, IDC_USER), GetDlgItem(hwnd, IDC_DOMAIN)); } break; } } return TRUE; } }
return FALSE; }
//
// attempt to join a domain/workgroup using the specified names and OU.
//
HRESULT _AttemptJoin(HWND hwnd, DWORD dwFlags, LPCWSTR pszDomain, LPCWSTR pszUser, LPCWSTR pszUserDomain, LPCWSTR pszPassword) { HRESULT hr = S_OK;
#ifndef DONT_JOIN
TCHAR szDomainUser[MAX_DOMAINUSER + 1]; if ( pszUser ) MakeDomainUserString(pszUserDomain, pszUser, szDomainUser, ARRAYSIZE(szDomainUser));
NET_API_STATUS nas = NetJoinDomain(NULL, pszDomain, NULL, szDomainUser, pszPassword, dwFlags); if ( (nas == ERROR_ACCESS_DENIED) ) { // perhaps an account exists, but we can't delete it so try and remove
// the account create flag
if ( dwFlags & NETSETUP_ACCT_CREATE ) { dwFlags &= ~NETSETUP_ACCT_CREATE; nas = NetJoinDomain(NULL, pszDomain, NULL, szDomainUser, *pszPassword ? pszPassword : NULL, dwFlags); } }
if ( (nas != NERR_Success) && (nas != NERR_SetupAlreadyJoined) ) { TCHAR szMessage[512];
if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD) nas, 0, szMessage, ARRAYSIZE(szMessage), NULL)) LoadString(g_hinst, IDS_ERR_UNEXPECTED, szMessage, ARRAYSIZE(szMessage)); ::DisplayFormatMessage(hwnd, IDS_ERR_CAPTION, IDS_NAW_JOIN_GENERICERROR, MB_OK|MB_ICONERROR, szMessage); hr = HRESULT_FROM_WIN32(nas); } #endif
return hr; }
void _ShowDcNotFoundErrorDialog(HWND hwnd, LPCWSTR pszDomain, LPCWSTR pszTitle) { typedef void (*pfnShowDcNotFoundErrorDialog)(HWND, PCWSTR, PCWSTR); static HMODULE hNetID = NULL; static pfnShowDcNotFoundErrorDialog ShowDcNotFoundErrorDialog = NULL;
if (!hNetID) { hNetID = LoadLibrary(L"netid.dll"); }
if (hNetID) { ShowDcNotFoundErrorDialog = (pfnShowDcNotFoundErrorDialog) GetProcAddress(hNetID, "ShowDcNotFoundErrorDialog"); if (ShowDcNotFoundErrorDialog) { ShowDcNotFoundErrorDialog(hwnd, pszDomain, pszTitle); } } }
//
// Handle moving from to a workgroup or domain. To do this we are passed
// a structure containing all the information we need.
//
HRESULT JoinDomain(HWND hwnd, BOOL fDomain, LPCWSTR pszDomain, CREDINFO* pci, BOOL *pfReboot) { HRESULT hres = E_FAIL; DWORD dwFlags = 0x0; LPWSTR pszCurrentDomain = NULL; NET_API_STATUS nas; BOOL fPassedCredentials = (pci && pci->pszUser && pci->pszUser[0] && pci->pszPassword); CWaitCursor cur;
//
// lets validate the domain name before we go and use it, therefore avoiding
// orphaning the computer too badly
//
nas = NetValidateName(NULL, pszDomain, NULL, NULL, fDomain ? NetSetupDomain:NetSetupWorkgroup);
if (fDomain && (ERROR_NO_SUCH_DOMAIN == nas)) { WCHAR szTitle[256]; LoadString(g_hinst, IDS_NETWIZCAPTION, szTitle, ARRAYSIZE(szTitle));
_ShowDcNotFoundErrorDialog(hwnd, pszDomain, szTitle); return E_FAIL; }
if ( NERR_Success != nas ) { ShellMessageBox(g_hinst, hwnd, fDomain ? MAKEINTRESOURCE(IDS_ERR_BADDOMAIN) : MAKEINTRESOURCE(IDS_ERR_BADWORKGROUP), MAKEINTRESOURCE(IDS_NETWIZCAPTION), MB_OK|MB_ICONWARNING, pszDomain); return E_FAIL; }
//
// now attempt to join the domain, prompt for credentails if the ones
// specified are not good enough
//
if ( fDomain ) { dwFlags |= NETSETUP_JOIN_DOMAIN|NETSETUP_ACCT_CREATE|NETSETUP_DOMAIN_JOIN_IF_JOINED; } else { nas = NetUnjoinDomain(NULL, NULL, NULL, NETSETUP_ACCT_DELETE); if ( (nas != NERR_Success) && (nas != NERR_SetupNotJoined) ) { nas = NetUnjoinDomain(NULL, NULL, NULL, 0x0); }
if ( (nas != NERR_Success) && (nas != NERR_SetupNotJoined) ) { hres = E_UNEXPECTED; goto exit_gracefully; }
*pfReboot = TRUE; // we changed the domain
}
if ( !fDomain || fPassedCredentials) { if (fPassedCredentials) { hres = _AttemptJoin(hwnd, dwFlags, pszDomain, pci->pszUser, pci->pszDomain, pci->pszPassword); } else { hres = _AttemptJoin(hwnd, dwFlags, pszDomain, NULL, NULL, NULL); } }
if ( fDomain && ((FAILED(hres) || (!fPassedCredentials))) ) { do { if ( IDCANCEL == DialogBoxParam(g_hinst, MAKEINTRESOURCE(IDD_PSW_JOINCREDENTIALS), hwnd, _CredDlgProc, (LPARAM)pci) ) { hres = E_FAIL; goto exit_gracefully; }
// The dialog box changed the cursor from a wait cursor to an arrow cursor, so the cursor
// needs to be changed back.. This call could be moved to _AttemptJoin (along with a call to
// reset the cursor). This call is made synchronously from the message loop for this hwnd
cur.WaitCursor(); hres = _AttemptJoin(hwnd, dwFlags, pszDomain, pci->pszUser, pci->pszDomain, pci->pszPassword);
} while ( FAILED(hres) ); }
exit_gracefully:
if ( SUCCEEDED(hres) ) { ClearAutoLogon(); *pfReboot = TRUE; // we changed the domain
}
NetApiBufferFree(pszCurrentDomain); return hres; }
//
// set and clear the auto admin logon state.
//
// we set the default user and default domain to the specified strings, we then blow away
// the clear text password stored in the registry to replace it with a password stored
// in the LSA secret space.
//
NTSTATUS _SetDefaultPassword(LPCWSTR PasswordBuffer) { NTSTATUS Status = STATUS_SUCCESS; OBJECT_ATTRIBUTES ObjectAttributes; LSA_HANDLE LsaHandle = NULL; UNICODE_STRING SecretName; UNICODE_STRING SecretValue;
InitializeObjectAttributes(&ObjectAttributes, NULL, 0L, (HANDLE)NULL, NULL);
Status = LsaOpenPolicy(NULL, &ObjectAttributes, POLICY_CREATE_SECRET, &LsaHandle); if (!NT_SUCCESS(Status)) return Status;
RtlInitUnicodeString(&SecretName, c_szDefaultPwdKey); RtlInitUnicodeString(&SecretValue, PasswordBuffer);
Status = LsaStorePrivateData(LsaHandle, &SecretName, &SecretValue); LsaClose(LsaHandle);
return Status; }
//
// Set and clear auto logon for a particular
//
void SetAutoLogon(LPCWSTR pszUserName, LPCWSTR pszPassword) { #ifndef DONT_JOIN
WCHAR szComputerName[MAX_COMPUTERNAME_LENGTH+1]; DWORD dwComputerName = ARRAYSIZE(szComputerName); HKEY hk;
GetComputerName(szComputerName, &dwComputerName); SetDefAccount(pszUserName, szComputerName); // also clears auto logon
if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szWinLogon, 0x0, KEY_WRITE, &hk) ) { _RegSetSZ(hk, c_szAutoLogon, L"1"); // auto admin logon
_RegDelValue(hk, c_szDefPassword); // use the LSA secret for the password
RegCloseKey (hk); }
_SetDefaultPassword(pszPassword); #endif
}
//
// clear the auto admin logon
//
STDAPI ClearAutoLogon(VOID) { #ifndef DONT_JOIN
HKEY hk; if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szWinLogon, 0x0, KEY_WRITE, &hk) ) { _RegSetSZ(hk, c_szAutoLogon, L"0"); // no auto admin logon
_RegDelValue(hk, c_szDefPassword);
RegCloseKey(hk); }
_SetDefaultPassword(L""); // clear the LSA secret
#endif
return S_OK; }
//
// set the default account
//
void SetDefAccount(LPCWSTR pszUser, LPCWSTR pszDomain) { #ifndef DONT_JOIN
ClearAutoLogon();
HKEY hk; if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szWinLogon, 0x0, KEY_WRITE, &hk) ) { _RegSetSZ(hk, c_szDefUserName, pszUser); _RegSetSZ(hk, c_szDefDomain, pszDomain); RegCloseKey(hk); }
#endif
}
|