Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1565 lines
45 KiB

//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1998.
//
// File: op.cxx
//
// Contents: object picker entry point
//
// Classes: CObjectPicker
//
// History: 01-20-2000 davidmun Created
//
//---------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
DEBUG_DECLARE_INSTANCE_COUNTER(CObjectPicker)
#define __THIS_FILE__ L"op"
ULONG
GetMachineNtVer(
PCWSTR pwzMachine);
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::CObjectPicker
//
// Synopsis: ctor
//
// History: 01-20-2000 davidmun Created
//
//---------------------------------------------------------------------------
CObjectPicker::CObjectPicker():
m_cRefs(1),
m_hwndParent(NULL),
m_pExternalCustomizer(NULL),
m_mcTargetComputer(MC_UNKNOWN),
m_fTargetComputerIsLocal(FALSE),
m_mcPreviousTargetComputer(MC_UNKNOWN),
m_fPreviousTargetComputerIsLocal(FALSE),
m_flInitInfoOptions(0),
m_pScopeManager(NULL),
m_pQueryEngine(NULL),
m_pFilterManager(NULL),
m_pAttributeManager(NULL),
m_pAdminCustomizer(NULL),
m_pBaseDlg(NULL)
{
TRACE_CONSTRUCTOR(CObjectPicker);
DEBUG_INCREMENT_INSTANCE_COUNTER(CObjectPicker);
// NTRAID#NTBUG9-548146-2002/02/20-lucios. Pending fix.
InitializeCriticalSection(&m_csOleFreeThreading);
//
// Initialize globals in a thread-safe way. Even though this DLL is
// apartment model only, that only means one thread can access each
// interface instance. It doesn't preclude the creation of multiple
// objects in different threads, each of which will try to init the
// globals.
//
CAutoCritSec Lock(&g_csGlobalVarsCreation);
if (g_pBinder)
{
ASSERT(g_pADsPath); // all globals created at once
g_pBinder->AddRef();
g_pADsPath->AddRef();
}
else
{
g_pBinder = new CBinder;
g_pADsPath = new CADsPathWrapper;
}
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::~CObjectPicker
//
// Synopsis: dtor
//
// History: 01-20-2000 davidmun Created
//
//---------------------------------------------------------------------------
CObjectPicker::~CObjectPicker()
{
TRACE_DESTRUCTOR(CObjectPicker);
DEBUG_DECREMENT_INSTANCE_COUNTER(CObjectPicker);
ASSERT(!m_pExternalCustomizer);
delete m_pScopeManager;
m_pScopeManager = NULL;
delete m_pQueryEngine;
m_pQueryEngine = NULL;
delete m_pFilterManager;
m_pFilterManager = NULL;
delete m_pAttributeManager;
m_pAttributeManager = NULL;
delete m_pAdminCustomizer;
m_pAdminCustomizer = NULL;
delete m_pBaseDlg;
m_pBaseDlg = NULL;
CAutoCritSec Lock(&g_csGlobalVarsCreation);
if (g_pBinder)
{
ASSERT(g_pADsPath); // all globals created at once
if (!g_pBinder->Release())
{
g_pBinder = NULL;
}
if (!g_pADsPath->Release())
{
g_pADsPath = NULL;
}
}
DeleteCriticalSection(&m_csOleFreeThreading);
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::InitCopyFree
//
// Synopsis: Frees structure created by InitCopy
//
// Arguments: dest - pointer to structure to free
//
// Returns: void
//
// History: 05-23-2002 Lucios Created
//
//---------------------------------------------------------------------------
void CObjectPicker::InitCopyFree
(
PDSOP_INIT_INFO *dest
)
{
if(*dest==NULL) return;
for(ULONG t=0;t<(*dest)->cDsScopeInfos;t++)
{
delete [] (*dest)->aDsScopeInfos[t].pwzADsPath;
delete [] (*dest)->aDsScopeInfos[t].pwzDcName;
}
delete [] (*dest)->aDsScopeInfos;
for(ULONG t=0;t<(*dest)->cAttributesToFetch;t++)
{
delete [] (*dest)->apwzAttributeNames[t];
}
delete [] (*dest)->apwzAttributeNames;
delete [] (*dest)->pwzTargetComputer;
delete *dest;
*dest=0;
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::InitCopy
//
// Synopsis: Copy dest into src to catch exceptions due to invalid args
//
// Arguments: dest - returned structure allocated with new that will
// receive a deep copy of src
// src - pointer to the structure to be copied
//
// Returns: S_OK or E_INVALIDARG
//
// History: 05-23-2002 Lucios Created
//
//---------------------------------------------------------------------------
HRESULT CObjectPicker::InitCopy
(
PDSOP_INIT_INFO *dest,
PDSOP_INIT_INFO src
)
{
if(!src) return E_INVALIDARG;
__try
{
*dest=new DSOP_INIT_INFO;
**dest=*src;
// We will grow these as we succed in our alocations
// , so that we only free what we allocate
(*dest)->cDsScopeInfos=0;
(*dest)->cAttributesToFetch=0;
NewDupStr((PWSTR *)&(*dest)->pwzTargetComputer,src->pwzTargetComputer);
(*dest)->apwzAttributeNames=new
PCWSTR[src->cAttributesToFetch];
for(ULONG t=0;t<src->cAttributesToFetch;t++)
{
NewDupStr
(
(PWSTR *)&(*dest)->apwzAttributeNames[t],
src->apwzAttributeNames[t]
);
(*dest)->cAttributesToFetch++;
}
(*dest)->aDsScopeInfos=new
DSOP_SCOPE_INIT_INFO[src->cDsScopeInfos];
for(ULONG t=0;t<src->cDsScopeInfos;t++)
{
(*dest)->aDsScopeInfos[t]=src->aDsScopeInfos[t];
NewDupStr
(
(PWSTR *)&(*dest)->aDsScopeInfos[t].pwzADsPath,
src->aDsScopeInfos[t].pwzADsPath
);
NewDupStr
(
(PWSTR *)&(*dest)->aDsScopeInfos[t].pwzDcName,
src->aDsScopeInfos[t].pwzDcName
);
(*dest)->cDsScopeInfos++;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return E_INVALIDARG;
}
return S_OK;
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::Initialize
//
// Synopsis: Validate and copy the passed-in structure.
//
// Arguments: [pInitInfo] - initialization information
//
// Returns: S_OK, E_INVALIDARG, or E_OUTOFMEMORY
//
// History: 08-29-1998 DavidMun Created
//
//---------------------------------------------------------------------------
STDMETHODIMP
CObjectPicker::Initialize(
PDSOP_INIT_INFO pInitInfoArg)
{
TRACE_METHOD(CObjectPicker, Initialize);
PDSOP_INIT_INFO pInitInfo=NULL;
HRESULT hr = S_OK;
ULONG i;
CAutoCritSec Lock(&m_csOleFreeThreading);
try
{
do
{
hr=InitCopy(&pInitInfo,pInitInfoArg);
BREAK_ON_FAIL_HRESULT(hr);
//
// Create objects that manage various duties; if they already
// exist clear them of data from any previous initialization
// or use.
//
if (!m_pScopeManager)
{
m_pScopeManager = new CScopeManager(*this);
}
else
{
m_pScopeManager->Clear();
}
if (!m_pQueryEngine)
{
m_pQueryEngine = new CQueryEngine(*this);
m_pQueryEngine->Initialize();
}
else
{
m_pQueryEngine->Clear();
}
if (!m_pFilterManager)
{
m_pFilterManager = new CFilterManager(*this);
}
else
{
m_pFilterManager->Clear();
}
// note attribute manager is only cleared if target machine changes
if (!m_pAttributeManager)
{
m_pAttributeManager = new CAttributeManager(*this);
}
if (!m_pAdminCustomizer)
{
m_pAdminCustomizer = new CAdminCustomizer(*this);
}
else
{
m_pAdminCustomizer->Clear();
}
if (!m_pBaseDlg)
{
m_pBaseDlg = new CBaseDlg(*this);
}
else
{
m_pBaseDlg->Clear();
}
m_vstrAttributesToFetch.clear();
_ClearFlag(CDSOP_INIT_SUCCEEDED);
#if (DBG == 1)
_DumpInitInfo(pInitInfo);
#endif // (DBG == 1)
for (i = 0; i < pInitInfo->cAttributesToFetch; i++)
{
PCWSTR pwzAttrName = pInitInfo->apwzAttributeNames[i];
m_vstrAttributesToFetch.push_back(pwzAttrName);
}
m_flInitInfoOptions = pInitInfo->flOptions;
//
// If target machine is not the same as the previous call, or if
// this is the first call, determine the configuration
//
BOOL fLastTargetIsLocalMachine = m_fTargetComputerIsLocal;
m_fTargetComputerIsLocal =
IsLocalComputername(pInitInfo->pwzTargetComputer);
if ((m_mcTargetComputer == MC_UNKNOWN) ||
(m_fTargetComputerIsLocal && !fLastTargetIsLocalMachine) ||
(!m_fTargetComputerIsLocal && fLastTargetIsLocalMachine) ||
(!m_fTargetComputerIsLocal &&
!fLastTargetIsLocalMachine &&
m_strTargetComputer.icompare(pInitInfo->pwzTargetComputer)))
{
if (pInitInfo->pwzTargetComputer && *pInitInfo->pwzTargetComputer)
{
m_strPreviousTargetComputer = m_strTargetComputer;
m_strTargetComputer = pInitInfo->pwzTargetComputer;
m_strTargetComputer.strip(String::LEADING, L'\\');
Dbg(DEB_TRACE,
"Target computer is %s\n",
m_strTargetComputer.c_str());
}
else
{
WCHAR wzLocalComputer[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cchSize = ARRAYLEN(wzLocalComputer);
// NTRAID#NTBUG9-550683-2002/02/20-lucios. Pending fix.
VERIFY(GetComputerName(wzLocalComputer, &cchSize));
m_fPreviousTargetComputerIsLocal = m_fTargetComputerIsLocal;
m_fTargetComputerIsLocal = TRUE;
m_strPreviousTargetComputer = m_strTargetComputer;
m_strTargetComputer = wzLocalComputer;
Dbg(DEB_TRACE,
"Target computer NULL, using '%s'\n",
m_strTargetComputer.c_str());
}
m_pAttributeManager->Clear();
hr = _InitializeMachineConfig();
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
if (m_strTargetComputer.length())
{
PopupMessage(GetForegroundWindow(),
IDS_INIT_FAILED_MACHINE_CONFIG,
m_strTargetComputer.c_str());
}
else
{
PopupMessage(GetForegroundWindow(),
IDS_INIT_FAILED_LOCAL_MACHINE_CONFIG);
}
break;
}
if (m_mcTargetComputer == MC_JOINED_NT5 ||
m_mcTargetComputer == MC_NT5_DC)
{
m_RootDSE.Init(m_strTargetDomainDns.c_str(),
m_strTargetForest.c_str());
}
}
hr = m_pScopeManager->Initialize(pInitInfo);
BREAK_ON_FAIL_HRESULT(hr);
_SetFlag(CDSOP_INIT_SUCCEEDED);
} while (0);
}
catch (const exception &e)
{
hr = E_OUTOFMEMORY;
Dbg(DEB_ERROR, "Caught %s\n", e.what());
}
if (FAILED(hr))
{
DBG_OUT_HRESULT(hr);
}
InitCopyFree(&pInitInfo);
return hr;
}
#if (DBG == 1)
//+--------------------------------------------------------------------------
//
// Function: _DumpInOptForm
//
// Synopsis: Dump to the debugger the scope flags in a form that can be
// copied and pasted into a text file that the unit test can
// read.
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
_DumpInOptForm(
PDSOP_SCOPE_INIT_INFO pCur,
ULONG flScope)
{
if (pCur->flType & flScope)
{
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "%#x\n", flScope);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "%#x\n", pCur->flScope);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, L"%#x\n", pCur->FilterFlags.Uplevel.flBothModes);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, L"%#x\n", pCur->FilterFlags.Uplevel.flMixedModeOnly);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, L"%#x\n", pCur->FilterFlags.Uplevel.flNativeModeOnly);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, L"%#x\n", pCur->FilterFlags.flDownlevel);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "\"%ws\"\n", pCur->pwzDcName);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "\"%ws\"\n", pCur->pwzADsPath);
}
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::_DumpInitInfo
//
// Synopsis: Dump initialization structure caller supplied to the debugger
//
// History: 06-22-2000 DavidMun Created
//
//---------------------------------------------------------------------------
void
CObjectPicker::_DumpInitInfo(
PCDSOP_INIT_INFO pInitInfo)
{
Dbg(DEB_TRACE, "\n");
String strDateTime;
WCHAR wzDateTime[12];
int iRet = GetDateFormat(NULL,
0,
NULL,
L"MM'/'dd'/'yyyy",
wzDateTime,
ARRAYLEN(wzDateTime));
if (iRet)
{
strDateTime = wzDateTime;
}
iRet = GetTimeFormat(NULL,
0,
NULL,
L"HH':'mm':'ss",
wzDateTime,
ARRAYLEN(wzDateTime));
if (iRet)
{
if (!strDateTime.empty())
{
strDateTime += L" ";
}
strDateTime += wzDateTime;
}
Dbg(DEB_TRACE, " %ws\n", strDateTime.c_str());
WCHAR wzLocalComputerNB[LM20_CNLEN + 1] = L"";
ULONG cchLocalComputerNB = ARRAYLEN(wzLocalComputerNB);
//REVIEWED-2002-02-21-lucios.
BOOL fOk = GetComputerName(wzLocalComputerNB, &cchLocalComputerNB);
if (fOk)
{
Dbg(DEB_TRACE, " Local Computer '%ws'\n", wzLocalComputerNB);
}
else
{
DBG_OUT_LASTERROR;
}
OSVERSIONINFOEX VerInfo;
//REVIEWED-2002-02-21-lucios.
ZeroMemory(&VerInfo, sizeof VerInfo);
VerInfo.dwOSVersionInfoSize = sizeof VerInfo;
fOk = GetVersionEx(reinterpret_cast<OSVERSIONINFO *>(&VerInfo));
if (fOk)
{
PCWSTR pwzProductType;
switch (VerInfo.wProductType)
{
case VER_NT_WORKSTATION:
pwzProductType = L"Workstation";
break;
case VER_NT_DOMAIN_CONTROLLER:
pwzProductType = L"Domain Controller";
break;
case VER_NT_SERVER:
pwzProductType = L"Server";
break;
default:
pwzProductType = L"(unknown product type)";
break;
}
if (VerInfo.szCSDVersion && *VerInfo.szCSDVersion)
{
Dbg(DEB_TRACE,
" Windows %ws %u.%u build %u %ws SP version %u.%u\n",
pwzProductType,
VerInfo.dwMajorVersion,
VerInfo.dwMinorVersion,
VerInfo.dwBuildNumber,
VerInfo.szCSDVersion,
VerInfo.wServicePackMajor,
VerInfo.wServicePackMinor);
}
else
{
Dbg(DEB_TRACE, " Windows %ws version %u.%u build %u\n",
pwzProductType,
VerInfo.dwMajorVersion,
VerInfo.dwMinorVersion,
VerInfo.dwBuildNumber);
}
}
else
{
DBG_OUT_LASTERROR;
}
WCHAR wzUserName[LM20_DNLEN + 1 + LM20_UNLEN + 1] = L""; // +1 for \ +1 for NUL
ULONG cchUserName = ARRAYLEN(wzUserName);
//REVIEWED-2002-02-21-lucios.
fOk = GetUserNameEx(NameSamCompatible, wzUserName, &cchUserName);
if (fOk)
{
Dbg(DEB_TRACE, " Logged on as '%ws'\n", wzUserName);
}
else
{
DBG_OUT_LASTERROR;
}
Dbg(DEB_TRACE,
" Target Computer '%ws'\n",
CHECK_NULL(pInitInfo->pwzTargetComputer));
DumpOptionFlags(pInitInfo->flOptions);
ULONG i;
for (i = 0; i < pInitInfo->cDsScopeInfos; i++)
{
PDSOP_SCOPE_INIT_INFO pCur = &pInitInfo->aDsScopeInfos[i];
Dbg(DEB_TRACE, "\n");
DumpScopeType(pCur->flType);
DumpScopeFlags(pCur->flScope);
DumpFilterFlags(pCur->FilterFlags);
if (pCur->pwzDcName)
{
Dbg(DEB_TRACE, " DC Name '%ws'\n", pCur->pwzDcName);
}
if (pCur->pwzADsPath)
{
Dbg(DEB_TRACE, " ADsPath '%ws'\n", pCur->pwzADsPath);
}
}
// dump in format opt.exe can read
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "\"%ws\"\n", pInitInfo->pwzTargetComputer);
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "%#x\n", pInitInfo->flOptions);
String strAttr(L"\"");
for (i = 0; i < pInitInfo->cAttributesToFetch; i++)
{
strAttr += pInitInfo->apwzAttributeNames[i];
if (i < pInitInfo->cAttributesToFetch - 1)
{
strAttr += L"; ";
}
}
strAttr += L"\"";
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "%ws\n", strAttr.c_str());
ULONG cIndividualScopes = 0;
for (i = 0; i < pInitInfo->cDsScopeInfos; i++)
{
PDSOP_SCOPE_INIT_INFO pCur = &pInitInfo->aDsScopeInfos[i];
if (pCur->flType & ST_TARGET_COMPUTER)
{
cIndividualScopes++;
}
if (pCur->flType & ST_UPLEVEL_JOINED_DOMAIN)
{
cIndividualScopes++;
}
if (pCur->flType & ST_DOWNLEVEL_JOINED_DOMAIN)
{
cIndividualScopes++;
}
if (pCur->flType & ST_ENTERPRISE_DOMAIN)
{
cIndividualScopes++;
}
if (pCur->flType & ST_GLOBAL_CATALOG)
{
cIndividualScopes++;
}
if (pCur->flType & ST_EXTERNAL_UPLEVEL_DOMAIN)
{
cIndividualScopes++;
}
if (pCur->flType & ST_EXTERNAL_DOWNLEVEL_DOMAIN)
{
cIndividualScopes++;
}
if (pCur->flType & ST_WORKGROUP)
{
cIndividualScopes++;
}
if (pCur->flType & ST_USER_ENTERED_UPLEVEL_SCOPE)
{
cIndividualScopes++;
}
if (pCur->flType & ST_USER_ENTERED_DOWNLEVEL_SCOPE)
{
cIndividualScopes++;
}
}
Dbg(DEB_TRACE | DEB_NOCOMPNAME, "%u\n", cIndividualScopes);
for (i = 0; i < pInitInfo->cDsScopeInfos; i++)
{
PDSOP_SCOPE_INIT_INFO pCur = &pInitInfo->aDsScopeInfos[i];
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_TARGET_COMPUTER );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_UPLEVEL_JOINED_DOMAIN );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_DOWNLEVEL_JOINED_DOMAIN );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_ENTERPRISE_DOMAIN );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_GLOBAL_CATALOG );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_EXTERNAL_UPLEVEL_DOMAIN );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_EXTERNAL_DOWNLEVEL_DOMAIN );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_WORKGROUP );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_USER_ENTERED_UPLEVEL_SCOPE );
_DumpInOptForm(pCur, DSOP_SCOPE_TYPE_USER_ENTERED_DOWNLEVEL_SCOPE);
}
}
#endif // (DBG == 1)
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::_InitializeMachineConfig
//
// Synopsis: Determine the configuration of the target computer.
//
// History: 06-22-2000 DavidMun Created
//
// Notes: Configuration in this sense means whether the target
// computer is joined to an NT4 domain, an NT5 domain, in a
// workgroup, etc.
//
//---------------------------------------------------------------------------
HRESULT
CObjectPicker::_InitializeMachineConfig()
{
TRACE_METHOD(CObjectPicker, _InitializeMachineConfig);
HRESULT hr = S_OK;
ULONG ulResult;
PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pDsRole = NULL;
PDOMAIN_CONTROLLER_INFO pdci = NULL;
RpIADs rpADs;
do
{
m_mcPreviousTargetComputer = m_mcTargetComputer;
m_mcTargetComputer = MC_UNKNOWN;
PCWSTR pwzMachine;
if (m_fTargetComputerIsLocal)
{
pwzMachine = NULL;
}
else
{
pwzMachine = m_strTargetComputer.c_str();
ASSERT(*pwzMachine);
}
{
TIMER("DsRoleGetPrimaryDomainInformation(%ws)",
CHECK_NULL(pwzMachine));
ulResult = DsRoleGetPrimaryDomainInformation(pwzMachine,
DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pDsRole);
}
if (pwzMachine && ulResult == ERROR_ACCESS_DENIED)
{
Dbg(DEB_TRACE,
"DsRoleGetPrimaryDomainInformation returned ERROR_ACCESS_DENIED, establishing connection\n");
//
// Establish a connection with remote machine using WinNT provider,
// and try again.
//
WCHAR wzComputerAdsPath[MAX_PATH];
// NTRAID#NTBUG9-548039-2002/02/20-lucios. Pending fix.
wsprintf(wzComputerAdsPath, L"WinNT://%ws,Computer", pwzMachine);
hr = g_pBinder->BindToObject(GetForegroundWindow(),
wzComputerAdsPath,
IID_IADs,
(void **) &rpADs);
BREAK_ON_FAIL_HRESULT(hr);
TIMER("DsRoleGetPrimaryDomainInformation2");
ulResult =
DsRoleGetPrimaryDomainInformation(pwzMachine,
DsRolePrimaryDomainInfoBasic,
(PBYTE *)&pDsRole);
}
if (ulResult != NO_ERROR)
{
DBG_OUT_LRESULT(ulResult);
hr = HRESULT_FROM_WIN32(ulResult);
break;
}
else if(NULL == pDsRole)
{
DBG_OUT_LRESULT(ERROR_UNEXP_NET_ERR);
Dbg(DEB_TRACE,"Network issue found in WinSE Raid 21714, Whistler Raid 476297");
hr = HRESULT_FROM_WIN32(ERROR_UNEXP_NET_ERR);
break;
}
ASSERT(pDsRole);
Dbg(DEB_TRACE, "DsRoleGetPrimaryDomainInformation returned:\n");
Dbg(DEB_TRACE, " DomainNameFlat: %ws\n", CHECK_NULL(pDsRole->DomainNameFlat));
Dbg(DEB_TRACE, " DomainNameDns: %ws\n", CHECK_NULL(pDsRole->DomainNameDns));
Dbg(DEB_TRACE, " DomainForestName: %ws\n", CHECK_NULL(pDsRole->DomainForestName));
//
// If machine is in a workgroup, we're done.
//
if (pDsRole->MachineRole == DsRole_RoleStandaloneWorkstation ||
pDsRole->MachineRole == DsRole_RoleStandaloneServer)
{
Dbg(DEB_TRACE, "Target machine is not joined to a domain\n");
m_mcTargetComputer = MC_IN_WORKGROUP;
break;
}
if (pDsRole->DomainNameFlat)
{
m_strTargetDomainFlat = pDsRole->DomainNameFlat;
}
//
// Target machine is joined to a domain. Find out if it's joined
// to an NT4 or an NT5 domain by getting the name of a DC, and
// requesting that we get one which supports DS.
//
PWSTR pwzDomainNameForDsGetDc;
ULONG flDsGetDc = DS_DIRECTORY_SERVICE_PREFERRED;
if (pDsRole->DomainNameDns)
{
pwzDomainNameForDsGetDc = pDsRole->DomainNameDns;
flDsGetDc |= DS_IS_DNS_NAME;
Dbg(DEB_TRACE,
"DsGetDcName(Domain=%ws, flags=DS_IS_DNS_NAME | DS_DIRECTORY_SERVICE_PREFERRED)\n",
CHECK_NULL(pwzDomainNameForDsGetDc));
}
else
{
pwzDomainNameForDsGetDc = pDsRole->DomainNameFlat;
flDsGetDc |= DS_IS_FLAT_NAME;
Dbg(DEB_TRACE,
"DsGetDcName(Domain=%ws, flags=DS_IS_FLAT_NAME | DS_DIRECTORY_SERVICE_PREFERRED)\n",
CHECK_NULL(pwzDomainNameForDsGetDc));
}
ulResult = DsGetDcName(NULL, // per CliffV this should ALWAYS be NULL
pwzDomainNameForDsGetDc,
NULL,
NULL,
flDsGetDc,
&pdci);
if (ulResult != NO_ERROR)
{
m_mcTargetComputer = MC_NO_NETWORK;
Dbg(DEB_ERROR,
"DsGetDcName for domain %ws returned %#x, treating target machine as no-net\n",
pwzDomainNameForDsGetDc,
ulResult);
break;
}
if (pdci->Flags & DS_DS_FLAG)
{
Dbg(DEB_TRACE,
"DsGetDcName returned DS DC for domain %ws, asking for DNS name\n",
pwzDomainNameForDsGetDc);
PDOMAIN_CONTROLLER_INFO pdci2 = NULL;
ulResult = DsGetDcName(NULL,
pwzDomainNameForDsGetDc,
NULL,
NULL,
flDsGetDc | DS_RETURN_DNS_NAME,
&pdci2);
if (ulResult == NO_ERROR)
{
NetApiBufferFree(pdci);
pdci = pdci2;
}
else
{
ASSERT(!pdci2);
}
}
//
// If TCP/IP is not installed on local machine then DsGetDcName for
// DNS name will fail. Also, no LDAP or GC scopes may be used.
// Pretend we're joined to an NT4 domain so WinNT provider will be
// used for domain scopes.
//
if (ulResult == ERROR_NO_SUCH_DOMAIN)
{
Dbg(DEB_TRACE,
"Attempting to get DNS name for DS DC %ws failed, treating target machine as joined to NT4 domain\n",
pwzDomainNameForDsGetDc);
m_mcTargetComputer = MC_JOINED_NT4;
break;
}
if (ulResult != NO_ERROR)
{
Dbg(DEB_ERROR,
"DsGetDcName for domain %ws (call for DNS name) returned %uL\n",
pwzDomainNameForDsGetDc,
ulResult);
hr = HRESULT_FROM_WIN32(ulResult);
break;
}
//
// If the target machine is an NT4 BDC in an NT5 mixed-mode domain,
// treat it as an NT4 DC.
//
if (pDsRole->MachineRole == DsRole_RoleBackupDomainController
&& GetMachineNtVer(pwzMachine) < 5)
{
Dbg(DEB_TRACE,
"Target machine is an NT4 DC in NT5 mixed mode domain %ws\n",
m_strTargetDomainDns.empty()
? m_strTargetDomainFlat.c_str()
: m_strTargetDomainDns.c_str());
m_mcTargetComputer = MC_NT4_DC;
ASSERT(pwzMachine); // we can't be running on NT4
m_strTargetDomainDc = pwzMachine;
break;
}
m_strTargetDomainDc = pdci->DomainControllerName;
if (pDsRole->DomainNameDns)
{
m_strTargetDomainDns = pDsRole->DomainNameDns;
}
else if (pdci->DomainName)
{
m_strTargetDomainDns = pdci->DomainName;
}
m_strTargetDomainDns.strip(String::TRAILING, L'.');
if (pdci->Flags & DS_DS_FLAG)
{
m_strTargetForest = pdci->DnsForestName;
m_strTargetForest.strip(String::TRAILING, L'.');
if (pDsRole->MachineRole == DsRole_RolePrimaryDomainController ||
pDsRole->MachineRole == DsRole_RoleBackupDomainController)
{
Dbg(DEB_TRACE,
"Target machine is an NT5 DC for NT5 domain %ws in forest %ws\n",
m_strTargetDomainDns.empty()
? m_strTargetDomainFlat.c_str()
: m_strTargetDomainDns.c_str(),
m_strTargetForest.c_str());
m_mcTargetComputer = MC_NT5_DC;
}
else
{
Dbg(DEB_TRACE,
"Target machine is joined to NT5 domain %ws (DC is %ws) in forest %ws\n",
m_strTargetDomainDns.empty()
? m_strTargetDomainFlat.c_str()
: m_strTargetDomainDns.c_str(),
m_strTargetDomainDc.c_str(),
m_strTargetForest.c_str());
m_mcTargetComputer = MC_JOINED_NT5;
}
}
else
{
if (pDsRole->MachineRole == DsRole_RolePrimaryDomainController ||
pDsRole->MachineRole == DsRole_RoleBackupDomainController)
{
Dbg(DEB_TRACE,
"Target machine is an NT4 DC for domain %ws\n",
m_strTargetDomainFlat.c_str());
m_mcTargetComputer = MC_NT4_DC;
}
else
{
Dbg(DEB_TRACE,
"Target machine is joined to NT4 domain %ws\n",
m_strTargetDomainFlat.c_str());
m_mcTargetComputer = MC_JOINED_NT4;
}
}
} while (0);
if (pdci)
{
NetApiBufferFree(pdci);
}
if (pDsRole)
{
DsRoleFreeMemory(pDsRole);
}
return hr;
}
#define NT_VERSION_KEY L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
#define NT_VERSION_VALUE L"CurrentVersion"
//+--------------------------------------------------------------------------
//
// Function: GetMachineNtVer
//
// Synopsis: Return the major NT version number on machine [pwzMachine]
// as an unsigned integer, or 0 on error.
//
// Arguments: [pwzMachine] - machine from which to read version; NULL
// for local machine
//
// History: 09-01-1999 davidmun Created
//
//---------------------------------------------------------------------------
ULONG
GetMachineNtVer(
PCWSTR pwzMachine)
{
TRACE_FUNCTION(GetMachineNtVer);
ULONG ulVer = 0;
HRESULT hr = S_OK;
CSafeReg reg;
WCHAR wzBuf[20] = L"";
NET_API_STATUS Status = NERR_Success;
WKSTA_INFO_100 *pinfo100 = NULL;
do
{
//
// Try to get the nt version using NetWkstaGetInfo first
//
String strServer;
if (pwzMachine)
{
ASSERT(*pwzMachine);
strServer = String(L"\\\\") + pwzMachine;
Status = NetWkstaGetInfo(const_cast<PWSTR>(strServer.c_str()),
100,
reinterpret_cast<LPBYTE *>(&pinfo100));
}
else
{
Status = NetWkstaGetInfo(NULL,
100,
reinterpret_cast<LPBYTE *>(&pinfo100));
}
if (Status == NERR_Success)
{
ulVer = pinfo100->wki100_ver_major;
Dbg(DEB_TRACE,
"NetWkstaGetInfo returns %u.%u\n",
pinfo100->wki100_ver_major,
pinfo100->wki100_ver_minor);
break;
}
Dbg(DEB_ERROR, "NetWkstaGetInfo error %u\n", Status);
//
// NetWkstaGetInfo failed. Try to get the version number from
// the registry.
//
if (pwzMachine)
{
CSafeReg regRemote;
hr = regRemote.Connect(pwzMachine, HKEY_LOCAL_MACHINE);
BREAK_ON_FAIL_HRESULT(hr);
hr = reg.Open(regRemote,
NT_VERSION_KEY,
STANDARD_RIGHTS_READ | KEY_QUERY_VALUE);
BREAK_ON_FAIL_HRESULT(hr);
}
else
{
hr = reg.Open(HKEY_LOCAL_MACHINE,
NT_VERSION_KEY,
STANDARD_RIGHTS_READ | KEY_QUERY_VALUE);
BREAK_ON_FAIL_HRESULT(hr);
}
hr = reg.QueryStr(NT_VERSION_VALUE, wzBuf, ARRAYLEN(wzBuf));
BREAK_ON_FAIL_HRESULT(hr);
ulVer = wcstoul(wzBuf, NULL, 10);
} while (0);
if (pinfo100)
{
NetApiBufferFree(pinfo100);
}
Dbg(DEB_TRACE,
"%ws NT version is %ws (%u)\n",
pwzMachine ? pwzMachine : L"Local machine",
wzBuf,
ulVer);
return ulVer;
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::InvokeDialog
//
// Synopsis: Once Initialize has been called successfully, this method
// may be called to invoke the modal object picker dialog.
//
// Arguments: [hwndParent] - parent window
// [ppdoSelections] - filled with selected objects
//
// Returns: HRESULT
//
// History: 01-20-2000 davidmun Created
//
//---------------------------------------------------------------------------
STDMETHODIMP
CObjectPicker::InvokeDialog(
HWND hwndParent,
IDataObject **ppdoSelections)
{
return InvokeDialogEx(hwndParent, NULL, ppdoSelections);
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::InvokeDialogEx
//
// Synopsis: Invoke the modal object picker dialog.
//
// Arguments: [hwndParent] - parent window of dialog
// [pCustomizer] - callback methods
// [ppdoSelections] - filled with data object containing user's
// selections on success
//
// Returns: S_FALSE - user cancelled dialog, *ppdoSelections == NULL
// E_* - error occurred, *ppdoSelections == NULL
// S_OK - *ppdoSelections is valid
//
// Modifies: *[ppdoSelections]
//
// History: 10-07-1998 DavidMun Created
// 01-20-2000 davidmun rewritten
//
//---------------------------------------------------------------------------
STDMETHODIMP
CObjectPicker::InvokeDialogEx(
HWND hwndParent,
ICustomizeDsBrowser *pCustomizer,
IDataObject **ppdoSelections)
{
TRACE_METHOD(CObjectPicker, InvokeDialogEx);
HRESULT hr = S_OK;
CAutoCritSec Lock(&m_csOleFreeThreading);
try
{
*ppdoSelections = NULL;
do
{
if (!_IsFlagSet(CDSOP_INIT_SUCCEEDED))
{
PopupMessage(hwndParent, IDS_CANNOT_INVOKE);
hr = E_UNEXPECTED;
DBG_OUT_HRESULT(hr);
break;
}
m_hwndParent = hwndParent;
m_pExternalCustomizer = pCustomizer;
//
// If init succeeded we should know what the machine config is
//
ASSERT(m_mcTargetComputer != MC_UNKNOWN);
//
// Put up the dialog
//
LinkWindow_RegisterClass();
hr = m_pBaseDlg->DoModal(ppdoSelections);
LinkWindow_UnregisterClass(g_hinst);
BREAK_ON_FAIL_HRESULT(hr);
} while (0);
m_hwndParent = NULL;
m_pExternalCustomizer = NULL;
}
STANDARD_CATCH_BLOCK;
return hr;
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::ProcessNames
//
// Synopsis: Process the user-entered text and any objects in the
// rich edit control.
//
// Arguments: [hwndRichEdit] - edit control containing text and
// objects to process
// [pEdsoGdiProvider] - points to instance of object which
// will provide GDI objects needed
// to draw in the richedit.
// [fForceSingleSelect] - if TRUE then the contents of the
// rich edit are treated as a single
// name, even if the
// DSOP_FLAG_MULTISELECT flag was set
// by the caller.
//
// Returns: TRUE if all text and every object processed successfully
//
// History: 06-22-2000 DavidMun Created
//
// Notes: When user-entered text is processed it is removed and
// replaced with zero or more CEmbeddedDsObjects. Each of these
// objects is processed by requesting it to perform the
// caller-specified name translation and attribute fetches, if
// any.
//
//---------------------------------------------------------------------------
BOOL
CObjectPicker::ProcessNames(
HWND hwndRichEdit,
const CEdsoGdiProvider *pEdsoGdiProvider,
BOOL fForceSingleSelect) const
{
TRACE_METHOD(CObjectPicker, ProcessNames);
enum PARSE_STATE
{
EAT_LEADING,
EAT_TRAILING,
EAT_DELIM
};
CWaitCursor Hourglass;
PARSE_STATE ParseState = EAT_LEADING;
NAME_PROCESS_RESULT npr = NPR_SUCCESS;
ULONG idxNextObjectToProcess = 0;
IRichEditOle *pRichEditOle = NULL;
LRESULT lResult = SendMessage(hwndRichEdit,
EM_GETOLEINTERFACE,
0,
(LPARAM) &pRichEditOle);
if (!lResult)
{
DBG_OUT_LASTERROR;
PopupMessage(hwndRichEdit,
IDS_CANNOT_READ_RICHEDIT,
lResult);
return FALSE;
}
CRichEditHelper re(*this,
hwndRichEdit,
pEdsoGdiProvider,
pRichEditOle,
fForceSingleSelect);
CRichEditHelper::iterator itCur = re.begin();
while (!NAME_PROCESSING_FAILED(npr) && itCur != re.end())
{
switch (ParseState)
{
case EAT_LEADING:
re.Consume(itCur, L" \r\t;");
if (itCur == re.end())
{
break;
}
// if itCur is an object, advance past and eat trailing
if (re.IsObject(itCur))
{
npr = re.ProcessObject(itCur, idxNextObjectToProcess);
if (!NAME_PROCESSING_FAILED(npr))
{
itCur++;
idxNextObjectToProcess++;
ParseState = EAT_TRAILING;
}
break;
}
//
// itCur is at start of some text. convert it to object(s) or
// delete it.
//
npr = re.MakeObject(itCur);
break;
case EAT_TRAILING:
re.Consume(itCur, L" \t");
// exit switch if nothing to the right of itCur
if (itCur == re.end())
{
break;
}
if (re.ReadChar(itCur) == L'\r')
{
re.ReplaceChar(itCur, L';');
}
if (re.ReadChar(itCur) == L';')
{
itCur++;
ParseState = EAT_DELIM;
break;
}
//
// itCur is at text or object. since we're eating trailing spaces
// that means there's an object to the left of itCur. insert
// a delimiter, move past it, and switch to eating leading spaces.
//
re.Insert(itCur, L"; ");
itCur += 2;
ParseState = EAT_LEADING;
break;
case EAT_DELIM:
re.Consume(itCur, L";\r");
if (itCur == re.end())
{
break;
}
if (iswspace(re.ReadChar(itCur)))
{
itCur++;
ParseState = EAT_LEADING;
break;
}
//
// itCur is at non-whitespace text or object which is folloinwg
// directly after a semicolon. add a space and move past it, then
// switch to eating leading.
//
re.Insert(itCur, L" ");
itCur++;
ParseState = EAT_LEADING;
break;
}
}
SAFE_RELEASE(pRichEditOle);
if (NAME_PROCESSING_FAILED(npr))
{
return FALSE;
}
re.TrimTrailing(L"; \t");
return re.begin() != re.end();
}
//+---------------------------------------------------------------------------
//
// Member: CObjectPicker::AddRef
//
// Synopsis: Standard OLE
//
// History: 12-04-96 DavidMun Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CObjectPicker::AddRef()
{
ULONG ul = InterlockedIncrement((LONG *) &m_cRefs);
//Dbg(DEB_TRACE, "AddRef new refcount is %d\n", ul);
return ul;
}
//+---------------------------------------------------------------------------
//
// Member: CObjectPicker::Release
//
// Synopsis: Standard OLE
//
// History: 12-04-96 DavidMun Created
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CObjectPicker::Release()
{
ULONG cRefsTemp = InterlockedDecrement((LONG *)&m_cRefs);
//Dbg(DEB_TRACE, "Release new refcount is %d\n", cRefsTemp);
if (0 == cRefsTemp)
{
delete this;
}
return cRefsTemp;
}
//+--------------------------------------------------------------------------
//
// Member: CObjectPicker::QueryInterface
//
// Synopsis: Standard OLE
//
// History: 12-05-1996 DavidMun Created
//
//---------------------------------------------------------------------------
STDMETHODIMP
CObjectPicker::QueryInterface(
REFIID riid,
LPVOID *ppvObj)
{
HRESULT hr = S_OK;
do
{
if (NULL == ppvObj)
{
hr = E_INVALIDARG;
DBG_OUT_HRESULT(hr);
break;
}
if (IsEqualIID(riid, IID_IUnknown))
{
*ppvObj = (IUnknown *)this;
}
else if (IsEqualIID(riid, IID_IDsObjectPicker))
{
*ppvObj = (IUnknown *)this;
}
else if (IsEqualIID(riid, IID_IDsObjectPickerEx))
{
*ppvObj = (IUnknown *)this;
}
else
{
DBG_OUT_NO_INTERFACE("CObjectPicker", riid);
hr = E_NOINTERFACE;
*ppvObj = NULL;
break;
}
//
// If we got this far we are handing out a new interface pointer on
// this object, so addref it.
//
AddRef();
} while (0);
return hr;
}