You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1498 lines
45 KiB
1498 lines
45 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: ncident.cpp
|
|
//
|
|
// Contents: Implementation of CNetCfgIdentification.
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 21 Mar 1997 danielwe Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include <nceh.h>
|
|
#include "ncfgval.h"
|
|
#include "ncident.h"
|
|
#include "ncmisc.h"
|
|
#include "ncreg.h"
|
|
#include "nsbase.h"
|
|
#include "nccom.h"
|
|
#include "ncerror.h"
|
|
|
|
EXTERN_C extern const INT MAX_WORKGROUPNAME_LENGTH;
|
|
EXTERN_C extern const INT MAX_DOMAINNAME_LENGTH;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DeleteStringAndSetNull
|
|
//
|
|
// Purpose: Frees the given string with delete, and sets it to
|
|
// NULL before exiting.
|
|
//
|
|
// Arguments:
|
|
// pszw [in, out] Pointer to string to be freed. The pointer is set to
|
|
// NULL before the function exits.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
// Author: danielwe 1 Apr 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
inline VOID DeleteStringAndSetNull(PWSTR *pszw)
|
|
{
|
|
AssertSz(pszw, "Param is NULL!");
|
|
|
|
delete *pszw;
|
|
*pszw = NULL;
|
|
}
|
|
|
|
inline HRESULT HrNetValidateName(IN PCWSTR lpMachine,
|
|
IN PCWSTR lpName,
|
|
IN PCWSTR lpAccount,
|
|
IN PCWSTR lpPassword,
|
|
IN NETSETUP_NAME_TYPE NameType)
|
|
{
|
|
NET_API_STATUS nerr;
|
|
|
|
nerr = NetValidateName(const_cast<PWSTR>(lpMachine),
|
|
const_cast<PWSTR>(lpName),
|
|
const_cast<PWSTR>(lpAccount),
|
|
const_cast<PWSTR>(lpPassword),
|
|
NameType);
|
|
|
|
TraceError("NetValidateName", HRESULT_FROM_WIN32(nerr));
|
|
return HrFromNerr(nerr);
|
|
}
|
|
|
|
|
|
inline HRESULT HrNetJoinDomain(IN PWSTR lpMachine,
|
|
IN PWSTR lpMachineObjectOU,
|
|
IN PWSTR lpDomain,
|
|
IN PWSTR lpAccount,
|
|
IN PWSTR lpPassword,
|
|
IN DWORD fJoinOptions)
|
|
{
|
|
NET_API_STATUS nerr;
|
|
HRESULT hr;
|
|
|
|
if ( fJoinOptions & NETSETUP_JOIN_DOMAIN )
|
|
{
|
|
hr = HrNetValidateName( lpMachine, lpDomain, lpAccount,
|
|
lpPassword, NetSetupDomain );
|
|
}
|
|
else
|
|
{
|
|
hr = HrNetValidateName( lpMachine, lpDomain, lpAccount,
|
|
lpPassword, NetSetupWorkgroup );
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
nerr = NetJoinDomain(lpMachine, lpDomain, lpMachineObjectOU,
|
|
lpAccount, lpPassword, fJoinOptions);
|
|
|
|
TraceError("NetJoinDomain", HRESULT_FROM_WIN32(nerr));
|
|
|
|
hr = HrFromNerr(nerr);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
inline HRESULT HrNetRenameInDomain(IN PWSTR lpMachine,
|
|
IN PWSTR lpNewMachine,
|
|
IN PWSTR lpAccount,
|
|
IN PWSTR lpPassword,
|
|
IN DWORD fJoinOptions)
|
|
{
|
|
NET_API_STATUS nerr;
|
|
|
|
nerr = NetRenameMachineInDomain(lpMachine, lpNewMachine, lpAccount,
|
|
lpPassword, fJoinOptions);
|
|
TraceError("NetRenameMachineInDomain", HRESULT_FROM_WIN32(nerr));
|
|
return HrFromNerr(nerr);
|
|
}
|
|
|
|
inline HRESULT HrNetUnjoinDomain(IN PWSTR lpAccount,
|
|
IN PWSTR lpPassword,
|
|
IN DWORD fJoinOptions)
|
|
{
|
|
NET_API_STATUS nerr;
|
|
|
|
nerr = NetUnjoinDomain(NULL,lpAccount, lpPassword, fJoinOptions);
|
|
|
|
TraceError("NetUnjoinDomain", HRESULT_FROM_WIN32(nerr));
|
|
return HrFromNerr(nerr);
|
|
}
|
|
|
|
inline HRESULT HrNetGetJoinInformation(IN PWSTR lpNameBuffer,
|
|
OUT LPDWORD lpNameBufferSize,
|
|
OUT PNETSETUP_JOIN_STATUS BufferType)
|
|
{
|
|
NET_API_STATUS nerr;
|
|
PWSTR JoinBuff = NULL;
|
|
|
|
nerr = NetGetJoinInformation(NULL, &JoinBuff, BufferType);
|
|
|
|
if ( nerr == NERR_Success ) {
|
|
|
|
if ( *BufferType == NetSetupUnjoined ) {
|
|
|
|
*lpNameBufferSize = 0;
|
|
*lpNameBuffer = UNICODE_NULL;
|
|
|
|
} else {
|
|
|
|
if ( *lpNameBufferSize >= ( wcslen( JoinBuff ) +1 ) * sizeof( WCHAR ) ) {
|
|
|
|
wcscpy( lpNameBuffer, JoinBuff );
|
|
|
|
}
|
|
|
|
*lpNameBufferSize = wcslen( JoinBuff ) +1;
|
|
|
|
NetApiBufferFree( JoinBuff );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TraceError("NetGetJoinInformation", HRESULT_FROM_WIN32(nerr));
|
|
return HrFromNerr(nerr);
|
|
}
|
|
|
|
#ifdef DBG
|
|
BOOL CNetCfgIdentification::FIsJoinedToDomain()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
NETSETUP_JOIN_STATUS js;
|
|
WCHAR wszBuffer[256];
|
|
DWORD cchBuffer = celems(wszBuffer);
|
|
|
|
hr = HrNetGetJoinInformation(wszBuffer, &cchBuffer, &js);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (js == NetSetupUnjoined)
|
|
{
|
|
// If we're as yet unjoined, only make sure that we marked our
|
|
// internal state as being joined to a workgroup called "WORKGROUP"
|
|
AssertSz(m_jsCur == NetSetupWorkgroupName, "We're unjoined but not "
|
|
"joined to a workgroup!");
|
|
AssertSz(m_szwCurDWName, "No current domain or "
|
|
"workgroup name?");
|
|
AssertSz(!lstrcmpiW(m_szwCurDWName,
|
|
SzLoadIds(IDS_WORKGROUP)),
|
|
"Workgroup name is not generic!");
|
|
}
|
|
else
|
|
{
|
|
AssertSz(js == m_jsCur, "Join status is not what we think it is!!");
|
|
}
|
|
}
|
|
|
|
TraceError("CNetCfgIdentification::FIsJoinedToDomain - "
|
|
"HrNetGetJoinInformation", hr);
|
|
|
|
return (m_jsCur == NetSetupDomainName);
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrFromNerr
|
|
//
|
|
// Purpose: Converts a NET_API_STATUS code into a NETCFG_E_* HRESULT
|
|
// value.
|
|
//
|
|
// Arguments:
|
|
// nerr [in] Status code to convert.
|
|
//
|
|
// Returns: HRESULT, Converted HRESULT value.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT HrFromNerr(NET_API_STATUS nerr)
|
|
{
|
|
HRESULT hr;
|
|
|
|
switch (nerr)
|
|
{
|
|
case NERR_Success:
|
|
hr = S_OK;
|
|
break;
|
|
case NERR_SetupAlreadyJoined:
|
|
hr = NETCFG_E_ALREADY_JOINED;
|
|
break;
|
|
case ERROR_DUP_NAME:
|
|
hr = NETCFG_E_NAME_IN_USE;
|
|
break;
|
|
case NERR_SetupNotJoined:
|
|
hr = NETCFG_E_NOT_JOINED;
|
|
break;
|
|
// case NERR_SetupIsDC:
|
|
// hr = NETCFG_E_MACHINE_IS_DC;
|
|
// break;
|
|
// case NERR_SetupNotAServer:
|
|
// hr = NETCFG_E_NOT_A_SERVER;
|
|
// break;
|
|
// case NERR_SetupImproperRole:
|
|
// hr = NETCFG_E_INVALID_ROLE;
|
|
// break;
|
|
case ERROR_INVALID_PARAMETER:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
case ERROR_ACCESS_DENIED:
|
|
hr = E_ACCESSDENIED;
|
|
break;
|
|
case NERR_InvalidComputer:
|
|
case ERROR_NO_SUCH_DOMAIN:
|
|
hr = NETCFG_E_INVALID_DOMAIN;
|
|
break;
|
|
default:
|
|
// Generic INetCfgIdentification error
|
|
//$ REVIEW (danielwe) 24 Jun 1997: What if this isn't a Win32 error?
|
|
hr = HRESULT_FROM_WIN32(nerr);
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//
|
|
// INetCfgIdentification implementation
|
|
//
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrEnsureCurrentComputerName
|
|
//
|
|
// Purpose: Ensures that the current computer name exists to act on.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes: Sets the m_szwCurComputerName variable.
|
|
//
|
|
HRESULT CNetCfgIdentification::HrEnsureCurrentComputerName()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_szwCurComputerName)
|
|
{
|
|
PWSTR pszwComputer;
|
|
|
|
// Go get the current computer name because we don't know it yet.
|
|
hr = HrGetCurrentComputerName(&pszwComputer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// m_szwCurComputerName is now set as a side effect
|
|
|
|
CoTaskMemFree(pszwComputer);
|
|
}
|
|
}
|
|
|
|
AssertSz(FImplies(SUCCEEDED(hr), m_szwCurComputerName),
|
|
"I MUST have a name here!");
|
|
|
|
TraceError("CNetCfgIdentification::HrEnsureCurrentComputerName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrGetNewestComputerName
|
|
//
|
|
// Purpose: Places the most recently referenced computer name into the
|
|
// output parameter.
|
|
//
|
|
// Arguments:
|
|
// pwszName [out] Most recently referenced computer name.
|
|
//
|
|
// Returns: Possible Win32 error code.
|
|
//
|
|
// Author: danielwe 24 Mar 1997
|
|
//
|
|
// Notes: If the SetComputerName() method was never called, this sets
|
|
// the m_szwCurComputerName variable and returns a pointer to it.
|
|
// Otherwise, it will return a pointer to the computer name
|
|
// given in the SetComputerName() call.
|
|
//
|
|
HRESULT CNetCfgIdentification::HrGetNewestComputerName(PCWSTR *pwszName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
AssertSz(pwszName, "NULL out param!");
|
|
|
|
*pwszName = NULL;
|
|
|
|
// New computer name is absent, use current computer name.
|
|
hr = HrEnsureCurrentComputerName();
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
*pwszName = m_szwCurComputerName;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrGetNewestComputerName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrValidateMachineName
|
|
//
|
|
// Purpose: Validates the given machine name.
|
|
//
|
|
// Arguments:
|
|
// szwName [in] Machine name to validate.
|
|
//
|
|
// Returns: S_OK if machine name is valid, NETCFG_E_NAME_IN_USE if machine
|
|
// name is in use.
|
|
//
|
|
// Author: danielwe 24 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrValidateMachineName(PCWSTR szwName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Only validate if networking is installed
|
|
hr = HrIsNetworkingInstalled();
|
|
if (hr == S_OK)
|
|
{
|
|
// Current computer name is unused for validation of machine name.
|
|
hr = HrNetValidateName(NULL,
|
|
szwName,
|
|
NULL, NULL,
|
|
NetSetupMachine);
|
|
if (FAILED(hr))
|
|
{
|
|
//$REVIEW(danielwe): What error code to return here?
|
|
TraceError("NetValidateName - Machine Name", hr);
|
|
}
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
// no networking installed. We're fine.
|
|
hr = S_OK;
|
|
}
|
|
|
|
TraceError("CNetCfgIdentification::HrValidateMachineName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrValidateWorkgroupName
|
|
//
|
|
// Purpose: Validates the given workgroup name.
|
|
//
|
|
// Arguments:
|
|
// szwName [in] Workgroup name to validate.
|
|
//
|
|
// Returns: S_OK if machine name is valid, NETCFG_E_NAME_IN_USE if machine
|
|
// name is in use.
|
|
//
|
|
// Author: danielwe 24 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrValidateWorkgroupName(PCWSTR szwName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCWSTR wszComputerName = NULL;
|
|
|
|
// If the user has changed the computer name, use it, otherwise get the
|
|
// current computer name and use that.
|
|
hr = HrGetNewestComputerName(&wszComputerName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
AssertSz(wszComputerName, "We don't have a computer name!");
|
|
|
|
hr = HrNetValidateName(const_cast<PWSTR>(wszComputerName),
|
|
szwName, NULL, NULL, NetSetupWorkgroup);
|
|
if (FAILED(hr))
|
|
{
|
|
//$REVIEW(danielwe): What error code to return here?
|
|
TraceError("NetValidateName - Workgroup Name", hr);
|
|
goto err;
|
|
}
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrValidateWorkgroupName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrValidateDomainName
|
|
//
|
|
// Purpose: Validates the given domain name.
|
|
//
|
|
// Arguments:
|
|
// szwName [in] Name of domain to validate.
|
|
// szwUserName [in] Username for authorization purposes.
|
|
// szwPassword [in] Password for authorization purposes.
|
|
//
|
|
// Returns: S_OK if machine name is valid, NETCFG_E_INVALID_DOMAIN if
|
|
// domain name is invalid (or non-existent).
|
|
//
|
|
// Author: danielwe 24 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrValidateDomainName(PCWSTR szwName,
|
|
PCWSTR szwUserName,
|
|
PCWSTR szwPassword)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// NetValidateName does not use the machine name in validating the
|
|
// domain name. So it is NULL here.
|
|
hr = HrNetValidateName(NULL, szwName,
|
|
szwUserName,
|
|
szwPassword,
|
|
NetSetupDomain);
|
|
if (FAILED(hr))
|
|
{
|
|
//$REVIEW(danielwe): What error code to return here?
|
|
TraceError("NetValidateName - Domain Name", hr);
|
|
goto err;
|
|
}
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrValidateDomainName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::Validate
|
|
//
|
|
// Purpose: Implements COM function to validate current set of values
|
|
// used during the lifetime of this object.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::Validate()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgIdentification_Validate();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
if (m_szwNewDWName)
|
|
{
|
|
if (GetNewJoinStatus() == NetSetupWorkgroupName)
|
|
{
|
|
// Validate workgroup name
|
|
hr = HrValidateWorkgroupName(m_szwNewDWName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
}
|
|
else if (GetNewJoinStatus() == NetSetupDomainName)
|
|
{
|
|
// Validate domain name
|
|
hr = HrValidateDomainName(m_szwNewDWName, m_szwUserName,
|
|
m_szwPassword);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
AssertSz(FALSE, "Invalid join status!");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
err:
|
|
// Translate all errors to S_FALSE.
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
m_fValid = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// spew out trace *before* the assignment so we know what the *real*
|
|
// error code was.
|
|
TraceError("CNetCfgIdentification::Validate (before S_FALSE)", hr);
|
|
hr = S_FALSE;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::Cancel
|
|
//
|
|
// Purpose: Cancels any changes made during the lifetime of the object.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns:
|
|
//
|
|
// Author: danielwe 25 Mar 1997
|
|
//
|
|
// Notes: Resets state information and frees any memory previously
|
|
// allocted.
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::Cancel()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgIdentification_Cancel();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
DeleteStringAndSetNull(&m_szwNewDWName);
|
|
DeleteStringAndSetNull(&m_szwPassword);
|
|
DeleteStringAndSetNull(&m_szwUserName);
|
|
DeleteStringAndSetNull(&m_szwCurComputerName);
|
|
DeleteStringAndSetNull(&m_szwCurDWName);
|
|
|
|
m_dwJoinFlags = 0;
|
|
m_dwCreateFlags = 0;
|
|
m_fValid = FALSE;
|
|
m_jsNew = NetSetupUnjoined;
|
|
}
|
|
|
|
COM_PROTECT_CATCH;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::Apply
|
|
//
|
|
// Purpose: Implements COM function to apply changes that were made
|
|
// during the lifetime of this object.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::Apply()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgIdentification_Apply();
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
// Has data been validated?
|
|
if (!m_fValid)
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
goto err;
|
|
}
|
|
|
|
if (m_szwNewDWName)
|
|
{
|
|
if (GetNewJoinStatus() == NetSetupWorkgroupName)
|
|
{
|
|
// The user specified a workgroup name. This means they want
|
|
// to join a workgroup.
|
|
hr = HrJoinWorkgroup();
|
|
if (FAILED(hr))
|
|
goto err;
|
|
}
|
|
else if (GetNewJoinStatus() == NetSetupDomainName)
|
|
{
|
|
// The user specified a domain name. This means they want to
|
|
// join a domain.
|
|
hr = HrJoinDomain();
|
|
if (FAILED(hr))
|
|
goto err;
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
AssertSz(FALSE, "Invalid join status!");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
err:
|
|
// Regardless of result, set valid flag to false again to require
|
|
// Validate() to be called again before calling Apply().
|
|
// $REVIEW (danielwe): Is this how we want to do it?
|
|
m_fValid = FALSE;
|
|
|
|
TraceError("CNetCfgIdentification::Apply", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrGetCurrentComputerName
|
|
//
|
|
// Purpose: Calls the Win32 GetComputerName API to get the current
|
|
// computer name.
|
|
//
|
|
// Arguments:
|
|
// ppszwComputer [out] Returned computer name.
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes: Makes a private copy of the computer name if obtained from the
|
|
// system (for further use).
|
|
//
|
|
HRESULT CNetCfgIdentification::HrGetCurrentComputerName(PWSTR* ppszwComputer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR szBuffer[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD cchBuffer = celems(szBuffer);
|
|
|
|
if (::GetComputerName(szBuffer, &cchBuffer))
|
|
{
|
|
// Make a copy for the out param.
|
|
hr = HrCoTaskMemAllocAndDupSz (
|
|
szBuffer, ppszwComputer, celems(szBuffer) );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Make another copy for our own use.
|
|
DeleteStringAndSetNull(&m_szwCurComputerName);
|
|
m_szwCurComputerName = SzDupSz(szBuffer);
|
|
|
|
AssertSz((DWORD)lstrlenW(*ppszwComputer) == cchBuffer,
|
|
"This is not how big the string is!");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TraceLastWin32Error("::GetComputerName");
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
|
|
TraceError("CNetCfgIdentification::HrGetCurrentComputerName", hr);
|
|
return hr;
|
|
}
|
|
|
|
static const WCHAR c_szRegKeyComputerName[] = L"System\\CurrentControlSet\\Control\\ComputerName\\ComputerName";
|
|
static const WCHAR c_szRegValueComputerName[] = L"ComputerName";
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrGetNewComputerName
|
|
//
|
|
// Purpose: Helper function to retreive the new computer name from the
|
|
// registry. This will be the same as the active computer name
|
|
// unless the user has changed the computer name since booting.
|
|
//
|
|
// Arguments:
|
|
// ppszwComputer [out] Returns new computer name.
|
|
//
|
|
// Returns: S_OK if successful, Win32 error code otherwise.
|
|
//
|
|
// Author: danielwe 21 May 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrGetNewComputerName(PWSTR* ppszwComputer)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
WCHAR szBuffer[MAX_COMPUTERNAME_LENGTH + 1];
|
|
DWORD cbBuffer = sizeof(szBuffer);
|
|
HKEY hkeyComputerName;
|
|
|
|
hr = HrRegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyComputerName,
|
|
KEY_READ, &hkeyComputerName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegQuerySzBuffer(hkeyComputerName, c_szRegValueComputerName,
|
|
szBuffer, &cbBuffer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Make a copy for the out param.
|
|
hr = HrCoTaskMemAllocAndDupSz (
|
|
szBuffer, ppszwComputer, celems(szBuffer) );
|
|
|
|
AssertSz(FImplies(SUCCEEDED(hr),
|
|
(lstrlenW(*ppszwComputer) + 1) * sizeof(WCHAR) == cbBuffer),
|
|
"This is not how big the string is!");
|
|
}
|
|
|
|
RegCloseKey(hkeyComputerName);
|
|
}
|
|
|
|
TraceError("CNetCfgIdentification::HrGetCurrentComputerName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName
|
|
//
|
|
// Purpose: Obtains the current domain or workgroup to which this machine
|
|
// belongs.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: S_OK if success, error code otherwise.
|
|
//
|
|
// Author: danielwe 26 Mar 1997
|
|
//
|
|
// Notes: A machine can be joined to either or workgroup or a domain. It
|
|
// must be joined to one or the other. If it is not, we'll use a
|
|
// more or less hardcoded string and "fake it" as if the machine
|
|
// was joined to a workgroup. The member variables:
|
|
// m_jsCur and m_szwCurDWName are set by this function.
|
|
//
|
|
// This call only does work once. Subsequent calls do nothing.
|
|
//
|
|
HRESULT CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_szwCurDWName)
|
|
{
|
|
NETSETUP_JOIN_STATUS js;
|
|
WCHAR wszBuffer[256];
|
|
PCWSTR wszName;
|
|
DWORD cchBuffer = celems(wszBuffer);
|
|
|
|
hr = HrNetGetJoinInformation(wszBuffer, &cchBuffer, &js);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
AssertSz(FIff(*wszBuffer, cchBuffer), "Buffer size inconsistency!");
|
|
|
|
if (js == NetSetupUnjoined)
|
|
{
|
|
// Uh oh. Machine is not joined to workgroup OR domain. Set
|
|
// default workgroup name and proceed as if joined to a workgroup.
|
|
js = NetSetupWorkgroupName;
|
|
|
|
// Use default name since HrNetGetJoinInformation() will return
|
|
// an empty string which is useless.
|
|
wszName = SzLoadIds(IDS_WORKGROUP);
|
|
}
|
|
else
|
|
{
|
|
// Use string returned from HrNetGetJoinInformation().
|
|
wszName = wszBuffer;
|
|
}
|
|
|
|
m_szwCurDWName = SzDupSz(wszName);
|
|
|
|
m_jsCur = js;
|
|
|
|
AssertSz(GetCurrentJoinStatus() == NetSetupWorkgroupName ||
|
|
GetCurrentJoinStatus() == NetSetupDomainName,
|
|
"Invalid join status flag!");
|
|
}
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrEnsureCurrentDomainOrWorkgroupName",
|
|
hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName
|
|
//
|
|
// Purpose: Returns the domain or workgroup name that was most recently
|
|
// referenced.
|
|
//
|
|
// Arguments:
|
|
// js [in] Tells whether the domain or workgroup name is wanted.
|
|
// pwszName [out] Domain or workgroup name.
|
|
//
|
|
// Returns: S_OK if success, E_OUTOFMEMORY if no memory.
|
|
//
|
|
// Author: danielwe 26 Mar 1997
|
|
//
|
|
// Notes: If the requested name has not been set by the user in a prior
|
|
// call, the current name is returned. Otherwise the name the
|
|
// user chose previously is returned.
|
|
//
|
|
HRESULT CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName(
|
|
NETSETUP_JOIN_STATUS js,
|
|
PCWSTR *pwszName)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PWSTR szwOut = NULL;
|
|
|
|
Assert(pwszName);
|
|
|
|
if (m_szwNewDWName && (GetNewJoinStatus() == js))
|
|
{
|
|
// Give them back a copy of the domain or workgroup name they
|
|
// previously gave us.
|
|
szwOut = m_szwNewDWName;
|
|
}
|
|
else
|
|
{
|
|
// Get the current workgroup or domain for this machine. It has
|
|
// to be in one or the other.
|
|
hr = HrEnsureCurrentDomainOrWorkgroupName();
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
if (GetCurrentJoinStatus() == js)
|
|
{
|
|
// Use the current name.
|
|
szwOut = m_szwCurDWName;
|
|
}
|
|
}
|
|
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
*pwszName = szwOut;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrGetNewestDomainOrWorkgroupName", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::GetWorkgroupName
|
|
//
|
|
// Purpose: Implements COM function to get the current workgroup name.
|
|
//
|
|
// Arguments:
|
|
// ppszwWorkgroup [out] Returns name of current workgroup.
|
|
//
|
|
// Returns: S_OK if succeeded, S_FALSE if machine is not joined to a
|
|
// workgroup, error code otherwise.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::GetWorkgroupName(PWSTR* ppszwWorkgroup)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCWSTR szwWorkgroup = NULL;
|
|
|
|
Validate_INetCfgIdentification_GetWorkgroupName(ppszwWorkgroup);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
*ppszwWorkgroup = NULL;
|
|
|
|
hr = HrGetNewestDomainOrWorkgroupName(NetSetupWorkgroupName,
|
|
&szwWorkgroup);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
if (szwWorkgroup)
|
|
{
|
|
hr = HrCoTaskMemAllocAndDupSz (
|
|
szwWorkgroup, ppszwWorkgroup, MAX_WORKGROUPNAME_LENGTH);
|
|
|
|
AssertSz(FImplies(SUCCEEDED(hr), lstrlenW(*ppszwWorkgroup) > 0),
|
|
"Why is *ppszwWorkgroup empty?");
|
|
}
|
|
else
|
|
{
|
|
// Not joined to a workgroup
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::GetWorkgroupName",
|
|
(hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::GetDomainName
|
|
//
|
|
// Purpose: Implements COM function to get the current domain name.
|
|
//
|
|
// Arguments:
|
|
// ppszwDomain [out] Returns name of domain to which this computer
|
|
// currently belongs.
|
|
//
|
|
// Returns: S_OK if succeeded, S_FALSE if machine is not joined to a
|
|
// domain, error code otherwise.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::GetDomainName(PWSTR* ppszwDomain)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCWSTR szwDomain = NULL;
|
|
|
|
Validate_INetCfgIdentification_GetDomainName(ppszwDomain);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
*ppszwDomain = NULL;
|
|
|
|
hr = HrGetNewestDomainOrWorkgroupName(NetSetupDomainName,
|
|
&szwDomain);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
if (szwDomain)
|
|
{
|
|
hr = HrCoTaskMemAllocAndDupSz (
|
|
szwDomain, ppszwDomain, MAX_DOMAINNAME_LENGTH);
|
|
|
|
AssertSz(FImplies(SUCCEEDED(hr), lstrlenW(*ppszwDomain) > 0),
|
|
"Why is *ppszwDomain empty?");
|
|
}
|
|
else
|
|
{
|
|
// Not joined to a domain
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::GetDomainName",
|
|
(hr == S_FALSE) ? S_OK : hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrJoinWorkgroup
|
|
//
|
|
// Purpose: Actually performs the JoinWorkgroup function.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrJoinWorkgroup()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCWSTR wszComputerName = NULL;
|
|
|
|
AssertSz(m_szwNewDWName &&
|
|
GetNewJoinStatus() == NetSetupWorkgroupName,
|
|
"If there was no workgroup name, why'd you call me?!");
|
|
|
|
// If the user has changed the computer name, use it, otherwise get the
|
|
// current computer name and use that.
|
|
hr = HrGetNewestComputerName(&wszComputerName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
AssertSz(wszComputerName, "We don't have a computer name!");
|
|
|
|
hr = HrEnsureCurrentDomainOrWorkgroupName();
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
if (FIsJoinedToDomain())
|
|
{
|
|
// Must unjoin from domain if currently joined.
|
|
// If currently joined to a workgroup, this is not necessary.
|
|
hr = HrNetUnjoinDomain(m_szwUserName, m_szwPassword, 0);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
// Free username and password
|
|
DeleteStringAndSetNull(&m_szwPassword);
|
|
DeleteStringAndSetNull(&m_szwUserName);
|
|
}
|
|
|
|
// Go ahead and join the workgroup
|
|
hr = HrNetJoinDomain(const_cast<PWSTR>(wszComputerName),
|
|
m_szMachineObjectOU,
|
|
m_szwNewDWName, NULL, NULL, 0);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
// Make the current workgroup name the new one since the join on the
|
|
// new workgroup has succeeded
|
|
hr = HrEstablishNewDomainOrWorkgroupName(NetSetupWorkgroupName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::HrJoinWorkgroup", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::JoinWorkgroup
|
|
//
|
|
// Purpose: Implements COM interface to join this computer to a new
|
|
// workgroup.
|
|
//
|
|
// Arguments:
|
|
// szwWorkgroup [in] Name of new workgroup to join.
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes: Validates, but does not actually join the workgroup. Only holds
|
|
// onto the information until Apply() is called.
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::JoinWorkgroup(PCWSTR szwWorkgroup)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgIdentification_JoinWorkgroup(szwWorkgroup);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
hr = HrValidateWorkgroupName(szwWorkgroup);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
// Free domain and password given if JoinDomain was called previously
|
|
DeleteStringAndSetNull(&m_szwPassword);
|
|
DeleteStringAndSetNull(&m_szwUserName);
|
|
|
|
// Assign in new workgroup name.
|
|
m_szwNewDWName = SzDupSz(szwWorkgroup);
|
|
|
|
m_jsNew = NetSetupWorkgroupName;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
err:
|
|
TraceError("CNetCfgIdentification::JoinWorkgroup", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName
|
|
//
|
|
// Purpose: When the computer is joined to a new domain or workgroup, this
|
|
// function is called to set the correct member variables and
|
|
// free the old ones.
|
|
//
|
|
// Arguments:
|
|
// js [in] Indicates whether the computer is joined to a domain or
|
|
// workgroup.
|
|
//
|
|
// Returns: S_OK, or E_OUTOFMEMORY.
|
|
//
|
|
// Author: danielwe 1 Apr 1997
|
|
//
|
|
// Notes: Replaces the m_szwCurDWName variable with the new one
|
|
// (m_szwNewDWName).
|
|
//
|
|
HRESULT CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName(
|
|
NETSETUP_JOIN_STATUS js)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Make the current domain or workgroup name the new one.
|
|
DeleteStringAndSetNull(&m_szwCurDWName);
|
|
m_szwCurDWName = SzDupSz(m_szwNewDWName);
|
|
|
|
m_jsCur = js;
|
|
|
|
AssertSz(GetCurrentJoinStatus() == NetSetupWorkgroupName ||
|
|
GetCurrentJoinStatus() == NetSetupDomainName,
|
|
"Invalid join status flag!");
|
|
|
|
// Free "new" name
|
|
DeleteStringAndSetNull(&m_szwNewDWName);
|
|
|
|
// Also make sure that we don't have a "new" join status either
|
|
m_jsNew = NetSetupUnjoined;
|
|
|
|
TraceError("CNetCfgIdentification::HrEstablishNewDomainOrWorkgroupName",
|
|
hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::HrJoinDomain
|
|
//
|
|
// Purpose: Actually performs the JoinDomain function.
|
|
//
|
|
// Arguments:
|
|
// (none)
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes:
|
|
//
|
|
HRESULT CNetCfgIdentification::HrJoinDomain()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PCWSTR wszComputerName = NULL;
|
|
DWORD dwJoinOption = 0;
|
|
BOOL fIsRename = FALSE;
|
|
BOOL fUseNulls = FALSE;
|
|
|
|
AssertSz(m_szwNewDWName && m_jsNew == NetSetupDomainName,
|
|
"If there was no domain name, why'd you call me?!");
|
|
AssertSz(FImplies(m_szwPassword,
|
|
m_szwUserName),
|
|
"Password without username!!");
|
|
|
|
// If the user has changed the computer name, use it, otherwise get the
|
|
// current computer name and use that.
|
|
hr = HrGetNewestComputerName(&wszComputerName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
{
|
|
AssertSz(wszComputerName == m_szwCurComputerName, "If I don't have a "
|
|
"new computer name, this better be the original one!");
|
|
dwJoinOption |= NETSETUP_JOIN_DOMAIN;
|
|
}
|
|
|
|
AssertSz(wszComputerName, "We don't have a computer name!");
|
|
AssertSz(dwJoinOption, "No option was set??");
|
|
|
|
AssertSz(FImplies(m_szwPassword,
|
|
m_szwUserName),
|
|
"Password without username!");
|
|
|
|
// Create a machine account if so asked.
|
|
if (m_dwJoinFlags & JDF_CREATE_ACCOUNT)
|
|
{
|
|
dwJoinOption |= NETSETUP_ACCT_CREATE;
|
|
}
|
|
|
|
if (m_dwJoinFlags & JDF_WIN9x_UPGRADE)
|
|
{
|
|
dwJoinOption |= NETSETUP_WIN9X_UPGRADE;
|
|
}
|
|
|
|
if (m_dwJoinFlags & JDF_JOIN_UNSECURE)
|
|
{
|
|
dwJoinOption |= NETSETUP_JOIN_UNSECURE;
|
|
}
|
|
|
|
#if defined(REMOTE_BOOT)
|
|
// TEMP: On a remote boot machine, prevent machine password change
|
|
if (HrIsRemoteBootMachine() == S_OK)
|
|
{
|
|
TraceTag (ttidNetcfgBase,
|
|
"Machine is remote boot, specifying WIN9X_UPGRADE flag to JoinDomain.");
|
|
dwJoinOption |= NETSETUP_WIN9X_UPGRADE;
|
|
}
|
|
#endif // defined(REMOTE_BOOT)
|
|
|
|
//$ REVIEW (danielwe) 2 Apr 1997: If new domain is same as old, unjoin
|
|
// then rejoin??
|
|
|
|
if (!(fIsRename) && FIsJoinedToDomain())
|
|
{
|
|
// Must unjoin from domain if currently joined.
|
|
// If currently joined to a workgroup, this is not necessary.
|
|
// Also we don't unjoin if we are renaming the machine in the domain.
|
|
hr = HrNetUnjoinDomain(m_szwUserName,
|
|
m_szwPassword, 0);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
}
|
|
|
|
if (FInSystemSetup())
|
|
{
|
|
// During system setup, need to pass special flag that tells join code
|
|
// to not do certain operations because SAM is not initialized yet.
|
|
dwJoinOption |= NETSETUP_INSTALL_INVOCATION;
|
|
}
|
|
|
|
// If the supplied username has astring length of zero, then the join
|
|
// API's should be called with NULL's.
|
|
//
|
|
if ((NULL == m_szwUserName) || (0 == wcslen(m_szwUserName)))
|
|
{
|
|
fUseNulls = TRUE;
|
|
}
|
|
|
|
// Go ahead and join the domain
|
|
if( fIsRename) {
|
|
|
|
hr = HrNetRenameInDomain(const_cast<PWSTR>(wszComputerName),
|
|
m_szwNewDWName,
|
|
(fUseNulls ? NULL : m_szwUserName),
|
|
(fUseNulls ? NULL : m_szwPassword),
|
|
dwJoinOption);
|
|
|
|
} else {
|
|
|
|
hr = HrNetJoinDomain(const_cast<PWSTR>(wszComputerName),
|
|
m_szMachineObjectOU,
|
|
m_szwNewDWName,
|
|
(fUseNulls ? NULL : m_szwUserName),
|
|
(fUseNulls ? NULL : m_szwPassword),
|
|
dwJoinOption);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
// Note: (danielwe) Making assumption that failure to join a domain puts us in
|
|
// a workgroup. MacM owns the code responsible for this.
|
|
m_jsCur = NetSetupWorkgroupName;
|
|
goto err;
|
|
}
|
|
|
|
// Make the current domain name the new one since the join on the
|
|
// new domain has succeeded
|
|
hr = HrEstablishNewDomainOrWorkgroupName(NetSetupDomainName);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
err:
|
|
// Free username and password
|
|
DeleteStringAndSetNull(&m_szwPassword);
|
|
DeleteStringAndSetNull(&m_szwUserName);
|
|
|
|
TraceError("CNetCfgIdentification::HrJoinDomain", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::JoinDomain
|
|
//
|
|
// Purpose: Implements COM interface to join this computer to a new
|
|
// domain.
|
|
//
|
|
// Arguments:
|
|
// szwDomain [in] New domain name.
|
|
// szMachineObjectOU [in] Machine object OU (optional)
|
|
// szwUserName [in] User name to use in validation.
|
|
// szwPassword [in] Password to use in validation.
|
|
// dwJoinFlags [in] Currently can be 0 or JDF_CREATE_ACCOUNT.
|
|
//
|
|
// Returns: HRESULT, Error code.
|
|
//
|
|
// Author: danielwe 21 Mar 1997
|
|
//
|
|
// Notes: Validates, but does not actually join the domain. Only holds
|
|
// onto the information until Apply() is called.
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::JoinDomain(PCWSTR szwDomain,
|
|
PCWSTR szMachineObjectOU,
|
|
PCWSTR szwUserName,
|
|
PCWSTR szwPassword,
|
|
DWORD dwJoinFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
static const WCHAR c_wszBackslash[] = L"\\";
|
|
static const WCHAR c_wszAt[] = L"@";
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
Validate_INetCfgIdentification_JoinDomain(szwDomain, szwUserName,
|
|
szwPassword);
|
|
|
|
#if defined(REMOTE_BOOT)
|
|
if (HrIsRemoteBootMachine() == S_FALSE)
|
|
#endif // defined(REMOTE_BOOT)
|
|
{
|
|
// look for non-empty password and empty username or username
|
|
// consisting of only the backslash character
|
|
if (!FIsStrEmpty(szwPassword) && FIsStrEmpty(szwUserName) ||
|
|
!lstrcmpW(szwUserName, c_wszBackslash))
|
|
{
|
|
// Password without username is invalid.
|
|
hr = E_INVALIDARG;
|
|
goto err;
|
|
}
|
|
|
|
PWSTR wszNewUserName;
|
|
INT cchNewUserName;
|
|
|
|
// Check if username that was passed in has a backslash in it or
|
|
// an '@', or if it is empty.
|
|
if (FIsStrEmpty(szwUserName) ||
|
|
wcschr(szwUserName, c_wszBackslash[0]) ||
|
|
wcschr(szwUserName, c_wszAt[0]))
|
|
{
|
|
// if so, don't do anything extra
|
|
wszNewUserName = NULL;
|
|
}
|
|
else
|
|
{
|
|
// if not, we have to append the domain name to the username
|
|
|
|
cchNewUserName = lstrlenW(szwUserName) + // original username
|
|
lstrlenW(szwDomain) + // domain name
|
|
1 + // backslash character
|
|
1; // terminating NULL
|
|
|
|
wszNewUserName = new WCHAR[cchNewUserName];
|
|
|
|
if(wszNewUserName)
|
|
{
|
|
// Turn username into domain\username format
|
|
lstrcpyW(wszNewUserName, szwDomain);
|
|
lstrcatW(wszNewUserName, c_wszBackslash);
|
|
lstrcatW(wszNewUserName, szwUserName);
|
|
|
|
AssertSz(lstrlenW(wszNewUserName) + 1 == cchNewUserName,
|
|
"Possible memory overwrite in username!");
|
|
}
|
|
}
|
|
|
|
// Use wszNewUserName if non-NULL, otherwise use szwUserName
|
|
|
|
PCWSTR szwUserNameToCopy;
|
|
|
|
szwUserNameToCopy = wszNewUserName ? wszNewUserName : szwUserName;
|
|
m_szwUserName = SzDupSz(szwUserNameToCopy);
|
|
m_szwPassword = SzDupSz(szwPassword);
|
|
|
|
delete [] wszNewUserName;
|
|
}
|
|
|
|
AssertSz(FImplies(m_szwPassword,
|
|
m_szwUserName),
|
|
"Password without username!");
|
|
|
|
hr = HrValidateDomainName(szwDomain, m_szwUserName, m_szwPassword);
|
|
if (FAILED(hr))
|
|
goto err;
|
|
|
|
// Assign in new strings
|
|
m_szwNewDWName = SzDupSz(szwDomain);
|
|
if (szMachineObjectOU)
|
|
{
|
|
m_szMachineObjectOU = SzDupSz(szMachineObjectOU);
|
|
}
|
|
|
|
m_dwJoinFlags = dwJoinFlags;
|
|
m_jsNew = NetSetupDomainName;
|
|
err:
|
|
// suppress compiler error
|
|
;
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
TraceError("CNetCfgIdentification::JoinDomain", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CNetCfgIdentification::GetComputerRole
|
|
//
|
|
// Purpose: Returns the current role of the computer.
|
|
//
|
|
// Arguments:
|
|
// pdwRoleFlags [out] Returns value which determines the role of this
|
|
// computer.
|
|
//
|
|
// Returns: S_OK if success, error code otherwise.
|
|
//
|
|
// Author: danielwe 26 Mar 1997
|
|
//
|
|
// Notes: Returned role can be one of:
|
|
// SERVER_STANDALONE - The machine is part of a workgroup.
|
|
// SERVER_MEMBER - The machine is joined to the domain.
|
|
// SERVER_PDC - The machine is a primary domain controller.
|
|
// SERVER_BDC - The machine is a backup domain controller.
|
|
//
|
|
STDMETHODIMP CNetCfgIdentification::GetComputerRole(DWORD* pdwRoleFlags)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
Validate_INetCfgIdentification_GetComputerRole(pdwRoleFlags);
|
|
|
|
COM_PROTECT_TRY
|
|
{
|
|
*pdwRoleFlags = 0;
|
|
|
|
hr = HrEnsureCurrentDomainOrWorkgroupName();
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (m_jsNew == NetSetupUnjoined)
|
|
{
|
|
// The workgroup or domain has not been changed since this
|
|
// object was instantiated
|
|
|
|
if (GetCurrentJoinStatus() == NetSetupDomainName)
|
|
{
|
|
*pdwRoleFlags = GCR_MEMBER;
|
|
}
|
|
else if (GetCurrentJoinStatus() == NetSetupWorkgroupName)
|
|
{
|
|
*pdwRoleFlags = GCR_STANDALONE;
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
AssertSz(FALSE, "Invalid join status flag!");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// This means the workgroup or domain name has been changed
|
|
// since this object was instantiated
|
|
|
|
if (GetNewJoinStatus() == NetSetupDomainName)
|
|
{
|
|
*pdwRoleFlags = GCR_MEMBER;
|
|
}
|
|
else if (GetNewJoinStatus() == NetSetupWorkgroupName)
|
|
{
|
|
*pdwRoleFlags = GCR_STANDALONE;
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
AssertSz(FALSE, "Invalid join status flag!");
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
COM_PROTECT_CATCH;
|
|
|
|
TraceError("CNetCfgIdentification::GetComputerRole", hr);
|
|
return hr;
|
|
}
|
|
|