windows-nt/Source/XPSP1/NT/admin/wizards/addusrw/welcome.cpp
2020-09-26 16:20:57 +08:00

577 lines
13 KiB
C++

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1991-1996 **/
/**********************************************************************/
/*
WelcomeDlg.cpp
CPropertyPage support for User management wizard
FILE HISTORY:
jony Apr-1996 created
*/
#include "stdafx.h"
#include "Speckle.h"
#include "wizbased.h"
#include "Welcome.h"
#include "trstlist.h"
#include <winreg.h>
#include <lmerr.h>
#include <lmapibuf.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CWelcomeDlg property page
IMPLEMENT_DYNCREATE(CWelcomeDlg, CWizBaseDlg)
CWelcomeDlg::CWelcomeDlg() : CWizBaseDlg(CWelcomeDlg::IDD)
{
//{{AFX_DATA_INIT(CWelcomeDlg)
//}}AFX_DATA_INIT
m_pFont = NULL;
}
CWelcomeDlg::~CWelcomeDlg()
{
if (m_pFont != NULL) delete m_pFont;
}
void CWelcomeDlg::DoDataExchange(CDataExchange* pDX)
{
CPropertyPage::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CWelcomeDlg)
DDX_Control(pDX, IDC_DOMAIN_LIST, m_cbDomainList);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CWelcomeDlg, CPropertyPage)
//{{AFX_MSG_MAP(CWelcomeDlg)
ON_WM_SHOWWINDOW()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CWelcomeDlg message handlers
BOOL CWelcomeDlg::OnInitDialog()
{
CPropertyPage::OnInitDialog();
CSpeckleApp* pApp = (CSpeckleApp*)AfxGetApp();
// read cached domain list from registry
DWORD dwRet;
HKEY hKey;
DWORD cbProv = 0;
TCHAR* lpProv = NULL;
BOOL bFoundOne = FALSE;
long lRet = RegConnectRegistry(
(LPTSTR)pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength()),
HKEY_LOCAL_MACHINE,
&hKey);
dwRet = RegOpenKey(hKey,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hKey );
TCHAR* lpPrimaryDomain = NULL;
if ((dwRet = RegQueryValueEx( hKey, TEXT(/*"CachePrimaryDomain"*/"DefaultDomainName"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
{
lpPrimaryDomain = (TCHAR*)malloc(cbProv);
if (lpPrimaryDomain == NULL)
{
AfxMessageBox(IDS_GENERIC_NO_HEAP, MB_ICONEXCLAMATION);
ExitProcess(1);
}
dwRet = RegQueryValueEx( hKey, TEXT(/*"CachePrimaryDomain"*/"DefaultDomainName"), NULL, NULL, (LPBYTE) lpPrimaryDomain, &cbProv );
bFoundOne = TRUE;
}
m_csPrimaryDomain = lpPrimaryDomain;
free(lpPrimaryDomain);
RegCloseKey(hKey);
CString csMachineName;
DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(csMachineName.GetBufferSetLength(MAX_COMPUTERNAME_LENGTH + 1), &dwSize);
pApp->m_csCurrentMachine = csMachineName;
// read the list of trusted domains
CTrustList pList;
if (!pList.BuildTrustList((LPTSTR)pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength())))
{
/* if this fails its probably because they are running the wizard
from a machine account that doesn't exist on the domain level.
Add only the local machine and select it.*/
m_cbDomainList.AddString(pApp->m_csCurrentMachine);
m_cbDomainList.SelectString(-1, pApp->m_csCurrentMachine);
}
else
{
UINT i;
for(i = 0 ; i < pList.m_dwTrustCount ; i++)
m_cbDomainList.AddString(pList.m_ppszTrustList[i]);
// remove the current machine from the list
// if ((i = m_cbDomainList.FindStringExact(-1, pApp->m_csCurrentMachine)) != LB_ERR)
// m_cbDomainList.DeleteString(i);
// now select the default domain into view
int nSel = m_cbDomainList.SelectString(-1, m_csPrimaryDomain);
m_cbDomainList.GetWindowText(m_csDomain);
UpdateData(FALSE);
}
// welcome text
m_pFont = new CFont;
LOGFONT lf;
memset(&lf, 0, sizeof(LOGFONT)); // Clear out structure.
lf.lfHeight = 15;
_tcscpy(lf.lfFaceName, L"MS Sans Serif");
lf.lfWeight = 700;
m_pFont->CreateFontIndirect(&lf); // Create the font.
CString cs;
cs.LoadString(IDS_WELCOME_STRING);
CWnd* pWnd = GetDlgItem(IDC_STATIC1);
pWnd->SetWindowText(cs);
pWnd->SetFont(m_pFont);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
LRESULT CWelcomeDlg::OnWizardNext()
{
UpdateData(TRUE);
CSpeckleApp* pApp = (CSpeckleApp*)AfxGetApp();
// get the DC of the selected domain
m_cbDomainList.GetWindowText(m_csDomain);
// same as last time? no need to check again.
if (m_csLastDomain == m_csDomain) return CPropertyPage::OnWizardNext();
CWaitCursor wait;
pApp->m_csDomain = m_csDomain;
pApp->m_bDomain = FALSE;
TCHAR* pDomain = m_csDomain.GetBuffer(m_csDomain.GetLength());
m_csDomain.ReleaseBuffer();
TCHAR* pDC;
NET_API_STATUS nApi;
// local machine?
if (m_csDomain == pApp->m_csCurrentMachine)
{
pApp->m_csServer = CString(L"\\\\") + pApp->m_csCurrentMachine;
pDC = pApp->m_csServer.GetBuffer(pApp->m_csServer.GetLength());
}
else
{
nApi = NetGetDCName(NULL,
pDomain,
(LPBYTE*)&pDC);
if (nApi != NERR_Success)
{
AfxMessageBox(IDS_NODC, MB_ICONSTOP);
return -1;
}
pApp->m_csServer = pDC;
pApp->m_bDomain = TRUE;
}
// we really shouldn't proceed until we know we are an admin on the remote machine
BYTE sidBuffer[100];
PSID pSID = (PSID)&sidBuffer;
BOOL bRet;
// create a SID for the Administrators group
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
bRet = AllocateAndInitializeSid(&SIDAuth,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ADMINS,
0,
0,
0,
0,
0,
0,
&pSID);
if (!bRet)
{
DWORD dw = GetLastError();
ASSERT(0);
}
TCHAR pName[256];
DWORD dwNameLen = 256;
TCHAR pDomainName[256];
DWORD dwDomainNameLen = 256;
SID_NAME_USE SNU;
bRet = LookupAccountSid(pDC,
pSID,
pName,
&dwNameLen,
pDomainName,
&dwDomainNameLen,
&SNU);
// get the users name and domain from the reg for comparison
DWORD dwRet;
HKEY hKey;
DWORD cbProv = 0;
CString csUsername;
CString csDomainName;
dwRet = RegOpenKey(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), &hKey );
if ((dwRet = RegQueryValueEx( hKey, TEXT("DefaultDomainName"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
{
dwRet = RegQueryValueEx( hKey, TEXT("DefaultDomainName"),
NULL,
NULL,
(LPBYTE)csDomainName.GetBufferSetLength(cbProv),
&cbProv );
}
TCHAR* lpDefaultUserName = NULL;
if ((dwRet = RegQueryValueEx( hKey, TEXT("DefaultUserName"), NULL, NULL, NULL, &cbProv )) == ERROR_SUCCESS)
{
dwRet = RegQueryValueEx( hKey, TEXT("DefaultUserName"),
NULL,
NULL,
(LPBYTE)csUsername.GetBufferSetLength(cbProv),
&cbProv );
}
RegCloseKey(hKey);
// now enumerate the members of the admin group to see if we are a member
BOOL bAdmin = FALSE;
PLOCALGROUP_MEMBERS_INFO_1 pMembers;
DWORD dwEntriesRead, dwTotalEntries;
DWORD dwResumeHandle = 0;
nApi = NetLocalGroupGetMembers(pDC,
pName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi == NERR_Success)
{
USHORT sIndex = 0;
while (sIndex < dwEntriesRead)
{
TCHAR pName[50];
DWORD dwNameSize = 50;
TCHAR pDomain[50];
DWORD dwDomainNameSize = 50;
SID_NAME_USE pUse;
LookupAccountSid(pDC, pMembers[sIndex].lgrmi1_sid,
pName, &dwNameSize,
pDomain, &dwDomainNameSize,
&pUse);
if (((pUse == SidTypeGroup) && (bParseGlobalGroup(pName, csUsername, csDomainName))) ||
((!csUsername.CompareNoCase(pName)) && (!csDomainName.CompareNoCase(pDomain))))
{
bAdmin = TRUE;
break;
}
sIndex++;
}
NetApiBufferFree(pMembers);
while ((dwResumeHandle != 0) && (!bAdmin))
{
nApi = NetLocalGroupGetMembers(pDC,
pName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi == NERR_Success)
{
USHORT sIndex = 0;
while (sIndex < dwEntriesRead)
{
TCHAR pName[50];
DWORD dwNameSize = 50;
TCHAR pDomain[50];
DWORD dwDomainNameSize = 50;
SID_NAME_USE pUse;
LookupAccountSid(pDC, pMembers[sIndex].lgrmi1_sid,
pName, &dwNameSize,
pDomain, &dwDomainNameSize,
&pUse);
if (((pUse == SidTypeGroup) && (bParseGlobalGroup(pName, csUsername, csDomainName))) ||
((!csUsername.CompareNoCase(pName)) && (!csDomainName.CompareNoCase(pDomain))))
{
bAdmin = TRUE;
break;
}
sIndex++;
}
}
NetApiBufferFree(pMembers);
}
}
if (!bAdmin) // not in the administrators group - check the account ops group
{
BYTE sidBuffer[100];
PSID pSID = (PSID)&sidBuffer;
BOOL bRet;
// create a SID for the Account Operators group
SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
bRet = AllocateAndInitializeSid(&SIDAuth,
2,
SECURITY_BUILTIN_DOMAIN_RID,
DOMAIN_ALIAS_RID_ACCOUNT_OPS,
0,
0,
0,
0,
0,
0,
&pSID);
if (!bRet)
{
DWORD dw = GetLastError();
ASSERT(0);
}
TCHAR pName[256];
DWORD dwNameLen = 256;
TCHAR pDomainName[256];
DWORD dwDomainNameLen = 256;
SID_NAME_USE SNU;
bRet = LookupAccountSid(pDC,
pSID,
pName,
&dwNameLen,
pDomainName,
&dwDomainNameLen,
&SNU);
// now enumerate the members of the group to see if we are a member
PLOCALGROUP_MEMBERS_INFO_1 pMembers;
DWORD dwEntriesRead, dwTotalEntries;
DWORD dwResumeHandle = 0;
nApi = NetLocalGroupGetMembers(pDC,
pName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi == NERR_Success)
{
USHORT sIndex = 0;
while (sIndex < dwEntriesRead)
{
TCHAR pName[50];
DWORD dwNameSize = 50;
TCHAR pDomain[50];
DWORD dwDomainNameSize = 50;
SID_NAME_USE pUse;
LookupAccountSid(pDC, pMembers[sIndex].lgrmi1_sid,
pName, &dwNameSize,
pDomain, &dwDomainNameSize,
&pUse);
if (((pUse == SidTypeGroup) && (bParseGlobalGroup(pName, csUsername, csDomainName))) ||
((!csUsername.CompareNoCase(pName)) && (!csDomainName.CompareNoCase(pDomain))))
{
bAdmin = TRUE;
break;
}
sIndex++;
}
NetApiBufferFree(pMembers);
while ((dwResumeHandle != 0) && (!bAdmin))
{
nApi = NetLocalGroupGetMembers(pDC,
pName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi == NERR_Success)
{
USHORT sIndex = 0;
while (sIndex < dwEntriesRead)
{
TCHAR pName[50];
DWORD dwNameSize = 50;
TCHAR pDomain[50];
DWORD dwDomainNameSize = 50;
SID_NAME_USE pUse;
LookupAccountSid(pDC, pMembers[sIndex].lgrmi1_sid,
pName, &dwNameSize,
pDomain, &dwDomainNameSize,
&pUse);
if (((pUse == SidTypeGroup) && (bParseGlobalGroup(pName, csUsername, csDomainName))) ||
((!csUsername.CompareNoCase(pName)) && (!csDomainName.CompareNoCase(pDomain))))
{
bAdmin = TRUE;
break;
}
sIndex++;
}
}
NetApiBufferFree(pMembers);
}
}
}
// not an admin? don't continue
if (!bAdmin)
{
AfxMessageBox(IDS_NOT_ADMIN);
return -1;
}
// store the domain name for a possible rerun.
m_csLastDomain = m_csDomain;
return CPropertyPage::OnWizardNext();
}
// this gets called to look into a global group which is included in the admin or account ops local group.
// these groups live on the DC of the domain passed in.
BOOL CWelcomeDlg::bParseGlobalGroup(LPTSTR lpGroupName, CString& lpName, CString& lpDomain)
{
DWORD dwEntriesRead;
DWORD dwTotalEntries;
DWORD dwResumeHandle = 0;
CSpeckleApp* pApp = (CSpeckleApp*)AfxGetApp();
TCHAR* pDomain = lpDomain.GetBuffer(lpDomain.GetLength());
lpDomain.ReleaseBuffer();
TCHAR* pServer;
NET_API_STATUS nApi = NetGetDCName(NULL,
pDomain,
(LPBYTE*)&pServer);
if (nApi != NERR_Success)
{
AfxMessageBox(IDS_NODC, MB_ICONSTOP);
return FALSE;
}
PGROUP_USERS_INFO_1 pMembers;
nApi = NetGroupGetUsers(pServer,
lpGroupName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi != ERROR_SUCCESS)
{
NetApiBufferFree(pServer);
return FALSE;
}
USHORT sIndex;
for (sIndex = 0; sIndex < dwEntriesRead; sIndex++)
{
if (!lpName.CompareNoCase(pMembers[sIndex].grui1_name))
{
NetApiBufferFree(pServer);
return TRUE;
}
}
while (dwResumeHandle != 0)
{
nApi = NetGroupGetUsers(pServer,
lpGroupName,
1,
(LPBYTE*)&pMembers,
5000,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if (nApi != ERROR_SUCCESS)
{
NetApiBufferFree(pServer);
return FALSE;
}
for (sIndex = 0; sIndex < dwEntriesRead; sIndex++)
{
if (!lpName.CompareNoCase(pMembers[sIndex].grui1_name))
{
NetApiBufferFree(pServer);
return TRUE;
}
}
}
NetApiBufferFree(pServer);
return FALSE;
}
void CWelcomeDlg::OnShowWindow(BOOL bShow, UINT nStatus)
{
CPropertyPage::OnShowWindow(bShow, nStatus);
CSpeckleApp* pApp = (CSpeckleApp*)AfxGetApp();
if (bShow) pApp->m_cps1.SetWizardButtons(PSWIZB_NEXT);
else pApp->m_cps1.SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
}