windows-nt/Source/XPSP1/NT/net/mmc/dialinusr/dialin.cpp
2020-09-26 16:20:57 +08:00

400 lines
11 KiB
C++

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corporation, 1997 - 1999 **/
/**********************************************************************/
/*
dialin.cpp
Implementationof CRasDialin class, this class implements COM
interfaces IUnknown, IShellExtInit, IShellPropSheetExt to extend
User object's property sheet.
FILE HISTORY:
*/
#include "stdafx.h"
#include "Dialin.h"
#include "DlgDial.h"
#include <dsrole.h>
#include <lmserver.h>
#include <localsec.h>
#include <dsgetdc.h>
#include <mmc.h>
#include <sdowrap.h>
#include "sharesdo.h"
#ifdef __cplusplus
extern "C"{
#endif
#ifndef __IID_DEFINED__
#define __IID_DEFINED__
typedef struct _IID
{
unsigned long x;
unsigned short s1;
unsigned short s2;
unsigned char c[8];
} IID;
#endif // __IID_DEFINED__
#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID;
#endif // CLSID_DEFINED
const IID IID_IRasDialin = {0xB52C1E4F,0x1DD2,0x11D1,{0xBC,0x43,0x00,0xC0,0x4F,0xC3,0x1F,0xD3}};
const IID LIBID_RASDIALLib = {0xB52C1E42,0x1DD2,0x11D1,{0xBC,0x43,0x00,0xC0,0x4F,0xC3,0x1F,0xD3}};
const CLSID CLSID_RasDialin = {0xB52C1E50,0x1DD2,0x11D1,{0xBC,0x43,0x00,0xC0,0x4F,0xC3,0x1F,0xD3}};
#ifdef __cplusplus
}
#endif
static ULONG_PTR g_cfMachineName = 0;
static ULONG_PTR g_cfDisplayName = 0;
LONG g_lComponentDataSessions = 0;
/////////////////////////////////////////////////////////////////////////////
// CRasDialin
CRasDialin::CRasDialin()
{
m_pPage = NULL;
m_pMergedPage = NULL;
m_pwszObjName = NULL;
m_pwszClass = NULL;
ZeroMemory(&m_ObjMedium, sizeof(m_ObjMedium));
m_ObjMedium.tymed =TYMED_HGLOBAL;
m_ObjMedium.hGlobal = NULL;
m_bShowPage = TRUE;
}
CRasDialin::~CRasDialin()
{
// stgmedia
// delete m_pPage;
ReleaseStgMedium(&m_ObjMedium);
}
//===============================================================================
// IShellExtInit::Initialize
//
// information of the user object is passed in via parameter pDataObject
// further processing will be based on the DN of the user object
STDMETHODIMP CRasDialin::Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey)
{
TRACE(_T("CRasDialin::Initialize()\r\n"));
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT (pDataObj != NULL);
// get the object name out of the pDataObj
HRESULT hr = S_OK;
TracePrintf(g_dwTraceHandle, _T("RegisterClipboardFormat %s"),CFSTR_DSOBJECTNAMES);
ULONG_PTR cfDsObjectNames = RegisterClipboardFormat(CFSTR_DSOBJECTNAMES);
TracePrintf(g_dwTraceHandle, _T(" %x"),cfDsObjectNames);
FORMATETC fmte = {cfDsObjectNames, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
LPDSOBJECTNAMES pDsObjectNames;
// Get the path to the DS object from the data object.
// Note: This call runs on the caller's main thread. The pages' window
// procs run on a different thread, so don't reference the data object
// from a winproc unless it is first marshalled on this thread.
TracePrintf(g_dwTraceHandle, _T("pDataObj->GetData returns"));
CHECK_HR(hr = pDataObj->GetData(&fmte, &m_ObjMedium));
TracePrintf(g_dwTraceHandle, _T(" %x"), hr);
pDsObjectNames = (LPDSOBJECTNAMES)m_ObjMedium.hGlobal;
if (pDsObjectNames->cItems < 1)
{
ASSERT (0);
return E_FAIL;
}
m_bShowPage = TRUE;
if(m_bShowPage)
{
// get the name of the object
m_pwszObjName = (LPWSTR)ByteOffset(pDsObjectNames, pDsObjectNames->aObjects[0].offsetName);
// get the class name of the object
m_pwszClass = (LPWSTR)ByteOffset(pDsObjectNames, pDsObjectNames->aObjects[0].offsetClass);
TracePrintf(g_dwTraceHandle, _T("UserPath %s"),m_pwszObjName);
try{
ASSERT(!m_pMergedPage);
CString machineName;
m_pMergedPage = new CDlgRASDialinMerge(RASUSER_ENV_DS, NULL, m_pwszObjName);
TracePrintf(g_dwTraceHandle, _T("new Dialin page object %x"),m_pMergedPage);
ASSERT(m_pMergedPage);
#ifdef SINGLE_SDO_CONNECTION // for share the same sdo connection for multiple users
TracePrintf(g_dwTraceHandle, _T("HrGetDCName returns "));
CHECK_HR(hr = m_pMergedPage->HrGetDCName(machineName));
TracePrintf(g_dwTraceHandle, _T("%x"),hr);
TracePrintf(g_dwTraceHandle, _T("HrGetSharedSdoServer returns "));
// ignore return value:
// reason: marshalling could fail in case this call was made from different thread,
// before the pointer is used, it will be checked again
GetSharedSdoServer((LPCTSTR)machineName, NULL, NULL, NULL, m_pMergedPage->GetMarshalSdoServerHolder());
TracePrintf(g_dwTraceHandle, _T("%x"),hr);
#endif
}
catch(CMemoryException&)
{
CHECK_HR( hr = E_OUTOFMEMORY );
}
}
L_ERR:
TracePrintf(g_dwTraceHandle, _T("%x"),hr);
return hr;
}
//
// FUNCTION: IShellPropSheetExt::AddPages(LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell just before the property sheet is displayed.
//
// PARAMETERS:
// lpfnAddPage - Pointer to the Shell's AddPage function
// lParam - Passed as second parameter to lpfnAddPage
//
// RETURN VALUE:
//
// NOERROR in all cases. If for some reason our pages don't get added,
// the Shell still needs to bring up the Properties... sheet.
//
// COMMENTS:
//
STDMETHODIMP CRasDialin::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam)
{
TRACE(_T("CRasDialin::AddPages()\r\n"));
if(!m_bShowPage) return S_OK;
HRESULT hr = S_OK;
// param validation
ASSERT (lpfnAddPage);
if (lpfnAddPage == NULL)
return E_UNEXPECTED;
// make sure our state is fixed up (cause we don't know what context we were called in)
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT(m_pMergedPage);
// tell MMC to hook the proc because we are running on a separate,
// non MFC thread.
m_pMergedPage->m_psp.pfnCallback = &CDlgRASDialinMerge::PropSheetPageProc;
// We also need to save a self-reference so that the static callback
// function can recover a "this" pointer
m_pMergedPage->m_psp.lParam = (LONG_PTR)m_pMergedPage;
MMCPropPageCallback(&m_pMergedPage->m_psp);
HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&m_pMergedPage->m_psp);
ASSERT (hPage);
if (hPage == NULL)
return E_UNEXPECTED;
// add the page
lpfnAddPage (hPage, lParam);
m_pPage = NULL; // since it's just consumed by the dialog, cannot added again
return S_OK;
}
//
// FUNCTION: IShellPropSheetExt::ReplacePage(UINT, LPFNADDPROPSHEETPAGE, LPARAM)
//
// PURPOSE: Called by the shell only for Control Panel property sheet
// extensions
//
// PARAMETERS:
// uPageID - ID of page to be replaced
// lpfnReplaceWith - Pointer to the Shell's Replace function
// lParam - Passed as second parameter to lpfnReplaceWith
//
// RETURN VALUE:
//
// E_FAIL, since we don't support this function. It should never be
// called.
// COMMENTS:
//
STDMETHODIMP CRasDialin::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam)
{
TRACE(_T("CRasDialin::ReplacePage()\r\n"));
return E_FAIL;
}
/*---------------------------------------------------------------------------
IExtendPropertySheet Implementation
---------------------------------------------------------------------------*/
/*!--------------------------------------------------------------------------
IExtendPropertySheet::QueryPagesFor
MMC calls this to see if a node has property pages
Author:
---------------------------------------------------------------------------*/
STDMETHODIMP
CRasDialin::QueryPagesFor
(
LPDATAOBJECT pDataObject
)
{
return S_OK;
}
/*!--------------------------------------------------------------------------
TFSComponentData::CreatePropertyPages
Implementation of IExtendPropertySheet::CreatePropertyPages
Called for a node to put up property pages
Author:
---------------------------------------------------------------------------*/
STDMETHODIMP
CRasDialin::CreatePropertyPages
(
LPPROPERTYSHEETCALLBACK lpProvider,
LONG_PTR handle,
LPDATAOBJECT pDataObject
)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
//STGMEDIUM medium = { TYMED_NULL, NULL, NULL };
STGMEDIUM mediumMachine = { TYMED_HGLOBAL, NULL, NULL };
STGMEDIUM mediumUser = { TYMED_HGLOBAL, NULL, NULL };
HGLOBAL hMem = GlobalAlloc(GMEM_SHARE, MAX_PATH * sizeof(WCHAR));
mediumMachine.hGlobal = hMem;
hMem = GlobalAlloc(GMEM_SHARE, MAX_PATH * sizeof(WCHAR));
mediumUser.hGlobal = hMem;
HRESULT hr = S_OK;
DWORD dwError;
LPWSTR pMachineName = NULL;
LPWSTR pUserName = NULL;
SERVER_INFO_102* pServerInfo102 = NULL;
NET_API_STATUS netRet = 0;
DSROLE_PRIMARY_DOMAIN_INFO_BASIC* pdsRole = NULL;
//==================================================================
// check if the machine is a standalone NT5 server
// check if the machine focused on is NT5 machine
if ( !g_cfMachineName )
g_cfMachineName = RegisterClipboardFormat(CCF_LOCAL_USER_MANAGER_MACHINE_NAME);
fmte.cfFormat = g_cfMachineName;
CHECK_HR( hr = pDataObject->GetDataHere(&fmte, &mediumMachine));
pMachineName = (LPWSTR)mediumMachine.hGlobal;
ASSERT(pMachineName);
if(!pMachineName) CHECK_HR(hr = E_INVALIDARG);
// not to show the page if focusing on workstation
// TODO change to real
/* postpone, till The dialog is being called
if(HrIsNTServer(pMachineName) != S_OK)
{
m_bShowPage = FALSE;
goto L_EXIT;
}
*/
if (g_cfDisplayName == 0)
g_cfDisplayName = RegisterClipboardFormat(CCF_DISPLAY_NAME);
fmte.cfFormat = g_cfDisplayName;
CHECK_HR( hr = pDataObject->GetDataHere(&fmte, &mediumUser));
pUserName = (LPWSTR)mediumUser.hGlobal;
ASSERT(pUserName);
if(!pUserName)
CHECK_HR(hr = E_INVALIDARG);
ASSERT(!m_pMergedPage);
try{
m_pMergedPage = new CDlgRASDialinMerge(RASUSER_ENV_LOCAL, pMachineName, pUserName);
#ifdef SINGLE_SDO_CONNECTION // for share the same sdo connection for multiple users
CHECK_HR(hr = GetSharedSdoServer(pMachineName, NULL, NULL, NULL, m_pMergedPage->GetMarshalSdoServerHolder()));
#endif
// tell MMC to hook the proc because we are running on a separate,
// non MFC thread.
m_pMergedPage->m_psp.pfnCallback = &CDlgRASDialinMerge::PropSheetPageProc;
// We also need to save a self-reference so that the static callback
// function can recover a "this" pointer
m_pMergedPage->m_psp.lParam = (LONG_PTR)m_pMergedPage;
MMCPropPageCallback(&m_pMergedPage->m_psp);
HPROPSHEETPAGE hPage = ::CreatePropertySheetPage(&m_pMergedPage->m_psp);
if(hPage == NULL)
return E_UNEXPECTED;
lpProvider->AddPage(hPage);
}catch(CMemoryException&){
delete m_pMergedPage;
m_pMergedPage = NULL;
CHECK_HR(hr = E_OUTOFMEMORY);
}
L_ERR:
if FAILED(hr)
ReportError(hr, IDS_ERR_PROPERTYPAGE, NULL);
if(pUserName)
GlobalFree(pUserName);
if(pMachineName)
GlobalFree(pMachineName);
if(pServerInfo102)
NetApiBufferFree(pServerInfo102);
return hr;
}