400 lines
11 KiB
C++
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;
|
|
}
|
|
|