/*++ Copyright (c) 1994-1998 Microsoft Corporation Module Name : fscfg.cpp Abstract: FTP Configuration Module Author: Ronald Meijer (ronaldm) Project: Internet Services Manager Revision History: --*/ // // Include Files // #include "stdafx.h" #include "fscfg.h" #include "fservic.h" #include "facc.h" #include "fmessage.h" #include "vdir.h" #include "security.h" #include "wizard.h" #include "..\mmc\constr.h" // // Standard Configuration Information // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< #define SVC_ID INET_FTP_SVC_ID #define INETSLOC_MASK (INET_FTP_SVCLOC_ID) // // Service capabilities flags // #define SERVICE_INFO_FLAGS (\ ISMI_UNDERSTANDINSTANCE | \ ISMI_INSTANCES | \ ISMI_CHILDREN | \ ISMI_INETSLOCDISCOVER | \ ISMI_CANCONTROLSERVICE | \ ISMI_CANPAUSESERVICE | \ ISMI_TASKPADS | \ ISMI_SECURITYWIZARD | \ ISMI_HASWEBPROTOCOL | \ ISMI_SUPPORTSMETABASE | \ ISMI_SUPPORTSMASTER | \ ISMI_NORMALTBMAPPING) // // Name used for this service by the service controller manager. // #define SERVICE_SC_NAME _T("MSFTPSVC") // // Short descriptive name of the service. This // is what will show up as the name of the service // in the internet manager tool. // // Issue: I'm assuming here that this name does NOT // require localisation. // #define SERVICE_SHORT_NAME _T("FTP") // // Longer name. This is the text that shows up in // the tooltips text on the internet manager // tool. This probably should be localised. // #define SERVICE_LONG_NAME _T("FTP Service") // // Web browser protocol name. e.g. xxxxx://address // A blank string if this is not supported. // #define SERVICE_PROTOCOL _T("ftp") // // Toolbar button background mask. This is // the colour that gets masked out in // the bitmap file and replaced with the // actual button background. This setting // is automatically assumed to be lt. gray // if NORMAL_TB_MAPPING (above) is TRUE // #define BUTTON_BMP_BACKGROUND RGB(192, 192, 192) // Lt. Gray // // Resource ID of the toolbar button bitmap. // // The bitmap must be 16x16 // #define BUTTON_BMP_ID IDB_FTP // // Similar to BUTTON_BMP_BACKGROUND, this is the // background mask for the service ID // #define SERVICE_BMP_BACKGROUND RGB(255,0,255) // Purple // // Bitmap id which is used in the service view // of the service manager. This may be the same // bitmap as BUTTON_BMP_BACKGROUND. // // The bitmap must be 16x16. // #define SERVICE_BMP_ID IDB_FTPVIEW // // /* K2 */ // // Similar to BUTTON_BMP_BACKGROUND, this is the // background mask for the child bitmap // #define CHILD_BMP_BACKGROUND RGB(255, 0, 255) // Purple // // /* K2 */ // // Bitmap id which is used for the child bitmap // // The bitmap must be 16x16. // #define CHILD_BMP_ID IDB_FTPDIR #define CHILD_BMP32_ID IDB_FTPDIR32 // // /* K2 */ // // Large bitmap (32x32) id // #define SERVICE_BMP32_ID IDB_FTPVIEW32 // // Service Name // const LPCTSTR g_cszSvc = _T("MSFTPSVC"); // // Help IDs // #define HIDD_DIRECTORY_PROPERTIES (0x207DB) #define HIDD_HOME_DIRECTORY_PROPERTIES (HIDD_DIRECTORY_PROPERTIES + 0x20000) // // End Of Standard configuration Information // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CFTPInstanceProps::CFTPInstanceProps( IN LPCTSTR lpszServerName, IN DWORD dwInstance OPTIONAL ) /*++ Routine Description: Constructor for FTP instance properties Arguments: LPCTSTR lpszServerName : Server name DWORD dwInstance : Instance number (could be MASTER_INSTANCE) Return Value: N/A --*/ : CInstanceProps(lpszServerName, g_cszSvc, dwInstance, 21U), m_nMaxConnections((LONG)0L), m_nConnectionTimeOut((LONG)0L), m_dwLogType(MD_LOG_TYPE_DISABLED), /**/ m_strUserName(), m_strPassword(), m_fAllowAnonymous(FALSE), m_fOnlyAnonymous(FALSE), m_fPasswordSync(TRUE), m_acl(), /**/ m_strExitMessage(), m_strMaxConMsg(), m_strlWelcome(), /**/ m_fDosDirOutput(TRUE), /**/ m_dwDownlevelInstance(1) { // // Fetch everything // m_dwMDUserType = ALL_METADATA; m_dwMDDataType = ALL_METADATA; } /* virtual */ void CFTPInstanceProps::ParseFields() /*++ Routine Description: Break into fields. Arguments: None. Return Value: None. --*/ { // // Fetch base properties // CInstanceProps::ParseFields(); BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData) // // Service Page // HANDLE_META_RECORD(MD_MAX_CONNECTIONS, m_nMaxConnections) HANDLE_META_RECORD(MD_CONNECTION_TIMEOUT, m_nConnectionTimeOut) HANDLE_META_RECORD(MD_LOG_TYPE, m_dwLogType) // // Accounts Page // HANDLE_META_RECORD(MD_ANONYMOUS_USER_NAME, m_strUserName) HANDLE_META_RECORD(MD_ANONYMOUS_PWD, m_strPassword) HANDLE_META_RECORD(MD_ANONYMOUS_ONLY, m_fOnlyAnonymous) HANDLE_META_RECORD(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous) HANDLE_META_RECORD(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync) HANDLE_META_RECORD(MD_ADMIN_ACL, m_acl) // // Message Page // HANDLE_META_RECORD(MD_EXIT_MESSAGE, m_strExitMessage) HANDLE_META_RECORD(MD_MAX_CLIENTS_MESSAGE, m_strMaxConMsg) HANDLE_META_RECORD(MD_GREETING_MESSAGE, m_strlWelcome) // // Directory Properties Page // HANDLE_META_RECORD(MD_MSDOS_DIR_OUTPUT, m_fDosDirOutput); END_PARSE_META_RECORDS } /* virtual */ HRESULT CFTPInstanceProps::WriteDirtyProps() /*++ Routine Description: Write the dirty properties to the metabase Arguments: None Return Value: HRESULT --*/ { CError err(CInstanceProps::WriteDirtyProps()); if (err.Failed()) { return err; } BEGIN_META_WRITE() // // Service Page // META_WRITE(MD_MAX_CONNECTIONS, m_nMaxConnections) META_WRITE(MD_CONNECTION_TIMEOUT, m_nConnectionTimeOut) META_WRITE(MD_LOG_TYPE, m_dwLogType) // // Accounts Page // META_WRITE(MD_ANONYMOUS_USER_NAME, m_strUserName) META_WRITE(MD_ANONYMOUS_PWD, m_strPassword) META_WRITE(MD_ANONYMOUS_ONLY, m_fOnlyAnonymous) META_WRITE(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous) META_WRITE(MD_ANONYMOUS_USE_SUBAUTH, m_fPasswordSync) META_WRITE(MD_ADMIN_ACL, m_acl) // // Message Page // META_WRITE(MD_EXIT_MESSAGE, m_strExitMessage) META_WRITE(MD_MAX_CLIENTS_MESSAGE, m_strMaxConMsg) META_WRITE(MD_GREETING_MESSAGE, m_strlWelcome) // // Directory Properties Page // META_WRITE(MD_MSDOS_DIR_OUTPUT, m_fDosDirOutput); END_META_WRITE(err); return err; } CFTPDirProps::CFTPDirProps( IN LPCTSTR lpszServerName, IN DWORD dwInstance, OPTIONAL IN LPCTSTR lpszParent, OPTIONAL IN LPCTSTR lpszAlias OPTIONAL ) /*++ Routine Description: FTP Directory properties object Arguments: LPCTSTR lpszServerName : Server name DWORD dwInstance : Instance number (could be MASTER_INSTANCE) LPCTSTR lpszParent : Parent path (could be NULL) LPCTSTR lpszAlias : Alias name (could be NULL) Return Value: N/A. --*/ : CChildNodeProps( lpszServerName, g_cszSvc, dwInstance, lpszParent, lpszAlias, WITH_INHERITANCE, FALSE // Complete information ), /**/ m_fDontLog(FALSE), m_ipl() { // // Fetch everything // m_dwMDUserType = ALL_METADATA; m_dwMDDataType = ALL_METADATA; } /* virtual */ void CFTPDirProps::ParseFields() /*++ Routine Description: Break into fields. Arguments: None. Return Value: None. --*/ { // // Fetch base properties // CChildNodeProps::ParseFields(); BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData) HANDLE_META_RECORD(MD_VR_USERNAME, m_strUserName) HANDLE_META_RECORD(MD_VR_PASSWORD, m_strPassword) HANDLE_META_RECORD(MD_DONT_LOG, m_fDontLog); HANDLE_META_RECORD(MD_IP_SEC, m_ipl); END_PARSE_META_RECORDS } /* virtual */ HRESULT CFTPDirProps::WriteDirtyProps() /*++ Routine Description: Write the dirty properties to the metabase Arguments: None Return Value: HRESULT --*/ { CError err(CChildNodeProps::WriteDirtyProps()); if (err.Failed()) { return err; } // // CODEWORK: Consider DDX/DDV like methods which do both // ParseFields and WriteDirtyProps in a single method. Must // take care not to write data which should only be read, not // written // BEGIN_META_WRITE() META_WRITE(MD_VR_USERNAME, m_strUserName) META_WRITE(MD_VR_PASSWORD, m_strPassword) META_WRITE(MD_DONT_LOG, m_fDontLog); META_WRITE(MD_IP_SEC, m_ipl); END_META_WRITE(err); return err; } CFtpSheet::CFtpSheet( LPCTSTR pszCaption, LPCTSTR lpszServer, DWORD dwInstance, LPCTSTR lpszParent, LPCTSTR lpszAlias, CWnd * pParentWnd, LPARAM lParam, LONG_PTR handle, UINT iSelectPage ) /*++ Routine Description: FTP Property sheet constructor Arguments: LPCTSTR pszCaption : Sheet caption LPCTSTR lpszServer : Server name DWORD dwInstance : Instance number LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Alias name CWnd * pParentWnd : Parent window LPARAM lParam : Parameter for MMC console LONG_PTR handle : MMC console handle UINT iSelectPage : Initial page selected or -1 Return Value: N/A --*/ : CInetPropertySheet( pszCaption, lpszServer, g_cszSvc, dwInstance, lpszParent, lpszAlias, pParentWnd, lParam, handle, iSelectPage ), m_ppropInst(NULL), m_ppropDir(NULL) { } CFtpSheet::~CFtpSheet() /*++ Routine Description: FTP Sheet destructor Arguments: N/A Return Value: N/A --*/ { FreeConfigurationParameters(); // // Must be deleted by now // ASSERT(m_ppropInst == NULL); ASSERT(m_ppropDir == NULL); } void CFtpSheet::WinHelp( IN DWORD dwData, IN UINT nCmd ) /*++ Routine Description: FTP Property sheet help handler Arguments: DWORD dwData : WinHelp data (dialog ID) UINT nCmd : WinHelp command Return Value: None Notes: Replace the dialog ID if this is the directory tab. We have different help depending on virtual directory, home, file, directory. --*/ { ASSERT(m_ppropDir != NULL); if (::lstrcmpi(m_ppropDir->QueryAlias(), g_cszRoot) == 0 && dwData == HIDD_DIRECTORY_PROPERTIES) { // // It's a home virtual directory -- change the ID // dwData = HIDD_HOME_DIRECTORY_PROPERTIES; } CInetPropertySheet::WinHelp(dwData, nCmd); } /* virtual */ HRESULT CFtpSheet::LoadConfigurationParameters() /*++ Routine Description: Load configuration parameters information Arguments: None Return Value: HRESULT --*/ { CError err; if (m_ppropInst == NULL) { ASSERT(m_ppropDir == NULL); m_ppropInst = new CFTPInstanceProps(m_strServer, m_dwInstance); m_ppropDir = new CFTPDirProps( m_strServer, m_dwInstance, m_strParent, m_strAlias ); if (!m_ppropInst || !m_ppropDir) { err = ERROR_NOT_ENOUGH_MEMORY; return err; } err = m_ppropInst->LoadData(); if (err.Succeeded()) { err = m_ppropDir->LoadData(); } } return err; } /* virtual */ void CFtpSheet::FreeConfigurationParameters() /*++ Routine Description: Clean up configuration data Arguments: None Return Value: None --*/ { // // Must be deleted by now // ASSERT(m_ppropInst != NULL); ASSERT(m_ppropDir != NULL); SAFE_DELETE(m_ppropInst); SAFE_DELETE(m_ppropDir); } // // Message Map // BEGIN_MESSAGE_MAP(CFtpSheet, CInetPropertySheet) //{{AFX_MSG_MAP(CInetPropertySheet) //}}AFX_MSG_MAP END_MESSAGE_MAP() // // Global DLL instance // HINSTANCE hInstance; // // ISM API Functions // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< extern "C" DWORD APIENTRY ISMQueryServiceInfo( OUT ISMSERVICEINFO * psi ) /*++ Routine Description: Return service-specific information back to the application. This function is called by the service manager immediately after LoadLibary(); The size element must be set prior to calling this API. Arguments: ISMSERVICEINFO * psi : Service information returned. Return Value: Error return code --*/ { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(psi != NULL); ASSERT(psi->dwSize == ISMSERVICEINFO_SIZE); psi->dwSize = ISMSERVICEINFO_SIZE; psi->dwVersion = ISM_VERSION; psi->flServiceInfoFlags = SERVICE_INFO_FLAGS; psi->ullDiscoveryMask = INETSLOC_MASK; psi->rgbButtonBkMask = BUTTON_BMP_BACKGROUND; psi->nButtonBitmapID = BUTTON_BMP_ID; psi->rgbServiceBkMask = SERVICE_BMP_BACKGROUND; psi->nServiceBitmapID = SERVICE_BMP_ID; psi->rgbServiceBkMask = SERVICE_BMP_BACKGROUND; psi->nLargeServiceBitmapID = SERVICE_BMP32_ID; ASSERT(::lstrlen(SERVICE_LONG_NAME) <= MAX_LNLEN); ASSERT(::lstrlen(SERVICE_SHORT_NAME) <= MAX_SNLEN); ::lstrcpy(psi->atchShortName, SERVICE_SHORT_NAME); ::lstrcpy(psi->atchLongName, SERVICE_LONG_NAME); // // /* K2 */ // psi->rgbChildBkMask = CHILD_BMP_BACKGROUND; psi->nChildBitmapID = CHILD_BMP_ID ; psi->rgbLargeChildBkMask = CHILD_BMP_BACKGROUND; psi->nLargeChildBitmapID = CHILD_BMP32_ID; // // IIS 5 // ASSERT(::lstrlen(SERVICE_PROTOCOL) <= MAX_SNLEN); ASSERT(::lstrlen(g_cszSvc) <= MAX_SNLEN); ::lstrcpy(psi->atchProtocol, SERVICE_PROTOCOL); ::lstrcpy(psi->atchMetaBaseName, g_cszSvc); return ERROR_SUCCESS; } DWORD APIENTRY ISMDiscoverServers( OUT ISMSERVERINFO * psi, IN DWORD * pdwBufferSize, IN int * cServers ) /*++ Routine Description: Discover machines running this service. This is only necessary for services not discovered with inetsloc (which don't give a mask) Arguments: ISMSERVERINFO * psi : Server info buffer. DWORD * pdwBufferSize : Size required/available. int * cServers : Number of servers in buffer. Return Value: Error return code --*/ { AFX_MANAGE_STATE(AfxGetStaticModuleState()); *cServers = 0; *pdwBufferSize = 0L; // // We're an inetsloc service // TRACEEOLID("Warning: service manager called bogus ISMDiscoverServers"); ASSERT(FALSE); return ERROR_SUCCESS; } extern "C" DWORD APIENTRY ISMQueryServerInfo( IN LPCTSTR lpszServerName, OUT ISMSERVERINFO * psi ) /*++ Routine Description: Get information about a specific server with regards to this service. Arguments: LPCTSTR lpszServerName : Name of server. ISMSERVERINFO * psi : Server information returned. Return Value: Error return code --*/ { AFX_MANAGE_STATE(AfxGetStaticModuleState()); ASSERT(psi != NULL); ASSERT(psi->dwSize == ISMSERVERINFO_SIZE); ASSERT(::lstrlen(lpszServerName) <= MAX_SERVERNAME_LEN); psi->dwSize = ISMSERVERINFO_SIZE; ::lstrcpy(psi->atchServerName, lpszServerName); // // Start with NULL comment // *psi->atchComment = _T('\0'); // // First look at the SC // CError err(::QueryInetServiceStatus( psi->atchServerName, SERVICE_SC_NAME, &(psi->nState) )); if (err.Failed()) { psi->nState = INetServiceUnknown; return err; } // // Check the metabase to see if the service is installed // CMetaKey mk(lpszServerName, METADATA_PERMISSION_READ, g_cszSvc); err = mk.QueryResult(); if (err.Failed()) { if (err == REGDB_E_CLASSNOTREG) { // // Ok, the service is there, but the metabase is not. // This must be the old IIS 1-3 version of this service, // which doesn't count as having the service installed. // return ERROR_SERVICE_DOES_NOT_EXIST; } return err; } // // If not exist, return bogus acceptable error // return (err.Win32Error() == ERROR_PATH_NOT_FOUND) ? ERROR_SERVICE_DOES_NOT_EXIST : err.Win32Error(); } extern "C" DWORD APIENTRY ISMChangeServiceState( IN int nNewState, OUT int * pnCurrentState, IN DWORD dwInstance, IN LPCTSTR lpszServers ) /*++ Routine Description: Change the service state of the servers (to paused/continue, started, stopped, etc) Arguments: int nNewState : INetService definition. int * pnCurrentState : Ptr to current state (will be changed DWORD dwInstance : Instance or 0 for the service itself LPCTSTR lpszServers : Double NULL terminated list of servers. Return Value: Error return code --*/ { AFX_MANAGE_STATE(AfxGetStaticModuleState() ); ASSERT(nNewState >= INetServiceStopped && nNewState <= INetServicePaused); if (IS_MASTER_INSTANCE(dwInstance)) { // // Service itself is referred to here // return ChangeInetServiceState( lpszServers, SERVICE_SC_NAME, nNewState, pnCurrentState ); } // // Change the state of the instance // CInstanceProps inst(lpszServers, g_cszSvc, dwInstance); inst.LoadData(); CError err(inst.ChangeState(nNewState)); *pnCurrentState = inst.QueryISMState(); return err; } extern "C" DWORD APIENTRY ISMConfigureServers( IN HWND hWnd, IN DWORD dwInstance, IN LPCTSTR lpszServers ) /*++ Routine Description: Display configuration property sheet. Arguments: HWND hWnd : Main app window handle DWORD dwInstance : Instance number LPCTSTR lpszServers : Double NULL terminated list of servers Return Value: Error return code --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); DWORD err = ERROR_SUCCESS; // // Convert the list of servers to a // more manageable CStringList. // CStringList strlServers; err = ConvertDoubleNullListToStringList(lpszServers, strlServers); if (err != ERROR_SUCCESS) { TRACEEOLID("Error building server string list"); return err; } CString strCaption; if (strlServers.GetCount() == 1) { CString str; LPCTSTR lpComputer = PURE_COMPUTER_NAME(lpszServers); if(IS_MASTER_INSTANCE(dwInstance)) { VERIFY(str.LoadString(IDS_CAPTION_DEFAULT)); strCaption.Format(str, lpComputer); } else { VERIFY(str.LoadString(IDS_CAPTION)); strCaption.Format(str, dwInstance, lpComputer); } } else // Multiple server caption { VERIFY(strCaption.LoadString(IDS_CAPTION_MULTIPLE)); } ASSERT(strlServers.GetCount() == 1); // // Get the server name // LPCTSTR lpszServer = strlServers.GetHead(); CFtpSheet * pSheet = NULL; try { pSheet = new CFtpSheet( strCaption, lpszServer, dwInstance, NULL, g_cszRoot, CWnd::FromHandlePermanent(hWnd) ); pSheet->AddRef(); if (SUCCEEDED(pSheet->QueryInstanceResult())) { // // Add instance pages // pSheet->AddPage(new CFtpServicePage(pSheet)); pSheet->AddPage(new CFtpAccountsPage(pSheet)); pSheet->AddPage(new CFtpMessagePage(pSheet)); } if (SUCCEEDED(pSheet->QueryDirectoryResult())) { // // Add home directory pages for the home directory // pSheet->AddPage(new CFtpDirectoryPage(pSheet, TRUE)); pSheet->AddPage(new CFtpSecurityPage(pSheet)); } } catch(CMemoryException * e) { TRACEEOLID("Aborting because of exception"); err = ERROR_NOT_ENOUGH_MEMORY; e->Delete(); } if (err == ERROR_SUCCESS) { ASSERT(pSheet != NULL); pSheet->DoModal(); pSheet->Release(); } // // Sheet and pages clean themselves up // return err; } // // K2 Functions // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HRESULT AddMMCPage( IN LPPROPERTYSHEETCALLBACK lpProvider, IN CPropertyPage * pg ) /*++ Routine Description: Helper function to add MFC property page using callback provider to MMC. Arguments: LPPROPERTYSHEETCALLBACK lpProvider : Property sheet provider CPropertyPage * pg : MFC property page object Return Value: HRESULT --*/ { ASSERT(pg != NULL); // // Patch MFC property page class. // MMCPropPageCallback(&pg->m_psp); HPROPSHEETPAGE hPage = CreatePropertySheetPage( (LPCPROPSHEETPAGE)&pg->m_psp ); if (hPage == NULL) { return E_UNEXPECTED; } lpProvider->AddPage(hPage); return S_OK; } extern "C" HRESULT APIENTRY ISMBind( IN LPCTSTR lpszServer, OUT HANDLE * phServer ) /*++ Routine Description: Generate a handle for the server name. Arguments: LPCTSTR lpszServer : Server name HANDLE * phServer : Returns a handle Return Value: HRESULT --*/ { return COMDLL_ISMBind(lpszServer, phServer); } extern "C" HRESULT APIENTRY ISMUnbind( IN HANDLE hServer ) /*++ Routine Description: Free up the server handle Arguments: HANDLE hServer : Server handle Return Value: HRESULT --*/ { return COMDLL_ISMUnbind(hServer); } extern "C" HRESULT APIENTRY ISMMMCConfigureServers( IN HANDLE hServer, IN PVOID lpfnMMCCallbackProvider, IN LPARAM param, IN LONG_PTR handle, IN DWORD dwInstance ) /*++ Routine Description: Display configuration property sheet. Arguments: HANDLE hServer : Server handle PVOID lpfnMMCCallbackProvider : MMC Callback provider LPARAM param : MMC LPARAM LONG_PTR handle : MMC Console handle DWORD dwInstance : Instance number Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; LPPROPERTYSHEETCALLBACK lpProvider = (LPPROPERTYSHEETCALLBACK)lpfnMMCCallbackProvider; LPCTSTR lpszServer = GetServerNameFromHandle(hServer); ASSERT(lpszServer != NULL); CString str, strCaption; LPCTSTR lpszComputer = PURE_COMPUTER_NAME(lpszServer); if(IS_MASTER_INSTANCE(dwInstance)) { VERIFY(str.LoadString(IDS_CAPTION_DEFAULT)); strCaption.Format(str, lpszComputer); } else { VERIFY(str.LoadString(IDS_CAPTION)); strCaption.Format(str, dwInstance, lpszComputer); } CFtpSheet * pSheet = NULL; try { pSheet = new CFtpSheet( strCaption, lpszServer, dwInstance, NULL, g_cszRoot, NULL, param, handle ); pSheet->SetModeless(); CFtpServicePage * pServPage = NULL; CFtpAccountsPage * pAccPage = NULL; CFtpMessagePage * pMessPage = NULL; CFtpDirectoryPage * pDirPage = NULL; CFtpSecurityPage * pSecPage = NULL; if (SUCCEEDED(pSheet->QueryInstanceResult())) { // // Add instance pages // AddMMCPage(lpProvider, new CFtpServicePage(pSheet)); AddMMCPage(lpProvider, new CFtpAccountsPage(pSheet)); AddMMCPage(lpProvider, new CFtpMessagePage(pSheet)); } if (SUCCEEDED(pSheet->QueryDirectoryResult())) { // // Add home directory pages for the home directory // AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet, TRUE)); AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet)); } } catch(CMemoryException * e) { TRACEEOLID("Aborting because of exception"); err = ERROR_NOT_ENOUGH_MEMORY; e->Delete(); } // // Sheet and pages clean themselves up // return err; } extern "C" HRESULT APIENTRY ISMMMCConfigureChild( IN HANDLE hServer, IN PVOID lpfnMMCCallbackProvider, IN LPARAM param, IN LONG_PTR handle, IN DWORD dwAttributes, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Display configuration property sheet for child object. Arguments: HANDLE hServer : Server handle PVOID lpfnMMCCallbackProvider : MMC Callback provider LPARAM param : MMC parameter passed to sheet LONG_PTR handle : MMC console handle DWORD dwAttributes : Must be FILE_ATTRIBUTE_VIRTUAL_DIRECTORY DWORD dwInstance : Parent instance number LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Child to configure Return Value: Error return code --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); LPCTSTR lpszServer = GetServerNameFromHandle(hServer); CError err; LPPROPERTYSHEETCALLBACK lpProvider = (LPPROPERTYSHEETCALLBACK)lpfnMMCCallbackProvider; CString strCaption; { CString str; VERIFY(str.LoadString(IDS_DIR_TITLE)); strCaption.Format(str, lpszAlias); } ASSERT(dwAttributes == FILE_ATTRIBUTE_VIRTUAL_DIRECTORY); // // Call the APIs and build the property pages // CFtpSheet * pSheet = NULL; try { pSheet = new CFtpSheet( strCaption, lpszServer, dwInstance, lpszParent, lpszAlias, NULL, param, handle ); pSheet->SetModeless(); if (SUCCEEDED(pSheet->QueryDirectoryResult())) { CFtpDirectoryPage * pDirPage = NULL; CFtpSecurityPage * pSecPage = NULL; // // Add private pages // AddMMCPage(lpProvider, new CFtpDirectoryPage(pSheet)); AddMMCPage(lpProvider, new CFtpSecurityPage(pSheet)); } } catch(CMemoryException * e) { TRACEEOLID("Aborting due to exception"); err = ERROR_NOT_ENOUGH_MEMORY; e->Delete(); } // // Sheet and pages clean themselves up // return err; } extern "C" HRESULT APIENTRY ISMEnumerateInstances( IN HANDLE hServer, OUT ISMINSTANCEINFO * pii, OUT IN HANDLE * phEnum ) /*++ Routine Description: Enumerate Instances. First call with *phEnum == NULL. Arguments: HANDLE hServer : Server handle ISMINSTANCEINFO * pii : Instance info buffer HANDLE * phEnum : Enumeration handle. Return Value: Error return code --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer); ASSERT(pInterface != NULL); BEGIN_ASSURE_BINDING_SECTION err = COMDLL_ISMEnumerateInstances( pInterface, pii, phEnum, g_cszSvc ); END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_NO_MORE_ITEMS); return err; } extern "C" HRESULT APIENTRY ISMAddInstance( IN HANDLE hServer, IN DWORD dwSourceInstance, OUT ISMINSTANCEINFO * pii, OPTIONAL IN DWORD dwBufferSize ) /*++ Routine Description: Add an instance. Arguments: HANDLE hServer : Server handle DWORD dwSourceInstance : Source instance ID to clone ISMINSTANCEINFO * pii : Instance info buffer. May be NULL DWORD dwBufferSize : Size of buffer Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CIISWizardSheet sheet(IDB_WIZ_LEFT, IDB_WIZ_HEAD); CIISFtpWizSettings ws(hServer, g_cszSvc); CIISWizardBookEnd pgWelcome( IDS_SITE_WELCOME, IDS_NEW_SITE_WIZARD, IDS_SITE_BODY ); CVDWPDescription pgDescr(&ws); CVDWPBindings pgBindings(&ws); CVDWPPath pgHome(&ws, FALSE); CVDWPUserName pgUserName(&ws, FALSE); CVDWPPermissions pgPerms(&ws, FALSE); CIISWizardBookEnd pgCompletion( &ws.m_hrResult, IDS_SITE_SUCCESS, IDS_SITE_FAILURE, IDS_NEW_SITE_WIZARD ); sheet.AddPage(&pgWelcome); sheet.AddPage(&pgDescr); sheet.AddPage(&pgBindings); sheet.AddPage(&pgHome); sheet.AddPage(&pgUserName); sheet.AddPage(&pgPerms); sheet.AddPage(&pgCompletion); if (sheet.DoModal() == IDCANCEL) { return ERROR_CANCELLED; } CError err(ws.m_hrResult); if (err.Succeeded()) { // // Get info on it to be returned. // ISMQueryInstanceInfo( ws.m_pKey, WITHOUT_INHERITANCE, pii, ws.m_dwInstance ); } return err; } extern "C" HRESULT APIENTRY ISMDeleteInstance( IN HANDLE hServer, IN DWORD dwInstance ) /*++ Routine Description: Delete an instance Arguments: HANDLE hServer : Server handle DWORD dwInstance : Instance to be deleted Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer); BEGIN_ASSURE_BINDING_SECTION err = CInstanceProps::Delete( pInterface, g_cszSvc, dwInstance ); END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED); return err; } extern "C" HRESULT APIENTRY ISMEnumerateChildren( IN HANDLE hServer, OUT ISMCHILDINFO * pii, OUT IN HANDLE * phEnum, IN DWORD dwInstance, IN LPCTSTR lpszParent ) /*++ Routine Description: Enumerate children. First call with *phEnum == NULL; Arguments: HANDLE hServer : Server handle ISMCHILDINFO * pii : Child info buffer HANDLE * phEnum : Enumeration handle. DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer); BEGIN_ASSURE_BINDING_SECTION err = COMDLL_ISMEnumerateChildren( pInterface, pii, phEnum, g_cszSvc, dwInstance, lpszParent ); END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_NO_MORE_ITEMS); return err; } extern "C" HRESULT APIENTRY ISMAddChild( IN HANDLE hServer, OUT ISMCHILDINFO * pii, IN DWORD dwBufferSize, IN DWORD dwInstance, IN LPCTSTR lpszParent ) /*++ Routine Description: Add a child. Arguments: HANDLE hServer : Server handle ISMCHILDINFO * pii : Child info buffer. May be NULL DWORD dwBufferSize : Size of info buffer DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CIISFtpWizSettings ws(hServer, g_cszSvc, dwInstance, lpszParent); CIISWizardSheet sheet(IDB_WIZ_LEFT_DIR, IDB_WIZ_HEAD_DIR); CIISWizardBookEnd pgWelcome( IDS_VDIR_WELCOME, IDS_NEW_VDIR_WIZARD, IDS_VDIR_BODY ); CVDWPAlias pgAlias(&ws); CVDWPPath pgPath(&ws, TRUE); CVDWPUserName pgUserName(&ws, TRUE); CVDWPPermissions pgPerms(&ws, TRUE); CIISWizardBookEnd pgCompletion( &ws.m_hrResult, IDS_VDIR_SUCCESS, IDS_VDIR_FAILURE, IDS_NEW_VDIR_WIZARD ); sheet.AddPage(&pgWelcome); sheet.AddPage(&pgAlias); sheet.AddPage(&pgPath); sheet.AddPage(&pgUserName); sheet.AddPage(&pgPerms); sheet.AddPage(&pgCompletion); if (sheet.DoModal() == IDCANCEL) { return ERROR_CANCELLED; } CError err(ws.m_hrResult); if (err.Succeeded()) { // // Refresh child info // err = ISMQueryChildInfo( ws.m_pKey, WITH_INHERITANCE, pii, ws.m_dwInstance, ws.m_strParent, ws.m_strAlias ); } return err; } extern "C" HRESULT APIENTRY ISMDeleteChild( IN HANDLE hServer, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Delete a child. Arguments: HANDLE hServer : Server handle DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Alias of child to be deleted Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer); BEGIN_ASSURE_BINDING_SECTION err = CChildNodeProps::Delete( pInterface, g_cszSvc, dwInstance, lpszParent, lpszAlias ); END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED); return err; } extern "C" HRESULT APIENTRY ISMRenameChild( IN HANDLE hServer, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias, IN LPCTSTR lpszNewName ) /*++ Routine Description: Rename a child. Arguments: HANDLE hServer : Server handle DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Alias of child to be renamed LPCTSTR lpszNewName : New alias name Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CError err; CMetaInterface * pInterface = GetMetaKeyFromHandle(hServer); BEGIN_ASSURE_BINDING_SECTION err = CChildNodeProps::Rename( pInterface, g_cszSvc, dwInstance, lpszParent, lpszAlias, lpszNewName ); END_ASSURE_BINDING_SECTION(err, pInterface, ERROR_CANCELLED) return err; } extern "C" HRESULT APIENTRY ISMQueryInstanceInfo( IN HANDLE hServer, IN BOOL fInherit, OUT ISMINSTANCEINFO * pii, IN DWORD dwInstance ) /*++ Routine Description: Get instance specific information. Arguments: HANDLE hServer : Server handle BOOL fInherit : TRUE to inherit, FALSE otherwise ISMINSTANCEINFO * pii : Instance info buffer LPCTSTR lpszServer : A single server DWORD dwInstance : Instance number Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); ASSERT(pii != NULL); CError err; CMetaKey * pKey = GetMetaKeyFromHandle(hServer); BEGIN_ASSURE_BINDING_SECTION CInstanceProps inst(pKey, g_cszSvc, dwInstance); err = inst.LoadData(); if (err.Succeeded()) { pii->dwSize = ISMINSTANCEINFO_SIZE; inst.FillInstanceInfo(pii); // // Get properties on the home directory // CChildNodeProps home( &inst, g_cszSvc, dwInstance, NULL, g_cszRoot, fInherit, TRUE // Path only ); err = home.LoadData(); home.FillInstanceInfo(pii); } END_ASSURE_BINDING_SECTION(err, pKey, err); return err.Failed() ? err : S_OK; } extern "C" HRESULT APIENTRY ISMQueryChildInfo( IN HANDLE hServer, IN BOOL fInherit, OUT ISMCHILDINFO * pii, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Get child-specific info. Arguments: HANDLE hServer : Server handle BOOL fInherit : TRUE to inherit, FALSE otherwise ISMCHILDINFO * pii : Child info buffer DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent Path ("" for root) LPCTSTR lpszAlias : Alias of child to be deleted Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); // // Get all the inherited properties // CChildNodeProps node( GetMetaKeyFromHandle(hServer), g_cszSvc, dwInstance, lpszParent, lpszAlias, fInherit, FALSE // Complete information ); CError err(node.LoadData()); // // Set the output structure // pii->dwSize = ISMCHILDINFO_SIZE; node.FillChildInfo(pii); // // Not supported for FTP // ASSERT(!node.IsRedirected()); ASSERT(!*pii->szRedirPath); ASSERT(!pii->fEnabledApplication); return err; } extern "C" HRESULT APIENTRY ISMConfigureChild( IN HANDLE hServer, IN HWND hWnd, IN DWORD dwAttributes, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Configure child. Arguments: HANDLE hServer : Server handle HWND hWnd : Main app window handle DWORD dwAttributes : File attributes DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Child to configure or NULL Return Value: Error return code. --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); CMetaKey * pKey = GetMetaKeyFromHandle(hServer); LPCTSTR lpszServer = GetServerNameFromHandle(hServer); CError err; CString strCaption; { CString str; VERIFY(str.LoadString(IDS_DIR_TITLE)); strCaption.Format(str, lpszAlias); } ASSERT(dwAttributes == FILE_ATTRIBUTE_VIRTUAL_DIRECTORY); // // Call the APIs and build the property pages // CFtpSheet * pSheet = NULL; try { pSheet = new CFtpSheet( strCaption, lpszServer, dwInstance, lpszParent, lpszAlias, CWnd::FromHandlePermanent(hWnd) ); pSheet->AddRef(); if (SUCCEEDED(pSheet->QueryDirectoryResult())) { CFtpDirectoryPage * pDirPage = NULL; CFtpSecurityPage * pSecPage = NULL; // // Add private pages // pSheet->AddPage(new CFtpDirectoryPage(pSheet)); pSheet->AddPage(new CFtpSecurityPage(pSheet)); } } catch(CMemoryException * e) { TRACEEOLID("Aborting due to exception"); err = ERROR_NOT_ENOUGH_MEMORY; e->Delete(); } if (err.Succeeded()) { ASSERT(pSheet != NULL); pSheet->DoModal(); pSheet->Release(); } // // Sheet and pages clean themselves up // return err; } class CFTPSecurityTemplate : public CIISSecurityTemplate /*++ Class Description: FTP Security template class Public Interface: CFTPSecurityTemplate : Constructor ApplySettings : Apply template to destination path GenerateSummary : Generate text summary --*/ { // // Constructor // public: CFTPSecurityTemplate( IN const CMetaKey * pKey, IN LPCTSTR lpszMDPath, IN BOOL fInherit ); public: // // Apply settings to destination path // virtual HRESULT ApplySettings( IN BOOL fUseTemplates, IN LPCTSTR lpszServerName, IN LPCTSTR lpszService, IN DWORD dwInstance = MASTER_INSTANCE, IN LPCTSTR lpszParent = NULL, IN LPCTSTR lpszAlias = NULL ); // // Load and parse source data // virtual HRESULT LoadData(); virtual void GenerateSummary( IN BOOL fUseTemplates, IN LPCTSTR lpszServerName, IN LPCTSTR lpszService, IN DWORD dwInstance = MASTER_INSTANCE, IN LPCTSTR lpszParent = NULL, IN LPCTSTR lpszAlias = NULL ); protected: // // Break out GetAllData() data to data fields // virtual void ParseFields(); public: MP_BOOL m_fAllowAnonymous; MP_BOOL m_fAnonymousOnly; }; CFTPSecurityTemplate::CFTPSecurityTemplate( IN const CMetaKey * pKey, IN LPCTSTR lpszMDPath, IN BOOL fInherit ) /*++ Routine Description: Construct from open key Arguments: const CMetaKey * pKey : Open key LPCTSTR lpszMDPath : Path BOOL fInherit : TRUE to inherit values, FALSE if not Return Value: N/A --*/ : CIISSecurityTemplate(pKey, lpszMDPath, fInherit), m_fAllowAnonymous(FALSE), m_fAnonymousOnly(FALSE) { // // Managed Properties // m_dlProperties.AddTail(MD_ALLOW_ANONYMOUS); m_dlProperties.AddTail(MD_ANONYMOUS_ONLY); } /* virtual */ HRESULT CFTPSecurityTemplate::LoadData() /*++ Routine Description: LoadData() base class override Arguments: None Return Value: HRESULT Notes: The FTP wizard has an annoying idiosynchrasy: access authentication settings are per site, not per vdir. Therefore, they need to be set and fetched in a separate path, and not be set at all if not setting props on a site. What a pain... --*/ { TRACEEOLID(m_strMetaPath); CError err(CIISSecurityTemplate::LoadData()); if (lstrcmpi(m_strMetaRoot, g_cszRoot) == 0) { // // Fetch the anonymous access settings from // the instance node. Note: This explicit step // should only be necessary for templates, because // this would otherwise be picked up on inheritance. // ASSERT(!m_fInherit); m_strMetaRoot.Empty(); err = CIISSecurityTemplate::LoadData(); } return err; } /* virtual */ void CFTPSecurityTemplate::ParseFields() /*++ Routine Description: Break into fields. Arguments: None. Return Value: None. --*/ { // // Fetch base class values // CIISSecurityTemplate::ParseFields(); BEGIN_PARSE_META_RECORDS(m_dwNumEntries, m_pbMDData) HANDLE_META_RECORD(MD_ALLOW_ANONYMOUS, m_fAllowAnonymous) HANDLE_META_RECORD(MD_ANONYMOUS_ONLY, m_fAnonymousOnly) END_PARSE_META_RECORDS } /* virtual */ HRESULT CFTPSecurityTemplate::ApplySettings( IN BOOL fUseTemplate, IN LPCTSTR lpszServerName, IN LPCTSTR lpszService, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Apply the settings to the specified destination path Arguments: BOOL fUseTemplates : TRUE if the source is from a template, FALSE if using inheritance. LPCTSTR lpszServerName : Server name LPCTSTR lpszService : Service name DWORD dwInstance : Instance LPCTSTR lpszParent : Parent path (or NULL) LPCTSTR lpszAlias : Alias name (or NULL) Return Value: HRESULT --*/ { // // Write base class properties // CError err(CIISSecurityTemplate::ApplySettings( fUseTemplate, lpszServerName, lpszService, dwInstance, lpszParent, lpszAlias )); if (err.Failed()) { return err; } BOOL fWriteProperties = TRUE; CMetaKey mk( lpszServerName, METADATA_PERMISSION_WRITE, lpszService, dwInstance, lpszParent, lpszAlias ); err = mk.QueryResult(); if (err.Win32Error() == ERROR_PATH_NOT_FOUND) { if (!fUseTemplate) { // // No need to delete properties; everything's already // inherited. Note that this is the only legit failure // case. If using a template, the base class must have // created the path by now. // fWriteProperties = FALSE; err.Reset(); } } if (fWriteProperties) { do { if (mk.IsHomeDirectoryPath()) { BREAK_ON_ERR_FAILURE(err); // // Path describes an instance path, which is the only // time we need to do anything here // err = mk.ConvertToParentPath(TRUE); BREAK_ON_ERR_FAILURE(err); if (fUseTemplate) { // // Write values from template // err = mk.SetValue( MD_ALLOW_ANONYMOUS, m_fAllowAnonymous ); BREAK_ON_ERR_FAILURE(err); err = mk.SetValue( MD_ANONYMOUS_ONLY, m_fAnonymousOnly ); } else { // // Inheritance case: delete authentication // values // mk.DeleteValue(MD_ALLOW_ANONYMOUS); mk.DeleteValue(MD_ANONYMOUS_ONLY); } } } while(FALSE); } return err; } /* virtual */ void CFTPSecurityTemplate::GenerateSummary( IN BOOL fUseTemplate, IN LPCTSTR lpszServerName, IN LPCTSTR lpszService, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Generate text summary of what's in the security template, and is about to be applied to the given path. Arguments: BOOL fUseTemplates : TRUE if the source is from a template, FALSE if using inheritance. LPCTSTR lpszServerName : Server name LPCTSTR lpszService : Service name DWORD dwInstance : Instance LPCTSTR lpszParent : Parent path (or NULL) LPCTSTR lpszAlias : Alias name (or NULL) Return Value: None --*/ { CString strPath; CMetaKey::BuildMetaPath( strPath, lpszService, dwInstance, lpszParent, lpszAlias ); // // Authentication methods apply to instances only // if (CMetaKey::IsHomeDirectoryPath(strPath)) { // // Add private summary items // AddSummaryString(IDS_AUTHENTICATION_METHODS); // // Summarize Authentication Methods: // AddSummaryString( m_fAllowAnonymous ? IDS_AUTHENTICATION_ANONYMOUS : IDS_AUTHENTICATION_NO_ANONYMOUS, 1 ); if (m_fAllowAnonymous && m_fAnonymousOnly) { AddSummaryString(IDS_AUTHENTICATION_ANONYMOUS_ONLY, 1); } } // // Add base class summary // CIISSecurityTemplate::GenerateSummary( fUseTemplate, lpszServerName, lpszService, dwInstance, lpszParent, lpszAlias ); } CIISSecurityTemplate * AllocateSecurityTemplate( IN const CMetaKey * pKey, IN LPCTSTR lpszMDPath, IN BOOL fInherit ) /*++ Routine Description: Security template allocator function Arguments: IN const CMetaKey * pKey : Open key IN LPCTSTR lpszMDPath : Path IN BOOL fInherit : TRUE to inherit properties Return Value: Pointer to newly allocated security object --*/ { return new CFTPSecurityTemplate(pKey, lpszMDPath, fInherit); } extern "C" HRESULT APIENTRY ISMSecurityWizard( IN HANDLE hServer, IN DWORD dwInstance, IN LPCTSTR lpszParent, IN LPCTSTR lpszAlias ) /*++ Routine Description: Launch the security wizard Arguments: HANDLE hServer : Server handle DWORD dwInstance : Parent instance LPCTSTR lpszParent : Parent path LPCTSTR lpszAlias : Child to configure or NULL Return Value: HRESULT --*/ { AFX_MANAGE_STATE(::AfxGetStaticModuleState()); return COMDLL_ISMSecurityWizard( &AllocateSecurityTemplate, GetMetaKeyFromHandle(hServer), IDB_WIZ_LEFT_SEC, IDB_WIZ_HEAD_SEC, g_cszSvc, dwInstance, lpszParent, lpszAlias ); } // // End of ISM API Functions // // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< void InitializeDLL() /*++ Routine Description: Perform additional DLL initialisation as necessary Arguments: None Return Value: None --*/ { #ifdef _DEBUG afxMemDF |= checkAlwaysMemDF; #endif // _DEBUG #ifdef UNICODE TRACEEOLID("Loading UNICODE fscfg.dll"); #else TRACEEOLID("Loading ANSI fscfg.dll"); #endif UNICODE ::AfxEnableControlContainer(); #ifndef _COMSTATIC // // Initialize IISUI extension DLL // InitIISUIDll(); #endif // _COMSTATIC } // // Declare the one and only dll object // CConfigDll NEAR theApp; CConfigDll::CConfigDll( IN LPCTSTR pszAppName OPTIONAL ) /*++ Routine Description: Constructor for USRDLL Arguments: LPCTSTR pszAppName : Name of the app or NULL to load from resources Return Value: N/A --*/ : CWinApp(pszAppName), m_lpOldHelpPath(NULL) { } BOOL CConfigDll::InitInstance() /*++ Routine Description: Initialise current instance of the DLL Arguments: None Return Value: TRUE for successful initialisation, FALSE otherwise --*/ { BOOL bInit = CWinApp::InitInstance(); hInstance = ::AfxGetInstanceHandle(); ASSERT(hInstance); InitializeDLL(); try { // // Get the help path // m_lpOldHelpPath = m_pszHelpFilePath; ASSERT(m_pszHelpFilePath != NULL); CString strFile(_tcsrchr(m_pszHelpFilePath, _T('\\'))); CRMCRegKey rk(REG_KEY, SZ_PARAMETERS, KEY_READ); rk.QueryValue(SZ_HELPPATH, m_strHelpPath, EXPANSION_ON); m_strHelpPath += strFile; } catch(CException * e) { e->ReportError(); e->Delete(); } if (!m_strHelpPath.IsEmpty()) { m_pszHelpFilePath = m_strHelpPath; } return bInit; } int CConfigDll::ExitInstance() /*++ Routine Description: Clean up current instance Arguments: None Return Value: The application's exit code; 0 indicates no errors, and values greater than 0 indicate an error. --*/ { m_pszHelpFilePath = m_lpOldHelpPath; return CWinApp::ExitInstance(); } // // Message Map // BEGIN_MESSAGE_MAP(CConfigDll, CWinApp) //{{AFX_MSG_MAP(CConfigDll) //}}AFX_MSG_MAP // // Global Help Commands // ON_COMMAND(ID_HELP, CWinApp::OnHelp) ON_COMMAND(ID_CONTEXT_HELP, CWinApp::OnContextHelp) END_MESSAGE_MAP()