/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1991 **/ /**********************************************************************/ /* srvmcpl.cxx This is the main module for the Server Manager Control Panel Applet. It contains the "LibMain" and "CplApplet" functions. FILE HISTORY: KeithMo 22-Apr-1992 Templated from DavidHov's NCPACPL.CXX. KeithMo 02-Jun-1992 Added "Start the Server?" option. KeithMo 10-Jun-1992 Allow other process to start the server "behind our back". KeithMo 03-Aug-1992 Folded in the Service Manager (SVCMGR.CPL). */ #include extern "C" { #include #include } // // #defining this macro enables certain "unique" behaviour in the // SVCCNTL_DIALOG dialog. The "standard" dialog will bail-out when // the user stops the server service. If this macro is #defined, // then the dialog won't bail out (SVCCNTL_DIALOG does not require // that the server service be running). // #define MINI_SERVER_MANAGER_APPLET #define INCL_NET #define INCL_NETLIB #define INCL_NETSERVICE #define INCL_WINDOWS #define INCL_WINDOWS_GDI #define INCL_NETERRORS #define INCL_DOSERRORS #include #if defined(DEBUG) static const CHAR szFileName[] = __FILE__; #define _FILENAME_DEFINED_ONCE szFileName #endif #include #include #define INCL_BLT_WINDOW #define INCL_BLT_DIALOG #define INCL_BLT_CONTROL #define INCL_BLT_CLIENT #define INCL_BLT_MSGPOPUP #define INCL_BLT_EVENT #define INCL_BLT_MISC #define INCL_BLT_TIMER #define INCL_BLT_CC #include #include #include #include extern "C" { #include // Multimedia CPL defs #include #include #include #include } #include #include #include #include #include #include #include extern "C" { // // Control Panel Applet entry point. // LONG FAR PASCAL CPlApplet( HWND hwndCPl, WORD nMsg, LONG lParam1, LONG lparam2 ); // // DLL load/unload entry point. // BOOL DllMain( HINSTANCE hInstance, DWORD nReason, LPVOID pReserved ); // // Globals. // HINSTANCE _hCplInstance = NULL; } // extern "C" // // This is the "type" for an applet startup function. // typedef APIERR (* PCPL_APPLET_FUNC)( HWND hWnd ); // // We'll keep one of these structures for each applet in this DLL. // typedef struct _CPL_APPLET { int idIcon; int idName; int idInfo; int idHelpFile; DWORD dwHelpContext; LONG lData; PCPL_APPLET_FUNC pfnApplet; } CPL_APPLET; // // Forward reference prototypes. // APIERR RunSrvMgr( HWND hWnd ); APIERR RunSvcMgr( HWND hWnd ); APIERR RunDevMgr( HWND hWnd ); // // Our applet descriptors. // CPL_APPLET CplApplets[] = { { // Server applet IDI_SMCPA_ICON, IDS_SMCPA_NAME_STRING, IDS_SMCPA_INFO_STRING, IDS_SMCPA_HELPFILENAME, HC_SERVER_PROPERTIES, 0L, &RunSrvMgr }, { // Services applet IDI_SVCCPA_ICON, IDS_SVCCPA_NAME_STRING, IDS_SVCCPA_INFO_STRING, IDS_SMCPA_HELPFILENAME, HC_SVCCNTL_DIALOG, 0L, &RunSvcMgr }, { // Devices applet IDI_DEVCPA_ICON, IDS_DEVCPA_NAME_STRING, IDS_DEVCPA_INFO_STRING, IDS_SMCPA_HELPFILENAME, HC_DEVCNTL_DIALOG, 0L, &RunDevMgr } }; LONG cActiveApplets = sizeof(CplApplets) / sizeof(CplApplets[0]); /******************************************************************* NAME: GetLocalServerName SYNOPSIS: Returns the name of the current server (\\server). ENTRY: nlsServerName - Will receive the server name. RETURNS: APIERR - Any error encountered. HISTORY: KeithMo 22-Apr-1992 Created. ********************************************************************/ APIERR GetLocalServerName( NLS_STR & nlsServerName ) { APIERR err = nlsServerName.QueryError(); if( err == NERR_Success ) { err = nlsServerName.CopyFrom( SZ("\\\\") ); } SERVER_INFO_100 * psrvi100; if( err == NERR_Success ) { err = ::MNetServerGetInfo( NULL, 100, (BYTE **)&psrvi100 ); } if( err == NERR_Success ) { ALIAS_STR nlsRawName( (const TCHAR *)psrvi100->sv100_name ); err = nlsServerName.Append( nlsRawName ); ::MNetApiBufferFree( (BYTE **)&psrvi100 ); } return err; } // GetLocalServerName /******************************************************************* NAME: StartServer SYNOPSIS: Starts the server on the local machine. ENTRY: hWnd - "Owning" window handle. RETURNS: APIERR - Any error encountered. HISTORY: KeithMo 02-Jun-1992 Created. ********************************************************************/ APIERR StartServer( HWND hWnd ) { LOCATION loc( LOC_TYPE_LOCAL ); NLS_STR nlsDisplayName; APIERR err = loc.QueryError(); if( err == NERR_Success ) { err = nlsDisplayName.QueryError(); } if( err == NERR_Success ) { err = loc.QueryDisplayName( &nlsDisplayName ); } if( err == NERR_Success ) { GENERIC_SERVICE * psvc = new GENERIC_SERVICE( hWnd, NULL, nlsDisplayName, (const TCHAR *)SERVICE_SERVER ); err = ( psvc == NULL ) ? ERROR_NOT_ENOUGH_MEMORY : psvc->QueryError(); if( err == NERR_Success ) { err = psvc->Start(); } delete psvc; } return err; } // StartServer /******************************************************************* NAME: InitializeDll SYNOPSIS: Perform DLL initialiazation functions on a once-per-process basis. ENTRY: hInstance - Program instance of the caller. EXIT: If this is the first initialization request for this process, then all necessary BLT initializers have been invoked. RETURNS: BOOL - TRUE = Initialization OK. FALSE = Initialization failed. HISTORY: KeithMo 22-Apr-1992 Created. beng 04-Aug-1992 Changes to BLT::Init ********************************************************************/ BOOL InitializeDll( HINSTANCE hInstance ) { // // Save the instance handle. // _hCplInstance = hInstance; return TRUE; } // InitializeDll /******************************************************************* NAME: TerminateDll SYNOPSIS: Perform DLL termination functions on a once-per-process basis. EXIT: All necessary BLT terminators have been invoked. HISTORY: KeithMo 22-Apr-1992 Created. beng 04-Aug-1992 Changes to BLT::Term ********************************************************************/ VOID TerminateDll( VOID ) { // // Just in case we try to do anything goofy. // _hCplInstance = NULL; } // TerminateDll /******************************************************************* NAME: InitializeAllApplets SYNOPSIS: Called before applet runs. ENTRY: hWnd - Window handle of parent window. RETURNS: BOOL - TRUE = Applet should be installed. FALSE = Applet cannot be installed. HISTORY: KeithMo 22-Apr-1992 Created. KeithMo 10-Jun-1992 Moved "guts" to RunSrvMgr. JonN 30-Aug-1994 Added lParam parameters to CPL_INIT, CPL_TERM JonN 22-Sep-1995 Only called when applet runs ********************************************************************/ BOOL InitializeAllApplets( HWND hWnd, LONG lParam1, LONG lParam2 ) { TRACEEOL( "SRVMGR.CPL: InitializeAllApplets enter" ); // // Initialize all of the NetUI goodies. // APIERR err = BLT::Init( _hCplInstance, IDRSRC_APP_BASE, IDRSRC_APP_LAST, IDS_UI_APP_BASE, IDS_UI_SRVMGR_LAST ); TRACEEOL( "SRVMGR.CPL: InitializeAllApplets BLT::Init returns " << err ); if( err == NERR_Success ) { TRACEEOL( "SRVMGR.CPL: InitializeAllApplets BLT::_MASTER_TIMER::Init next" ); err = BLT_MASTER_TIMER::Init(); TRACEEOL( "SRVMGR.CPL: InitializeAllApplets BLT::_MASTER_TIMER::Init returns " << err ); if( err != NERR_Success ) { // // BLT initialized OK, but BLT_MASTER_TIMER // failed. So, before we bag-out, we must // deinitialize BLT. // BLT::Term( _hCplInstance ); } } if( err == NERR_Success ) { err = BLT::RegisterHelpFile( _hCplInstance, IDS_SMCPA_HELPFILENAME, HC_UI_SRVMGR_BASE, HC_UI_SRVMGR_LAST ); if( err != NERR_Success ) { // // This is the only place where we can safely // invoke MsgPopup, since we *know* that all of // the BLT goodies were initialized properly. // ::MsgPopup( hWnd, err ); } } TRACEEOL( "SRVMGR.CPL: InitializeAllApplets exit" ); return err == NERR_Success; } // InitializeAllApplets /******************************************************************* NAME: TerminateAllApplets SYNOPSIS: Called after applet runs. ENTRY: hWnd - Window handle of parent window. HISTORY: KeithMo 22-Apr-1992 Created. JonN 30-Aug-1994 Added lParam parameters to CPL_INIT, CPL_TERM JonN 22-Sep-1995 Only called when applet runs ********************************************************************/ VOID TerminateAllApplets( HWND hWnd, LONG lParam1, LONG lParam2 ) { UNREFERENCED(hWnd); TRACEEOL( "SRVMGR.CPL: TerminateAllApplets enter" ); // // Kill the NetUI goodies. // TRACEEOL( "SRVMGR.CPL: TerminateAllApplets BLT::_MASTER_TIMER::Term next" ); BLT_MASTER_TIMER::Term(); TRACEEOL( "SRVMGR.CPL: TerminateAllApplets BLT::_MASTER_TIMER::Term complete" ); BLT::Term( _hCplInstance ); TRACEEOL( "SRVMGR.CPL: TerminateAllApplets exit" ); } // TerminateAllApplets /******************************************************************* NAME: RunSrvMgr SYNOPSIS: Invoke the main dialog of the Server Manager Control Panel Applet. ENTRY: hWnd - Window handle of parent window. RETURNS: APIERR HISTORY: KeithMo 22-Apr-1992 Created. KeithMo 10-Jun-1992 Robustified server startup code. ********************************************************************/ APIERR RunSrvMgr( HWND hWnd ) { #ifdef DEBUG_SMCPA DebugBreak(); #endif // DEBUG_SMCPA POPUP::SetCaption( IDS_CAPTION_PROPERTIES ); // // Let's see if the server is running. // NLS_STR nlsServerName; BOOL fServerRunning = FALSE; // until proven otherwise APIERR err = GetLocalServerName( nlsServerName ); if( err == NERR_Success ) { fServerRunning = TRUE; } else if( err == NERR_ServerNotStarted ) { // // The server is not started. Let's see if the user // wants us to start it. // if( MsgPopup( hWnd, IDS_START_SERVER_NOW, MPSEV_WARNING, MP_YESNO, MP_YES ) != IDYES ) { // // The user doesn't want to play right now. // err = NERR_Success; } else { // // Start the server & re-retrieve the server name. // err = StartServer( hWnd ); if( err == NERR_Success ) { err = GetLocalServerName( nlsServerName ); } fServerRunning = ( err == NERR_Success ); } } if( ( err == NERR_Success ) && fServerRunning ) { // // Invoke the Main Property Sheet. // BOOL fDummy; SERVER_PROPERTIES * pDlg = new SERVER_PROPERTIES( hWnd, nlsServerName, &fDummy ); if (pDlg == NULL) { err = ERROR_NOT_ENOUGH_MEMORY; } else if ( (err = pDlg->QueryError()) == NERR_Success) { err = pDlg->Process(); } delete pDlg; } if( err != NERR_Success ) { ::MsgPopup( hWnd, err ); } POPUP::ResetCaption(); return err; } // RunSrvMgr /******************************************************************* NAME: RunSvcMgr SYNOPSIS: Invoke the main dialog of the Service Manager Control Panel Applet. ENTRY: hWnd - Window handle of parent window. RETURNS: APIERR HISTORY: KeithMo 06-Jul-1992 Created. ********************************************************************/ APIERR RunSvcMgr( HWND hWnd ) { POPUP::SetCaption( IDS_CAPTION_SVCCNTL ); LOCATION loc( LOC_TYPE_LOCAL ); NLS_STR nlsDisplayName; APIERR err = loc.QueryError(); if( err == NERR_Success ) { err = nlsDisplayName.QueryError(); } if( err == NERR_Success ) { err = loc.QueryDisplayName( &nlsDisplayName ); } if( err == NERR_Success ) { SVCCNTL_DIALOG * pDlg = new SVCCNTL_DIALOG( hWnd, NULL, nlsDisplayName, SV_TYPE_NT ); err = ( pDlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY : pDlg->Process(); delete pDlg; } if( err != NERR_Success ) { ::MsgPopup( hWnd, err ); } POPUP::ResetCaption(); return err; } // RunSvcMgr /******************************************************************* NAME: RunDevMgr SYNOPSIS: Invoke the main dialog of the Device Manager Control Panel Applet. ENTRY: hWnd - Window handle of parent window. RETURNS: APIERR HISTORY: KeithMo 22-Dec-1992 Created. ********************************************************************/ APIERR RunDevMgr( HWND hWnd ) { POPUP::SetCaption( IDS_CAPTION_DEVCNTL ); LOCATION loc( LOC_TYPE_LOCAL ); NLS_STR nlsDisplayName; APIERR err = loc.QueryError(); if( err == NERR_Success ) { err = nlsDisplayName.QueryError(); } if( err == NERR_Success ) { err = loc.QueryDisplayName( &nlsDisplayName ); } if( err == NERR_Success ) { DEVCNTL_DIALOG * pDlg = new DEVCNTL_DIALOG( hWnd, NULL, nlsDisplayName, SV_TYPE_NT ); err = ( pDlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY : pDlg->Process(); delete pDlg; } if( err != NERR_Success ) { ::MsgPopup( hWnd, err ); } POPUP::ResetCaption(); return err; } // RunDevMgr BOOL strLoad( INT idString, WCHAR * pszBuffer, INT cchBuffer ) { int result = ::LoadString( ::_hCplInstance, idString, pszBuffer, cchBuffer ); return ( result > 0 ) && ( result < cchBuffer ); } // strLoad /******************************************************************* NAME: CPlApplet SYNOPSIS: Exported function to start the Server Manager Control Panel Applet. ENTRY: hwndCPl - Window handle of parent. nMsg - CPL user message (see CPL.H in WINDOWS\SHELL\CONTROL\H). lParam1 - Message-specific pointer. lParam2 - Message-specific pointer. RETURNS: LONG HISTORY: KeithMo 22-Apr-1992 Created. JonN 30-Aug-1994 Added lParam parameters to CPL_INIT, CPL_TERM ********************************************************************/ LONG FAR PASCAL CPlApplet( HWND hwndCPl, WORD nMsg, LONG lParam1, LONG lParam2 ) { LPCPLINFO pCplInfo; LPNEWCPLINFO pNewInfo; LONG nResult = 0; switch( nMsg ) { case CPL_INIT: // // This message is sent to indicate that CPlApplet() was found. // // lParam1 is not used, but we pass it anyway. // // lParam2 is -1 iff the DLL will be used only to confirm the // number of applets. // // // Return TRUE if applet should be installed, FALSE otherwise. // return TRUE; case CPL_GETCOUNT: // // This message is set to determine the number of applets contained // in this DLL. // // lParam1 and lParam2 are not used. // // Return the number of applets contained in this DLL. // return cActiveApplets; case CPL_INQUIRE: // // This message is sent once per applet to retrieve information // about each applet. // // lParam1 is the applet number to register. // // lParam2 is a pointer to a CPLINFO structure. The CPLINFO // structure's idIcon, idName, idInfo, and lData fields should // be initialized as appropriate for the applet. // // There is no return value. // pCplInfo = (LPCPLINFO)lParam2; if( lParam1 < cActiveApplets ) { CPL_APPLET * pApplet = &CplApplets[lParam1]; pCplInfo->idIcon = pApplet->idIcon; pCplInfo->idName = pApplet->idName; pCplInfo->idInfo = pApplet->idInfo; pCplInfo->lData = pApplet->lData; } break; case CPL_SELECT: // // This message is sent when the applet's icon has been // selected. // // lParam1 is the applet number that was selected. // // lParam2 is the applet's lData value. // // There is no return value. // break; case CPL_DBLCLK: // // This message is sent when the applet's icon has been // double-clicked. This message should initiate the // applet's dialog box. // // lParam1 is the applet number that was selected. // // lParam2 is the applet's lData value. // // There is no return value. // if( lParam1 < cActiveApplets ) { if ( (LONG)InitializeAllApplets( hwndCPl, lParam1, lParam2 ) ) { (CplApplets[lParam1].pfnApplet)( hwndCPl ); TerminateAllApplets( hwndCPl, lParam1, lParam2 ); } else { ASSERT( FALSE ); } } break; case CPL_STOP: // // This message is sent once for each applet when the // control panel is shutting down. This message should // initiate applet specific cleanup. // // lParam1 is the applet number being stopped. // // lParam2 is the applet's lData value. // // There is no return value. // break; case CPL_EXIT: // // This message is sent just before the control panel calls // FreeLibrary. This message should initiate non applet // specific cleanup. // // lParam1 is not used, but we pass it anyway. // // lParam2 is -1 iff the DLL was used only to confirm the // number of applets. // // There is no return value. // break; case CPL_NEWINQUIRE: // // This message is basically the same as CPL_INQUIRE, except // lParam2 points to a NEWCPLINFO structure. This message will // be sent *before* CPL_INQUIRE. If the applet returns a non // zero value, then CPL_INQUIRE will not be sent. // // lParam1 is the applet number to register. // // lParam2 is a pointer to a NEWCPLINFO structure. // // Return TRUE this message was handled, otherwise return FALSE. // pNewInfo = (LPNEWCPLINFO)lParam2; if( lParam1 < cActiveApplets ) { CPL_APPLET * pApplet = &CplApplets[lParam1]; pNewInfo->dwSize = sizeof(*pNewInfo); pNewInfo->dwFlags = 0; pNewInfo->dwHelpContext = pApplet->dwHelpContext; pNewInfo->lData = pApplet->lData; pNewInfo->hIcon = ::LoadIcon( ::_hCplInstance, MAKEINTRESOURCE( pApplet->idIcon ) ); if( ( pNewInfo->hIcon != NULL ) && strLoad( pApplet->idName, pNewInfo->szName, sizeof(pNewInfo->szName) ) && strLoad( pApplet->idInfo, pNewInfo->szInfo, sizeof(pNewInfo->szInfo) ) && strLoad( pApplet->idHelpFile, pNewInfo->szHelpFile, sizeof(pNewInfo->szHelpFile) ) ) { nResult = TRUE; } } break; default: // // Who knows. Ignore it. // break; } return nResult; } // CPlApplet /******************************************************************* NAME: DllMain SYNOPSIS: This DLL entry point is called when processes & threads are initialized and terminated, or upon calls to LoadLibrary() and FreeLibrary(). ENTRY: hInstance - A handle to the DLL. nReason - Indicates why the DLL entry point is being called. pReserved - Reserved. RETURNS: BOOL - TRUE = DLL init was successful. FALSE = DLL init failed. NOTES: The return value is only relevant during processing of DLL_PROCESS_ATTACH notifications. HISTORY: KeithMo 22-Apr-1992 Created. ********************************************************************/ BOOL DllMain( HINSTANCE hInstance, DWORD nReason, LPVOID pReserved ) { BOOL fResult = TRUE; UNREFERENCED(pReserved); switch( nReason ) { case DLL_PROCESS_ATTACH: // // This notification indicates that the DLL is attaching to // the address space of the current process. This is either // the result of the process starting up, or after a call to // LoadLibrary(). The DLL should us this as a hook to // initialize any instance data or to allocate a TLS index. // // This call is made in the context of the thread that // caused the process address space to change. // DisableThreadLibraryCalls(hInstance); fResult = InitializeDll( hInstance ); break; case DLL_PROCESS_DETACH: // // This notification indicates that the calling process is // detaching the DLL from its address space. This is either // due to a clean process exit or from a FreeLibrary() call. // The DLL should use this opportunity to return any TLS // indexes allocated and to free any thread local data. // // Note that this notification is posted only once per // process. Individual threads do not invoke the // DLL_THREAD_DETACH notification. // TerminateDll(); break; default: // // Who knows? Just ignore it. // break; } return fResult; } // DllMain