windows-nt/Source/XPSP1/NT/admin/snapin/dfsadmin/dfsgui/dfswiz.cpp
2020-09-26 16:20:57 +08:00

2216 lines
50 KiB
C++

/*++
Module Name:
DfsWiz.cpp
Abstract:
This module contains the implementation for CCreateDfsRootWizPage1, 2, 3, 4, 5, 6.
These classes implement pages in the CreateDfs Root wizard.
--*/
#include "stdafx.h"
#include "resource.h" // To be able to use the resource symbols
#include "DfsEnums.h" // for common enums, typedefs, etc
#include "NetUtils.h"
#include "ldaputils.h"
#include "Utils.h" // For the LoadStringFromResource method
#include "dfswiz.h" // For Ds Query Dialog
#include <shlobj.h>
#include <dsclient.h>
#include <initguid.h>
#include <cmnquery.h>
#include <dsquery.h>
#include <lmdfs.h>
#include <iads.h>
#include <icanon.h>
#include <dns.h>
HRESULT
ValidateFolderPath(
IN LPCTSTR lpszServer,
IN LPCTSTR lpszPath
);
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage1: Welcome page
// Has a watermark bitmap and no controls except the next and cancel buttons
CCreateDfsRootWizPage1::CCreateDfsRootWizPage1(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
: CQWizardPageImpl<CCreateDfsRootWizPage1> (false), m_lpWizInfo(i_lpWizInfo)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage1. Calls the parent ctor asking it to
display the watermark bitmap
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
}
BOOL
CCreateDfsRootWizPage1::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
::PropSheet_SetWizButtons(GetParent(), PSWIZB_NEXT);
::SetControlFont(m_lpWizInfo->hBigBoldFont, m_hWnd, IDC_WELCOME_BIG_TITLE);
::SetControlFont(m_lpWizInfo->hBoldFont, m_hWnd, IDC_WELCOME_SMALL_TITLE);
return TRUE;
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage2: Dfsroot type selection
// Used to decide the type of dfsroot to be created. Fault tolerant or standalone
CCreateDfsRootWizPage2::CCreateDfsRootWizPage2(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
:m_lpWizInfo(i_lpWizInfo), CQWizardPageImpl<CCreateDfsRootWizPage2>(true)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage2. Calls the parent ctor and stores
the Wizard info struct.
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
CComBSTR bstrTitle;
CComBSTR bstrSubTitle;
HRESULT hr = LoadStringFromResource(IDS_WIZ_PAGE2_TITLE, &bstrTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrTitle.m_str);
SetHeaderTitle(bstrTitle);
hr = LoadStringFromResource(IDS_WIZ_PAGE2_SUBTITLE, &bstrSubTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrSubTitle.m_str);
SetHeaderSubTitle(bstrSubTitle);
}
BOOL
CCreateDfsRootWizPage2::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown.
Also, sets the Dfsroot type to be fault tolerant.
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
::PropSheet_SetWizButtons(GetParent(), PSWIZB_BACK | PSWIZB_NEXT);
SetDefaultValues(); // Update the controls to show default values
return TRUE;
}
HRESULT
CCreateDfsRootWizPage2::SetDefaultValues(
)
/*++
Routine Description:
Sets the default values for controls in the dialog box
Arguments:
None
Return value:
S_OK
--*/
{
// Fault Tolerant dfsroot is the default.
if (DFS_TYPE_UNASSIGNED == m_lpWizInfo->DfsType)
{ // Set the variable and the radio button
CheckRadioButton(IDC_RADIO_FTDFSROOT, IDC_RADIO_STANDALONE_DFSROOT, IDC_RADIO_FTDFSROOT);
m_lpWizInfo->DfsType = DFS_TYPE_FTDFS;
}
return S_OK;
}
BOOL
CCreateDfsRootWizPage2::OnWizardNext()
/*++
Routine Description:
Called when the "Next" button is pressed. Gets the values from the page.
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
if (IsDlgButtonChecked(IDC_RADIO_FTDFSROOT)) // Use the radio buttons to set the variable
{
m_lpWizInfo->DfsType = DFS_TYPE_FTDFS;
}
else
{
m_lpWizInfo->DfsType = DFS_TYPE_STANDALONE;
}
return TRUE;
}
BOOL
CCreateDfsRootWizPage2::OnWizardBack()
/*++
Routine Description:
Called when the "Back" button on the pressed. Sets the buttons to be shown
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
return OnReset();
}
BOOL
CCreateDfsRootWizPage2::OnReset()
/*++
Routine Description:
Called when the page is being released. Can be on "Back" or "Cancel"
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
m_lpWizInfo->DfsType = DFS_TYPE_UNASSIGNED; // Reset the dfsroot type
return TRUE;
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage3: Domain selection
// Use to select a NT 5.0 domain
CCreateDfsRootWizPage3::CCreateDfsRootWizPage3(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
: m_lpWizInfo(i_lpWizInfo), m_hImgListSmall(NULL),
CQWizardPageImpl<CCreateDfsRootWizPage3>(true)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage3. Calls the parent ctor and stores
the Wizard info struct.
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
CComBSTR bstrTitle;
CComBSTR bstrSubTitle;
HRESULT hr = LoadStringFromResource(IDS_WIZ_PAGE3_TITLE, &bstrTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrTitle.m_str);
SetHeaderTitle(bstrTitle);
hr = LoadStringFromResource(IDS_WIZ_PAGE3_SUBTITLE, &bstrSubTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrSubTitle.m_str);
SetHeaderSubTitle(bstrSubTitle);
}
CCreateDfsRootWizPage3::~CCreateDfsRootWizPage3(
)
/*++
Routine Description:
The dtor for CCreateDfsRootWizPage3.
Arguments:
None
Return value:
None
--*/
{
}
BOOL
CCreateDfsRootWizPage3::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown.
Also, if the Dfsroot type is standalone, this page is skipped. Before
this the user domain name is specified
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
// if (NULL != m_lpWizInfo->bstrSelectedDomain)
// {
// OnReset();
// }
// Skip this page for standalone dfs roots
if (DFS_TYPE_STANDALONE == m_lpWizInfo->DfsType)
{
return FALSE;
}
SetDefaultValues(); // Update the controls to show default values
::PropSheet_SetWizButtons(GetParent(), PSWIZB_BACK | PSWIZB_NEXT);
return TRUE;
}
HRESULT
CCreateDfsRootWizPage3::SetDefaultValues(
)
/*++
Routine Description:
Sets the default values for controls in the dialog box
Sets the edit box to the current domain. No check to see, if it has
been already done as Standalone skips this page
Arguments:
None
Return value:
S_OK
--*/
{
if (NULL == m_lpWizInfo->bstrSelectedDomain)
{
// Page is displayed for the first time, Set domain to current domain
CComBSTR bstrDomain;
HRESULT hr = GetServerInfo(NULL, &bstrDomain);
if (S_OK == hr && S_OK == Is50Domain(bstrDomain))
{
m_lpWizInfo->bstrSelectedDomain = bstrDomain.Detach();
}
}
SetDlgItemText(IDC_EDIT_SELECTED_DOMAIN,
m_lpWizInfo->bstrSelectedDomain ? m_lpWizInfo->bstrSelectedDomain : _T(""));
// select the matching item in the listbox
HWND hwndList = GetDlgItem(IDC_LIST_DOMAINS);
if ( ListView_GetItemCount(hwndList) > 0)
{
int nIndex = -1;
if (m_lpWizInfo->bstrSelectedDomain)
{
TCHAR szText[DNS_MAX_NAME_BUFFER_LENGTH];
while (-1 != (nIndex = ListView_GetNextItem(hwndList, nIndex, LVNI_ALL)))
{
ListView_GetItemText(hwndList, nIndex, 0, szText, DNS_MAX_NAME_BUFFER_LENGTH);
if (!lstrcmpi(m_lpWizInfo->bstrSelectedDomain, szText))
{
ListView_SetItemState(hwndList, nIndex, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff);
ListView_Update(hwndList, nIndex);
break;
}
}
}
if (-1 == nIndex)
{
ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, 0xffffffff);
ListView_Update(hwndList, 0);
}
}
return S_OK;
}
BOOL
CCreateDfsRootWizPage3::OnWizardNext()
/*++
Routine Description:
Called when the "Next" button is pressed. Gets the values from the page.
Displays an error message, if an incorrect value has been specified
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
// Get the value entered by the user
DWORD dwTextLength = 0;
CComBSTR bstrCurrentText;
HRESULT hr = GetInputText(GetDlgItem(IDC_EDIT_SELECTED_DOMAIN), &bstrCurrentText, &dwTextLength);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_DOMAIN));
return FALSE;
} else if (0 == dwTextLength)
{
DisplayMessageBoxWithOK(IDS_MSG_EMPTY_FIELD);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_DOMAIN));
return FALSE;
}
CComBSTR bstrDnsDomain;
hr = CheckUserEnteredValues(bstrCurrentText, &bstrDnsDomain);
if (S_OK != hr)
{ // Error message on incorrect domain.
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_INCORRECT_DOMAIN, bstrCurrentText);
return FALSE;
}
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSelectedDomain);
m_lpWizInfo->bstrSelectedDomain = bstrDnsDomain.Detach();
return TRUE;
}
HRESULT
CCreateDfsRootWizPage3::CheckUserEnteredValues(
IN LPCTSTR i_szDomainName,
OUT BSTR* o_pbstrDnsDomainName
)
/*++
Routine Description:
Checks the value that user has given for this page.
This is done typically on "Next" key being pressed.
Check, if the domain is NT 5.0 and contactable
--*/
{
RETURN_INVALIDARG_IF_NULL(i_szDomainName);
// Check if it is NT 5.0 domain and is contactable
return Is50Domain(const_cast<LPTSTR>(i_szDomainName), o_pbstrDnsDomainName);
}
BOOL
CCreateDfsRootWizPage3::OnWizardBack()
/*++
Routine Description:
Called when the "Back" button is pressed. Resets the values
Arguments:
None
Return value:
TRUE. to let the user continue to the previous page
FALSE, to not let the user continue.
--*/
{
SetDlgItemText(IDC_EDIT_SELECTED_DOMAIN, _T("")); // Set edit box to empty
return OnReset(); // Simulate a reset.
}
BOOL
CCreateDfsRootWizPage3::OnReset()
/*++
Routine Description:
Called when the page is being released. Can be on "Back" or "Cancel"
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSelectedDomain);
return TRUE;
}
LRESULT
CCreateDfsRootWizPage3::OnNotify(
IN UINT i_uMsg,
IN WPARAM i_wParam,
IN LPARAM i_lParam,
IN OUT BOOL& io_bHandled
)
/*++
Routine Description:
Notify message for user actions. We handle only the mouse click right now
Arguments:
i_lParam - Details about the control sending the notify
io_bHandled - Whether we handled this message or not.
Return value:
TRUE
--*/
{
io_bHandled = FALSE; // So that the base class gets this notify too
NMHDR* pNMHDR = (NMHDR*)i_lParam;
if (NULL == pNMHDR)
return TRUE;
if (IDC_LIST_DOMAINS != pNMHDR->idFrom) // We need to handle notifies only to the LV
{
return TRUE;
}
switch(pNMHDR->code)
{
case LVN_ITEMCHANGED:
case NM_CLICK:
// On item changed
{
if (NULL != ((NM_LISTVIEW *)i_lParam))
OnItemChanged(((NM_LISTVIEW *)i_lParam)->iItem);
return 0; // Should be returning 0
}
case NM_DBLCLK: // Double click event
{
// Simulate a double click
if (NULL != ((NM_LISTVIEW *)i_lParam))
OnItemChanged(((NM_LISTVIEW *)i_lParam)->iItem);
if (0 <= ((NM_LISTVIEW *)i_lParam)->iItem)
::PropSheet_PressButton(GetParent(), PSBTN_NEXT);
break;
}
default:
break;
}
return TRUE;
}
BOOL
CCreateDfsRootWizPage3::OnItemChanged(
IN INT i_iItem
)
/*++
Routine Description:
Handles item change notify. Change the edit box content to the current LV
selection
Arguments:
i_iItem - Selected Item number of the LV.
Return value:
TRUE
--*/
{
HWND hwndDomainLV = GetDlgItem(IDC_LIST_DOMAINS);
CComBSTR bstrDomain;
if (NULL == hwndDomainLV)
{
return FALSE;
}
// Get the LV item text
HRESULT hr = GetListViewItemText(hwndDomainLV, i_iItem, &bstrDomain);
if ((S_OK == hr) && (bstrDomain != NULL) )
{
LRESULT lr = SetDlgItemText(IDC_EDIT_SELECTED_DOMAIN, bstrDomain);
return lr;
}
return TRUE;
}
LRESULT
CCreateDfsRootWizPage3::OnInitDialog(
IN UINT i_uMsg,
IN WPARAM i_wParam,
IN LPARAM i_lParam,
IN OUT BOOL& io_bHandled
)
/*++
Routine Description:
Called at the dialog creation time. We get the domain list here.
Also, set the imagelist for the LV.
Arguments:
None used
Return value:
TRUE - Nothing to do with errors. Just lets the dialog set the focus to a control
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
::SendMessage(GetDlgItem(IDC_EDIT_SELECTED_DOMAIN), EM_LIMITTEXT, DNSNAMELIMIT, 0);
HWND hwndDomainList = GetDlgItem(IDC_LIST_DOMAINS); // The imagelist
// Assign the image lists to the list view control.
HIMAGELIST hImageList = NULL;
int nIconIDs[] = {IDI_16x16_DOMAIN};
HRESULT hr = CreateSmallImageList(
_Module.GetResourceInstance(),
nIconIDs,
sizeof(nIconIDs) / sizeof(nIconIDs[0]),
&hImageList);
if (SUCCEEDED(hr))
{
ListView_SetImageList(hwndDomainList, hImageList, LVSIL_SMALL);
hr = AddDomainsToList(hwndDomainList); // Add the domains to the list view
}
return TRUE;
}
HRESULT
CCreateDfsRootWizPage3::AddDomainsToList(
IN HWND i_hImageList
)
/*++
Routine Description:
Add all the NT 5.0 domains to the list view
Arguments:
i_hImageList - The hwnd of the LV.
Return value:
S_OK - On success
E_FAIL - On failure
E_INVALID_ARG - On any argument being null
E_UNEXPECTED - Some unexpected error. If an image loading fails, etc
Value other than S_OK returned by called methods
--*/
{
RETURN_INVALIDARG_IF_NULL(i_hImageList);
HRESULT hr = S_FALSE;
NETNAMELIST ListOf50Domains; // Pointer to the first domain information
hr = Get50Domains(&ListOf50Domains); // Get the NT 5.0 domains
if (S_OK != hr)
{
return hr;
}
// Add the NT 5.0 domains to the LV
for(NETNAMELIST::iterator i = ListOf50Domains.begin(); i != ListOf50Domains.end(); i++)
{
if ((*i)->bstrNetName)
{
InsertIntoListView(i_hImageList, (*i)->bstrNetName);
}
}
if (!ListOf50Domains.empty())
{
for (NETNAMELIST::iterator i = ListOf50Domains.begin(); i != ListOf50Domains.end(); i++)
{
delete (*i);
}
ListOf50Domains.erase(ListOf50Domains.begin(), ListOf50Domains.end());
}
return S_OK;
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage4: Server selection
// Displays a list of Servers and allows the user to select one.
CCreateDfsRootWizPage4::CCreateDfsRootWizPage4(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
: m_lpWizInfo(i_lpWizInfo),
m_cfDsObjectNames(NULL),
CQWizardPageImpl<CCreateDfsRootWizPage4>(true)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage4. Calls the parent ctor and stores
the Wizard info struct.
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
CComBSTR bstrTitle;
CComBSTR bstrSubTitle;
HRESULT hr = LoadStringFromResource(IDS_WIZ_PAGE4_TITLE, &bstrTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrTitle.m_str);
SetHeaderTitle(bstrTitle);
hr = LoadStringFromResource(IDS_WIZ_PAGE4_SUBTITLE, &bstrSubTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrSubTitle.m_str);
SetHeaderSubTitle(bstrSubTitle);
}
CCreateDfsRootWizPage4::~CCreateDfsRootWizPage4(
)
/*++
Routine Description:
The dtor for CCreateDfsRootWizPage4.
Arguments:
None
Return value:
None
--*/
{
}
BOOL
CCreateDfsRootWizPage4::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown.
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
::SendMessage(GetDlgItem(IDC_EDIT_SELECTED_SERVER), EM_LIMITTEXT, DNSNAMELIMIT, 0);
HRESULT hr = S_OK;
dfsDebugOut((_T("WizPage4::OnSetActive bstrSelectedDomain=%s\n"), m_lpWizInfo->bstrSelectedDomain));
if (DFS_TYPE_STANDALONE== m_lpWizInfo->DfsType)
{
// Standalone Setup, set domain to current domain.
CComBSTR bstrDomain;
hr = GetServerInfo(NULL, &bstrDomain);
if (S_OK == hr)
m_lpWizInfo->bstrSelectedDomain = bstrDomain.Detach();
}
::EnableWindow(GetDlgItem(IDCSERVERS_BROWSE), m_lpWizInfo->bstrSelectedDomain && S_OK == Is50Domain(m_lpWizInfo->bstrSelectedDomain));
if (NULL == m_lpWizInfo->bstrSelectedServer) // If selected server is null
{
SetDefaultValues(); // Update the controls to show default values
}
if (m_lpWizInfo->bRootReplica) // If a root replica is being added
{
::PropSheet_SetWizButtons(GetParent(), PSWIZB_NEXT);
::ShowWindow(GetDlgItem(IDC_SERVER_SHARE_LABEL), SW_NORMAL);
::ShowWindow(GetDlgItem(IDC_SERVER_SHARE), SW_NORMAL);
SetDlgItemText(IDC_SERVER_SHARE, m_lpWizInfo->bstrDfsRootName);
} else
::PropSheet_SetWizButtons(GetParent(), PSWIZB_BACK | PSWIZB_NEXT);
return TRUE;
}
HRESULT
CCreateDfsRootWizPage4::SetDefaultValues(
)
/*++
Routine Description:
Sets the default values for controls in the dialog box
Sets the edit box to the current server.
Arguments:
None
Return value:
S_OK
--*/
{
if (NULL == m_lpWizInfo->bstrSelectedServer)
{
// Page is displayed for the first time, Set to local server
CComBSTR bstrServer;
HRESULT hr = GetLocalComputerName(&bstrServer);
if (SUCCEEDED(hr) &&
S_FALSE == IsHostingDfsRoot(bstrServer) &&
S_OK == IsServerInDomain(bstrServer) )
{
m_lpWizInfo->bstrSelectedServer = bstrServer.Detach();
}
}
SetDlgItemText(IDC_EDIT_SELECTED_SERVER,
m_lpWizInfo->bstrSelectedServer ? m_lpWizInfo->bstrSelectedServer : _T(""));
return S_OK;
}
BOOL
CCreateDfsRootWizPage4::OnWizardNext()
/*++
Routine Description:
Called when the "Next" button is pressed. Gets the values from the page.
Displays an error message, if an incorrect value has been specified
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
HRESULT hr = S_OK;
DWORD dwTextLength = 0;
CComBSTR bstrCurrentText;
hr = GetInputText(GetDlgItem(IDC_EDIT_SELECTED_SERVER), &bstrCurrentText, &dwTextLength);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
} else if (0 == dwTextLength)
{
DisplayMessageBoxWithOK(IDS_MSG_EMPTY_FIELD);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
}
if (I_NetNameValidate(0, bstrCurrentText, NAMETYPE_COMPUTER, 0))
{
DisplayMessageBoxWithOK(IDS_MSG_INVALID_SERVER_NAME, bstrCurrentText);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
}
CComBSTR bstrComputerName;
hr = CheckUserEnteredValues(bstrCurrentText, &bstrComputerName);
if (S_OK != hr) // If server is not a valid one. The above function has already displayed the message
{
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
}
if (m_lpWizInfo->bRootReplica)
{
hr = CheckShare(bstrCurrentText, m_lpWizInfo->bstrDfsRootName, &m_lpWizInfo->bShareExists);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
} else if (S_FALSE == hr)
{
DisplayMessageBoxWithOK(IDS_MSG_ROOTSHARE_NOGOOD, m_lpWizInfo->bstrDfsRootName);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
}
if (m_lpWizInfo->bPostW2KVersion && m_lpWizInfo->bShareExists && !CheckReparsePoint(bstrCurrentText, m_lpWizInfo->bstrDfsRootName))
{
DisplayMessageBoxWithOK(IDS_MSG_ROOTSHARE_NOTNTFS5, m_lpWizInfo->bstrDfsRootName);
::SetFocus(GetDlgItem(IDC_EDIT_SELECTED_SERVER));
return FALSE;
}
}
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSelectedServer);
m_lpWizInfo->bstrSelectedServer = bstrComputerName.Detach();
return TRUE;
}
// S_OK: Yes, it belongs to the selected domain
// S_FALSE: No, it does not belong to the selected domain
// hr: other errors
HRESULT
CCreateDfsRootWizPage4::IsServerInDomain(IN LPCTSTR lpszServer)
{
if (DFS_TYPE_FTDFS != m_lpWizInfo->DfsType)
return S_OK;
HRESULT hr = S_FALSE;
CComBSTR bstrActualDomain;
hr = GetServerInfo((LPTSTR)lpszServer, &bstrActualDomain);
if (S_OK == hr)
{
if (!lstrcmpi(bstrActualDomain, m_lpWizInfo->bstrSelectedDomain))
hr = S_OK;
else
hr = S_FALSE;
}
return hr;
}
HRESULT
CCreateDfsRootWizPage4::CheckUserEnteredValues(
IN LPCTSTR i_szMachineName,
OUT BSTR* o_pbstrComputerName
)
/*++
Routine Description:
Checks the value that user has given for this page.
This is done typically on "Next" key being pressed.
Check, if the machine name is a server that is NT 5.0, belongs to
the domain previously selected and is running dfs service.
Arguments:
i_szMachineName - Machine name given by the user
--*/
{
RETURN_INVALIDARG_IF_NULL(i_szMachineName);
RETURN_INVALIDARG_IF_NULL(o_pbstrComputerName);
HRESULT hr = S_OK;
LONG lMajorVer = 0;
LONG lMinorVer = 0;
hr = GetServerInfo(
(LPTSTR)i_szMachineName,
NULL, // &bstrActualDomain,
NULL, // &bstrNetbiosComputerName, // Netbios
NULL, // ValidDSObject
NULL, // Dns
NULL, // Guid
NULL, // FQDN
NULL, // pSubscriberList
&lMajorVer,
&lMinorVer
);
if(FAILED(hr))
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_INCORRECT_SERVER, i_szMachineName);
return hr;
}
if (lMajorVer < 5)
{
DisplayMessageBoxWithOK(IDS_MSG_NOT_50, (BSTR)i_szMachineName);
return S_FALSE;
}
/* LinanT 3/19/99: remove "check registry, if set, get dns server"
CComBSTR bstrDnsComputerName;
(void)GetServerInfo(
(LPTSTR)i_szMachineName,
NULL, // domain
NULL, // Netbios
NULL, // ValidDSObject
&bstrDnsComputerName, // Dns
NULL, // Guid
NULL, // FQDN
NULL, // lMajorVer
NULL //lMinorVer
);
*o_pbstrComputerName = SysAllocString(bstrDnsComputerName ? bstrDnsComputerName : bstrNetbiosComputerName);
*/
if ( !mylstrncmpi(i_szMachineName, _T("\\\\"), 2) )
*o_pbstrComputerName = SysAllocString(i_szMachineName + 2);
else
*o_pbstrComputerName = SysAllocString(i_szMachineName);
if (!*o_pbstrComputerName)
{
hr = E_OUTOFMEMORY;
DisplayMessageBoxForHR(hr);
return hr;
}
/*
//
// don't check, let DFS API handle it.
// This way, we have space to handle new DFS service if introduced in the future.
//
hr = IsServerRunningDfs(*o_pbstrComputerName);
if(S_OK != hr)
{
DisplayMessageBoxWithOK(IDS_MSG_NOT_RUNNING_DFS, *o_pbstrComputerName);
return hr;
}
*/
hr = IsServerInDomain(*o_pbstrComputerName);
if (FAILED(hr))
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_INCORRECT_SERVER, *o_pbstrComputerName);
return hr;
} else if (S_FALSE == hr)
{
DisplayMessageBoxWithOK(IDS_MSG_SERVER_FROM_ANOTHER_DOMAIN, *o_pbstrComputerName);
return hr;
}
//
// for W2K, check if server already has a dfs root set up
// do not check for Whistler (in which case the lMinorVer == 1).
//
if (lMajorVer == 5 && lMinorVer < 1 && S_OK == IsHostingDfsRoot(*o_pbstrComputerName))
{
DisplayMessageBoxWithOK(IDS_MSG_WIZ_DFS_ALREADY_PRESENT,NULL);
return S_FALSE;
}
m_lpWizInfo->bPostW2KVersion = (lMajorVer >= 5 && lMinorVer >= 1);
return S_OK;
}
BOOL
CCreateDfsRootWizPage4::OnWizardBack()
/*++
Routine Description:
Called when the "Back" button is pressed. Resets the values.
Empties the LV
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
SetDlgItemText(IDC_EDIT_SELECTED_SERVER, _T("")); // Set edit box to empty
return OnReset();
}
BOOL
CCreateDfsRootWizPage4::OnReset()
/*++
Routine Description:
Called when the page is being released. Can be on "Back" or "Cancel"
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSelectedServer);
return TRUE;
}
HRESULT
GetComputerDnsNameFromLDAP(
IN LPCTSTR lpszLDAPPath,
OUT BSTR *o_pbstrName
)
{
HRESULT hr = S_OK;
CComPtr<IADs> spIADs;
hr = ADsGetObject(const_cast<LPTSTR>(lpszLDAPPath), IID_IADs, (void**)&spIADs);
if (SUCCEEDED(hr))
{
VARIANT var;
VariantInit(&var);
hr = spIADs->Get(_T("dnsHostName"), &var);
if (SUCCEEDED(hr))
{
CComBSTR bstrComputer = V_BSTR(&var);
*o_pbstrName = bstrComputer.Detach();
VariantClear(&var);
}
}
return hr;
}
HRESULT
GetComputerNetbiosNameFromLDAP(
IN LPCTSTR lpszLDAPPath,
OUT BSTR *o_pbstrName
)
{
HRESULT hr = S_OK;
CComPtr<IADsPathname> spIAdsPath;
hr = CoCreateInstance(CLSID_Pathname, NULL, CLSCTX_INPROC_SERVER, IID_IADsPathname, (void**)&spIAdsPath);
if (SUCCEEDED(hr))
{
hr = spIAdsPath->Set(const_cast<LPTSTR>(lpszLDAPPath), ADS_SETTYPE_FULL);
if (SUCCEEDED(hr))
{
hr = spIAdsPath->SetDisplayType(ADS_DISPLAY_VALUE_ONLY);
if (SUCCEEDED(hr))
{
// Get first Component which is computer's Netbios name.
CComBSTR bstrComputer;
hr = spIAdsPath->GetElement(0, &bstrComputer);
if (SUCCEEDED(hr))
*o_pbstrName = bstrComputer.Detach();
}
}
}
return hr;
}
BOOL
CCreateDfsRootWizPage4::OnBrowse(
IN WORD wNotifyCode,
IN WORD wID,
IN HWND hWndCtl,
IN BOOL& bHandled
)
/*++
Routine Description:
Handles the mouse click of the Browse button.
Display the Computer Query Dialog.
--*/
{
CWaitCursor WaitCursor;
DSQUERYINITPARAMS dqip;
OPENQUERYWINDOW oqw;
CComPtr<ICommonQuery> pCommonQuery;
CComPtr<IDataObject> pDataObject;
HRESULT hr = S_OK;
do {
CComBSTR bstrDCName;
CComBSTR bstrLDAPDomainPath;
hr = GetDomainInfo(
m_lpWizInfo->bstrSelectedDomain,
&bstrDCName,
NULL, // domainDns
NULL, // domainDN
&bstrLDAPDomainPath);
if (FAILED(hr))
break;
dfsDebugOut((_T("OnBrowse bstrDCName=%s, bstrLDAPDomainPath=%s\n"),
bstrDCName, bstrLDAPDomainPath));
hr = CoCreateInstance(CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER, IID_ICommonQuery, (void **)&pCommonQuery);
if (FAILED(hr)) break;
// Parameters for Query Dialog.
ZeroMemory(&dqip, sizeof(dqip));
dqip.cbStruct = sizeof(dqip);
dqip.dwFlags = DSQPF_HASCREDENTIALS;
dqip.pDefaultScope = bstrLDAPDomainPath;
dqip.pServer = bstrDCName;
ZeroMemory(&oqw, sizeof(oqw));
oqw.cbStruct = sizeof(oqw);
oqw.clsidHandler = CLSID_DsQuery; // Handler is Ds Query.
oqw.pHandlerParameters = &dqip;
oqw.clsidDefaultForm = CLSID_DsFindComputer; // Show Find Computers Query Dialog
oqw.dwFlags = OQWF_OKCANCEL |
OQWF_SINGLESELECT |
OQWF_DEFAULTFORM |
OQWF_REMOVEFORMS |
OQWF_ISSUEONOPEN |
OQWF_REMOVESCOPES ;
hr = pCommonQuery->OpenQueryWindow(m_hWnd, &oqw, &pDataObject);
if (S_OK != hr) break;
if (NULL == m_cfDsObjectNames )
{
m_cfDsObjectNames = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
}
FORMATETC fmte = {
CF_HDROP,
NULL,
DVASPECT_CONTENT,
-1,
TYMED_HGLOBAL
};
STGMEDIUM medium = {
TYMED_NULL,
NULL,
NULL
};
fmte.cfFormat = m_cfDsObjectNames;
hr = pDataObject->GetData(&fmte, &medium);
if (FAILED(hr)) break;
LPDSOBJECTNAMES pDsObjects = (LPDSOBJECTNAMES)medium.hGlobal;
if (!pDsObjects || pDsObjects->cItems <= 0)
{
hr = S_FALSE;
break;
}
// retrieve the full LDAP path to the computer
LPTSTR lpszTemp =
(LPTSTR)(((LPBYTE)pDsObjects)+(pDsObjects->aObjects[0].offsetName));
// try to retrieve its Dns name
CComBSTR bstrComputer;
hr = GetComputerDnsNameFromLDAP(lpszTemp, &bstrComputer);
// if failed, try to retrieve its Netbios name
if (FAILED(hr))
hr = GetComputerNetbiosNameFromLDAP(lpszTemp, &bstrComputer);
if (FAILED(hr)) break;
SetDlgItemText(IDC_EDIT_SELECTED_SERVER, bstrComputer);
} while (0);
if (FAILED(hr))
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_FAILED_TO_BROWSE_SERVER);
return (S_OK == hr);
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage5: Share selection
// Displays the shares given a server. Allows choosing from this list or
// creating a new one.
CCreateDfsRootWizPage5::CCreateDfsRootWizPage5(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
:m_lpWizInfo(i_lpWizInfo), CQWizardPageImpl<CCreateDfsRootWizPage5>(true)
{
CComBSTR bstrTitle;
CComBSTR bstrSubTitle;
HRESULT hr = LoadStringFromResource(IDS_WIZ_PAGE5_TITLE, &bstrTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrTitle.m_str);
SetHeaderTitle(bstrTitle);
hr = LoadStringFromResource(IDS_WIZ_PAGE5_SUBTITLE, &bstrSubTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrSubTitle.m_str);
SetHeaderSubTitle(bstrSubTitle);
}
BOOL
CCreateDfsRootWizPage5::OnSetActive()
{
if (m_lpWizInfo->bShareExists)
return FALSE; // root share exists, skip this page
CComBSTR bstrText;
FormatResourceString(IDS_ROOTSHARE_NEEDED, m_lpWizInfo->bstrDfsRootName, &bstrText);
SetDlgItemText(IDC_ROOTSHARE_NEEDED, bstrText);
::PropSheet_SetWizButtons(GetParent(), PSWIZB_BACK | PSWIZB_NEXT);
return TRUE;
}
BOOL
CCreateDfsRootWizPage5::OnWizardNext()
{
CWaitCursor WaitCursor;
CComBSTR bstrCurrentText;
DWORD dwTextLength = 0;
// get share path
HRESULT hr = GetInputText(GetDlgItem(IDC_EDIT_SHARE_PATH), &bstrCurrentText, &dwTextLength);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_SHARE_PATH));
return FALSE;
} else if (0 == dwTextLength)
{
DisplayMessageBoxWithOK(IDS_MSG_EMPTY_FIELD);
::SetFocus(GetDlgItem(IDC_EDIT_SHARE_PATH));
return FALSE;
}
// Removing the ending backslash, otherwise, GetFileAttribute/NetShareAdd will fail.
TCHAR *p = bstrCurrentText + _tcslen(bstrCurrentText) - 1;
if (IsValidLocalAbsolutePath(bstrCurrentText) && *p == _T('\\') && *(p-1) != _T(':'))
*p = _T('\0');
if (S_OK != ValidateFolderPath(m_lpWizInfo->bstrSelectedServer, bstrCurrentText))
{
::SetFocus(GetDlgItem(IDC_EDIT_SHARE_PATH));
return FALSE;
}
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSharePath);
m_lpWizInfo->bstrSharePath = bstrCurrentText.Detach();
// Create the share.
hr = CreateShare(
m_lpWizInfo->bstrSelectedServer,
m_lpWizInfo->bstrDfsRootName,
_T(""), // Blank Comment
m_lpWizInfo->bstrSharePath
);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
return FALSE;
}
if (m_lpWizInfo->bPostW2KVersion && !CheckReparsePoint(m_lpWizInfo->bstrSelectedServer, m_lpWizInfo->bstrDfsRootName))
{
DisplayMessageBoxWithOK(IDS_MSG_ROOTSHARE_NOTNTFS5, m_lpWizInfo->bstrDfsRootName);
NetShareDel(m_lpWizInfo->bstrSelectedServer, m_lpWizInfo->bstrDfsRootName, 0);
::SetFocus(GetDlgItem(IDC_EDIT_SHARE_PATH));
return FALSE;
}
SetDlgItemText(IDC_EDIT_SHARE_PATH, _T(""));
SetDlgItemText(IDC_EDIT_SHARE_NAME, _T(""));
return TRUE;
}
BOOL
CCreateDfsRootWizPage5::OnWizardBack()
{
// Set the edit boxes to empty
SetDlgItemText(IDC_EDIT_SHARE_PATH, _T(""));
SetDlgItemText(IDC_EDIT_SHARE_NAME, _T(""));
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrSharePath);
return TRUE;
}
/*
BOOL
CCreateDfsRootWizPage5::OnWizardFinish(
)
{
if (!OnWizardNext())
return(FALSE);
return (S_OK == _SetUpDfs(m_lpWizInfo));
}
*/
LRESULT CCreateDfsRootWizPage5::OnInitDialog(
IN UINT i_uMsg,
IN WPARAM i_wParam,
IN LPARAM i_lParam,
IN OUT BOOL& io_bHandled
)
{
::SendMessage(GetDlgItem(IDC_EDIT_SHARE_PATH), EM_LIMITTEXT, _MAX_DIR - 1, 0);
return TRUE;
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage6: DfsRoot name selection
// The final page, here the user specifies the dfsroot name.
CCreateDfsRootWizPage6::CCreateDfsRootWizPage6(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
: m_lpWizInfo(i_lpWizInfo), CQWizardPageImpl<CCreateDfsRootWizPage6>(true)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage6. Calls the parent ctor and stores
the Wizard info struct.
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
CComBSTR bstrTitle;
CComBSTR bstrSubTitle;
HRESULT hr = LoadStringFromResource(IDS_WIZ_PAGE6_TITLE, &bstrTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrTitle.m_str);
SetHeaderTitle(bstrTitle);
hr = LoadStringFromResource(IDS_WIZ_PAGE6_SUBTITLE, &bstrSubTitle);
_ASSERTE(S_OK == hr);
_ASSERTE(NULL != bstrSubTitle.m_str);
SetHeaderSubTitle(bstrSubTitle);
}
BOOL
CCreateDfsRootWizPage6::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown.
Set the default value of dfsroot name
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
if (m_lpWizInfo->bRootReplica)
return FALSE; // we skip this page in case of creating new root target
SetDefaultValues(); // Update the controls to contain the default values
UpdateLabels(); // Change the labels
::PropSheet_SetWizButtons(GetParent(), PSWIZB_BACK | PSWIZB_NEXT);
return TRUE;
}
HRESULT
CCreateDfsRootWizPage6::SetDefaultValues(
)
/*++
Routine Description:
Sets the default values for controls in the dialog box.
Sets the default dfsroot name to the share name
Arguments:
None
Return value:
S_OK
--*/
{
HWND hwndDfsRoot = GetDlgItem(IDC_EDIT_DFSROOT_NAME);
if (DFS_TYPE_FTDFS == m_lpWizInfo->DfsType)
{
::SendMessage(hwndDfsRoot,
EM_LIMITTEXT, MAX_RDN_KEY_SIZE, 0);
}
if (NULL != m_lpWizInfo->bstrDfsRootName) // Set the default dfsroot name
{
SetDlgItemText(IDC_EDIT_DFSROOT_NAME, m_lpWizInfo->bstrDfsRootName);
}
::SendMessage(GetDlgItem(IDC_EDIT_DFSROOT_COMMENT), EM_LIMITTEXT, MAXCOMMENTSZ, 0);
return S_OK;
}
HRESULT
CCreateDfsRootWizPage6::UpdateLabels(
)
/*++
Routine Description:
Change the text labels to show previous selections
--*/
{
CComBSTR bstrDfsRootName;
DWORD dwTextLength = 0;
(void)GetInputText(GetDlgItem(IDC_EDIT_DFSROOT_NAME), &bstrDfsRootName, &dwTextLength);
SetDlgItemText(IDC_ROOT_SHARE, bstrDfsRootName);
CComBSTR bstrFullPath = _T("\\\\");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrFullPath);
if (DFS_TYPE_FTDFS == m_lpWizInfo->DfsType)
bstrFullPath += m_lpWizInfo->bstrSelectedDomain;
else
bstrFullPath += m_lpWizInfo->bstrSelectedServer;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrFullPath);
bstrFullPath += _T("\\");
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrFullPath);
bstrFullPath += bstrDfsRootName;
RETURN_OUTOFMEMORY_IF_NULL((BSTR)bstrFullPath);
SetDlgItemText(IDC_TEXT_DFSROOT_PREFIX, bstrFullPath);
::SendMessage(GetDlgItem(IDC_TEXT_DFSROOT_PREFIX), EM_SETSEL, 0, (LPARAM)-1);
::SendMessage(GetDlgItem(IDC_TEXT_DFSROOT_PREFIX), EM_SETSEL, (WPARAM)-1, 0);
::SendMessage(GetDlgItem(IDC_TEXT_DFSROOT_PREFIX), EM_SCROLLCARET, 0, 0);
return S_OK;
}
LRESULT
CCreateDfsRootWizPage6::OnChangeDfsRoot(
WORD wNotifyCode,
WORD wID,
HWND hWndCtl,
BOOL& bHandled)
{
UpdateLabels();
return TRUE;
}
BOOL
CCreateDfsRootWizPage6::OnWizardNext(
)
/*++
Routine Description:
Called when the user presses the next button.
We get the user specified values here and take action on these.
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
CWaitCursor WaitCursor; // Set cursor to wait
HRESULT hr = S_OK;
CComBSTR bstrCurrentText;
DWORD dwTextLength = 0;
// get dfsroot name
hr = GetInputText(GetDlgItem(IDC_EDIT_DFSROOT_NAME), &bstrCurrentText, &dwTextLength);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
} else if (0 == dwTextLength)
{
DisplayMessageBoxWithOK(IDS_MSG_EMPTY_FIELD);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
}
// See if the Dfs Name has illegal Characters.
if (_tcscspn(bstrCurrentText, _T("\\/@")) != _tcslen(bstrCurrentText) ||
(DFS_TYPE_FTDFS == m_lpWizInfo->DfsType && I_NetNameValidate(NULL, bstrCurrentText, NAMETYPE_SHARE, 0)) )
{
DisplayMessageBoxWithOK(IDS_MSG_WIZ_BAD_DFS_NAME,NULL);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
}
// domain DFS only: See if the Dfs Name exists.
if (DFS_TYPE_FTDFS == m_lpWizInfo->DfsType)
{
BOOL bRootAlreadyExist = FALSE;
NETNAMELIST DfsRootList;
if (S_OK == GetDomainDfsRoots(&DfsRootList, m_lpWizInfo->bstrSelectedDomain))
{
for (NETNAMELIST::iterator i = DfsRootList.begin(); i != DfsRootList.end(); i++)
{
if (!lstrcmpi((*i)->bstrNetName, bstrCurrentText))
{
bRootAlreadyExist = TRUE;
break;
}
}
FreeNetNameList(&DfsRootList);
}
if (bRootAlreadyExist)
{
DisplayMessageBoxWithOK(IDS_MSG_ROOT_ALREADY_EXISTS, bstrCurrentText);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
}
}
hr = CheckShare(m_lpWizInfo->bstrSelectedServer, bstrCurrentText, &m_lpWizInfo->bShareExists);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
} else if (S_FALSE == hr)
{
DisplayMessageBoxWithOK(IDS_MSG_ROOTSHARE_NOGOOD, bstrCurrentText);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
}
if (m_lpWizInfo->bPostW2KVersion && m_lpWizInfo->bShareExists && !CheckReparsePoint(m_lpWizInfo->bstrSelectedServer, bstrCurrentText))
{
DisplayMessageBoxWithOK(IDS_MSG_ROOTSHARE_NOTNTFS5, bstrCurrentText);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_NAME));
return FALSE;
}
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrDfsRootName);
m_lpWizInfo->bstrDfsRootName = bstrCurrentText.Detach();
// get dfsroot comment
hr = GetInputText(GetDlgItem(IDC_EDIT_DFSROOT_COMMENT), &bstrCurrentText, &dwTextLength);
if (FAILED(hr))
{
DisplayMessageBoxForHR(hr);
::SetFocus(GetDlgItem(IDC_EDIT_DFSROOT_COMMENT));
return FALSE;
}
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrDfsRootComment);
m_lpWizInfo->bstrDfsRootComment = bstrCurrentText.Detach();
return TRUE;
}
BOOL
CCreateDfsRootWizPage6::OnWizardBack(
)
/*++
Routine Description:
Called when the "Back" button is pressed. Resets the values
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
SAFE_SYSFREESTRING(&m_lpWizInfo->bstrDfsRootName);
return TRUE;
}
// ----------------------------------------------------------------------------
// CCreateDfsRootWizPage7: Completion page
// The final page. Just displays a message
CCreateDfsRootWizPage7::CCreateDfsRootWizPage7(
IN LPCREATEDFSROOTWIZINFO i_lpWizInfo /* = NULL */
)
:m_lpWizInfo(i_lpWizInfo), CQWizardPageImpl<CCreateDfsRootWizPage7> (false)
/*++
Routine Description:
The ctor for CCreateDfsRootWizPage7. Calls the parent ctor and ignores
the wizard struct.
Arguments:
i_lpWizInfo - The wizard information structure. Contains details like
domain name, server name, etc
Return value:
None
--*/
{
}
BOOL
CCreateDfsRootWizPage7::OnSetActive()
/*++
Routine Description:
Called when the page is being showed. Sets the buttons to be shown.
Set the default value of dfsroot name
Arguments:
None
Return value:
TRUE. Since we handle the message
--*/
{
CWaitCursor wait;
UpdateLabels(); // Change the labels
::PropSheet_SetWizButtons(GetParent(), PSWIZB_FINISH | PSWIZB_BACK);
::SetControlFont(m_lpWizInfo->hBigBoldFont, m_hWnd, IDC_COMPLETE_BIG_TITLE);
::SetControlFont(m_lpWizInfo->hBoldFont, m_hWnd, IDC_COMPLETE_SMALL_TITLE);
return TRUE;
}
HRESULT
CCreateDfsRootWizPage7::UpdateLabels(
)
/*++
Routine Description:
Change the text labels to show previous selections
Arguments:
None
Return value:
S_OK, on success
--*/
{
/* bug#217602 Remove the Publish checkbox from the New Root Wizard final page (for all types of root)
if (S_OK == GetSchemaVersionEx(m_lpWizInfo->bstrSelectedServer) &&
CheckPolicyOnSharePublish())
{
CheckDlgButton(IDC_DFSWIZ_PUBLISH, BST_CHECKED);
} else
{
m_lpWizInfo->bPublish = false;
MyShowWindow(GetDlgItem(IDC_DFSWIZ_PUBLISH), FALSE);
}
*/
CComBSTR bstrText;
if (DFS_TYPE_FTDFS == m_lpWizInfo->DfsType)
{
FormatMessageString(&bstrText, 0, IDS_DFSWIZ_TEXT_FTDFS,
m_lpWizInfo->bstrSelectedDomain,
m_lpWizInfo->bstrSelectedServer,
m_lpWizInfo->bstrDfsRootName,
m_lpWizInfo->bstrDfsRootName);
} else
{
FormatMessageString(&bstrText, 0, IDS_DFSWIZ_TEXT_SADFS,
m_lpWizInfo->bstrSelectedServer,
m_lpWizInfo->bstrDfsRootName,
m_lpWizInfo->bstrDfsRootName);
}
SetDlgItemText(IDC_DFSWIZ_TEXT, bstrText);
return S_OK;
}
BOOL
CCreateDfsRootWizPage7::OnWizardFinish(
)
/*++
Routine Description:
Called when the user presses the finish button. This is the
last page in the wizard.
Arguments:
None
Return value:
TRUE. to let the user continue to the next page
FALSE, to not let the user continue ahead.
--*/
{
/* bug#217602 Remove the Publish checkbox from the New Root Wizard final page (for all types of root)
m_lpWizInfo->bPublish = (BST_CHECKED == IsDlgButtonChecked(IDC_DFSWIZ_PUBLISH));
*/
return (S_OK == _SetUpDfs(m_lpWizInfo));
}
BOOL
CCreateDfsRootWizPage7::OnWizardBack()
{
//
// if share was created by the previous page, blow it away when we go back
//
if (!m_lpWizInfo->bShareExists)
NetShareDel(m_lpWizInfo->bstrSelectedServer, m_lpWizInfo->bstrDfsRootName, 0);
return TRUE;
}
BOOL CCreateDfsRootWizPage7::OnQueryCancel()
{
//
// if share was created by the previous page, blow it away when we cancel the wizard
//
if (!m_lpWizInfo->bShareExists)
NetShareDel(m_lpWizInfo->bstrSelectedServer, m_lpWizInfo->bstrDfsRootName, 0);
return TRUE; // ok to cancel
}
HRESULT _SetUpDfs(
LPCREATEDFSROOTWIZINFO i_lpWizInfo
)
/*++
Routine Description:
Helper Function to Setup Dfs, called from wizard and new root replica,
Finish() method of Page5 if root level replca is created and Next() method of Page6
for Create New Dfs Root Wizard.
Arguments:
i_lpWizInfo - Wizard data.
Return value:
S_OK, on success
--*/
{
if (!i_lpWizInfo ||
!(i_lpWizInfo->bstrSelectedServer) ||
!(i_lpWizInfo->bstrDfsRootName))
return(E_INVALIDARG);
CWaitCursor WaitCursor; // Set cursor to wait
HRESULT hr = S_OK;
NET_API_STATUS nstatRetVal = 0;
// Set up the dfs, based on type.
if (DFS_TYPE_FTDFS == i_lpWizInfo->DfsType)
{
nstatRetVal = NetDfsAddFtRoot(
i_lpWizInfo->bstrSelectedServer, // Remote Server
i_lpWizInfo->bstrDfsRootName, // Root Share
i_lpWizInfo->bstrDfsRootName, // FtDfs Name
i_lpWizInfo->bstrDfsRootComment, // Comment
0 // No Flags.
);
} else
{
nstatRetVal = NetDfsAddStdRoot(
i_lpWizInfo->bstrSelectedServer, // Remote Server
i_lpWizInfo->bstrDfsRootName, // Root Share
i_lpWizInfo->bstrDfsRootComment, // Comment
0 // No Flags.
);
}
if (NERR_Success != nstatRetVal)
{
hr = HRESULT_FROM_WIN32(nstatRetVal);
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_FAILED_TO_CREATE_DFSROOT, i_lpWizInfo->bstrSelectedServer);
hr = S_FALSE; // failed to create dfsroot, wizard cannot be closed
} else
{
i_lpWizInfo->bDfsSetupSuccess = true;
/* bug#217602 Remove the Publish checkbox from the New Root Wizard final page (for all types of root)
if (i_lpWizInfo->bPublish)
{
CComBSTR bstrUNCPath = _T("\\\\");
if (DFS_TYPE_FTDFS == i_lpWizInfo->DfsType)
{
bstrUNCPath += i_lpWizInfo->bstrSelectedDomain;
bstrUNCPath += _T("\\");
bstrUNCPath += i_lpWizInfo->bstrDfsRootName;
hr = ModifySharePublishInfoOnFTRoot(
i_lpWizInfo->bstrSelectedDomain,
i_lpWizInfo->bstrDfsRootName,
TRUE,
bstrUNCPath,
NULL,
NULL,
NULL
);
} else
{
bstrUNCPath += i_lpWizInfo->bstrSelectedServer;
bstrUNCPath += _T("\\");
bstrUNCPath += i_lpWizInfo->bstrSelectedShare;
hr = ModifySharePublishInfoOnSARoot(
i_lpWizInfo->bstrSelectedServer,
i_lpWizInfo->bstrSelectedShare,
TRUE,
bstrUNCPath,
NULL,
NULL,
NULL
);
if (S_FALSE == hr)
hr = S_OK; // ignore non-existing object
}
if (FAILED(hr))
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_FAILED_TO_PUBLISH_DFSROOT, bstrUNCPath);
hr = S_OK; // let wizard finish and close, ignore this error
} else if (S_FALSE == hr) // no such object
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_FAILED_TO_PUBLISH_NOROOTOBJ);
hr = S_OK; // let wizard finish and close, ignore this error
}
} */
}
return hr;
}
HRESULT
ValidateFolderPath(
IN LPCTSTR lpszServer,
IN LPCTSTR lpszPath
)
{
if (!lpszPath || !*lpszPath)
return E_INVALIDARG;
HWND hwnd = ::GetActiveWindow();
HRESULT hr = S_FALSE;
do {
if (!IsValidLocalAbsolutePath(lpszPath))
{
DisplayMessageBox(hwnd, MB_OK, 0, IDS_INVALID_FOLDER);
break;
}
hr = IsComputerLocal(lpszServer);
if (FAILED(hr))
{
DisplayMessageBox(hwnd, MB_OK, hr, IDS_FAILED_TO_VALIDATE_FOLDER, lpszPath);
break;
}
BOOL bLocal = (S_OK == hr);
hr = VerifyDriveLetter(lpszServer, lpszPath);
if (FAILED(hr))
{
DisplayMessageBox(hwnd, MB_OK, hr, IDS_FAILED_TO_VALIDATE_FOLDER, lpszPath);
break;
} else if (S_OK != hr)
{
DisplayMessageBox(hwnd, MB_OK, 0, IDS_INVALID_FOLDER);
break;
}
if (!bLocal)
{
hr = IsAdminShare(lpszServer, lpszPath);
if (FAILED(hr))
{
DisplayMessageBox(hwnd, MB_OK, hr, IDS_FAILED_TO_VALIDATE_FOLDER, lpszPath);
break;
} else if (S_OK != hr)
{
// there is no matching $ shares, hence, no need to call GetFileAttribute, CreateDirectory,
// assume lpszDir points to an existing directory
hr = S_OK;
break;
}
}
CComBSTR bstrFullPath;
hr = GetFullPath(lpszServer, lpszPath, &bstrFullPath);
if (FAILED(hr))
{
DisplayMessageBox(hwnd, MB_OK, hr, IDS_FAILED_TO_VALIDATE_FOLDER, lpszPath);
break;
}
hr = IsAnExistingFolder(hwnd, bstrFullPath);
if (FAILED(hr) || S_OK == hr)
break;
if ( IDYES != DisplayMessageBox(hwnd, MB_YESNO, 0, IDS_CREATE_FOLDER, bstrFullPath) )
{
hr = S_FALSE;
break;
}
// create the directories layer by layer
hr = CreateLayeredDirectory(lpszServer, lpszPath);
if (FAILED(hr))
{
DisplayMessageBox(hwnd, MB_OK, hr, IDS_FAILED_TO_CREATE_FOLDER, bstrFullPath);
break;
}
} while (0);
return hr;
}