/**********************************************************************/ /** 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 #include #include #include #include #include #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; }