|
|
//
// User or remote site invokes applet
//
#include "precomp.h"
#include "appldr.h"
#include "cuserdta.hpp"
#include "csap.h"
#define count_of(array) (sizeof(array) / sizeof(array[0]))
static CRITICAL_SECTION g_csAppLdrInfo; static AppLoaderInfo g_aAppLoaderInfo[APPLET_LAST]; static BOOL g_fAppLdrInitialized = FALSE;
const static CHAR *g_fnAppletDLL[APPLET_LAST] = {"nmwb.dll", "nmft.dll", "nmchat.dll"};
// Chat session key
static const GUID guidNM2Chat = { 0x340f3a60, 0x7067, 0x11d0, { 0xa0, 0x41, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } }; #define CHAT_KEY_SIZE 25
extern struct Key CHAT_APP_PROTO_KEY;
// NetMeeting/UI, T.120
T120Error WINAPI T120_LoadApplet ( APPLET_ID nAppId, BOOL flocal, T120ConfID nConfId, BOOL fNoUI, LPSTR pszCmdLine ) { T120Error rc = T120_NO_ERROR; LPFN_CREATE_APPLET_LOADER_INTERFACE pfnCreateInterface;
if (nAppId >= APPLET_LAST) { ERROR_OUT(("T120_LoadApplet: invalid applet ID=%u", nAppId)); return T120_INVALID_PARAMETER; }
//
// Check policies. Launch & auto-launch not allowed if corp has
// disabled applet.
//
RegEntry rePol(POLICIES_KEY, HKEY_CURRENT_USER); switch (nAppId) { case APPLET_ID_WB: if (rePol.GetNumber(REGVAL_POL_NO_NEWWHITEBOARD, DEFAULT_POL_NO_NEWWHITEBOARD)) { WARNING_OUT(("New WB disabled by policy, not starting")); return GCC_NO_SUCH_APPLICATION; } break;
case APPLET_ID_FT: if (rePol.GetNumber(REGVAL_POL_NO_FILETRANSFER_SEND, DEFAULT_POL_NO_FILETRANSFER_SEND) && rePol.GetNumber(REGVAL_POL_NO_FILETRANSFER_RECEIVE, DEFAULT_POL_NO_FILETRANSFER_RECEIVE)) { WARNING_OUT(("FT disabled by policy, not starting")); return GCC_NO_SUCH_APPLICATION; } break;
case APPLET_ID_CHAT: if (rePol.GetNumber(REGVAL_POL_NO_CHAT, DEFAULT_POL_NO_CHAT)) { WARNING_OUT(("Chat disabled by policy, not starting")); return GCC_NO_SUCH_APPLICATION; } break; }
::EnterCriticalSection(&g_csAppLdrInfo);
if (NULL != g_aAppLoaderInfo[nAppId].hLibApplet) { switch (g_aAppLoaderInfo[nAppId].eStatus) { case APPLET_CLOSING: case APPLET_WORK_THREAD_EXITED: WARNING_OUT(("T120_LoadApplet: applet is closing or work thread exited")); rc = GCC_APPLET_EXITING; break; default: if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletInvoke(flocal, nConfId, pszCmdLine)) { g_aAppLoaderInfo[nAppId].cLoads++; } // rc = T120_NO_ERROR;
break; } goto MyExit; }
g_aAppLoaderInfo[nAppId].hLibApplet = ::LoadLibrary(g_fnAppletDLL[nAppId]); if (NULL != g_aAppLoaderInfo[nAppId].hLibApplet) { pfnCreateInterface = (LPFN_CREATE_APPLET_LOADER_INTERFACE) ::GetProcAddress(g_aAppLoaderInfo[nAppId].hLibApplet, CREATE_APPLET_LOADER_INTERFACE); if (NULL != pfnCreateInterface) { //g_aAppLoaderInfo[nAppId].pIAppLoader = (IAppletLoader*)(*pfnCreateInterface)();
(*pfnCreateInterface)(&g_aAppLoaderInfo[nAppId].pIAppLoader); if (NULL != g_aAppLoaderInfo[nAppId].pIAppLoader) { if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletStartup(fNoUI)) { if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletInvoke(flocal, nConfId, pszCmdLine)) { g_aAppLoaderInfo[nAppId].cLoads++; // rc = T120_NO_ERROR;
goto MyExit; } else { ERROR_OUT(("T120_LoadApplet: cannot invoke applet(%s), flocal=%u, nConfID=%u", g_fnAppletDLL[nAppId], flocal, nConfId)); } } else { ERROR_OUT(("T120_LoadApplet: cannot start applet(%s)", g_fnAppletDLL[nAppId])); }
g_aAppLoaderInfo[nAppId].pIAppLoader->ReleaseInterface(); g_aAppLoaderInfo[nAppId].pIAppLoader = NULL; } else { ERROR_OUT(("T120_LoadApplet: Entry function of %s failed.\n", g_fnAppletDLL[nAppId])); } } else { WARNING_OUT(("T120_LoadApplet: Can't find entry point of %s.\n", g_fnAppletDLL[nAppId])); }
::FreeLibrary(g_aAppLoaderInfo[nAppId].hLibApplet); g_aAppLoaderInfo[nAppId].hLibApplet = NULL; } else { ERROR_OUT(("T120_LoadApplet: Can't open DLL %s, err %d.\n", g_fnAppletDLL[nAppId], GetLastError())); }
rc = GCC_NO_SUCH_APPLICATION; MyExit:
::LeaveCriticalSection(&g_csAppLdrInfo); return rc; }
// NetMeeting/UI shutdown
T120Error WINAPI T120_CloseApplet(APPLET_ID nAppId, BOOL fNowRegardlessRefCount, BOOL fSync, DWORD dwTimeout) { if (nAppId< APPLET_LAST) { if (g_fAppLdrInitialized) { ::EnterCriticalSection(&g_csAppLdrInfo); IAppletLoader *pIAppLdr = g_aAppLoaderInfo[nAppId].pIAppLoader; if (NULL != pIAppLdr) { ASSERT(g_aAppLoaderInfo[nAppId].cLoads > 0); g_aAppLoaderInfo[nAppId].cLoads --; if ((! fNowRegardlessRefCount) && g_aAppLoaderInfo[nAppId].cLoads > 0) { pIAppLdr = NULL; // do not free the library
} } ::LeaveCriticalSection(&g_csAppLdrInfo);
if (NULL != pIAppLdr) { // AppletCleanup() must be outside of the critical section
// because applet worker thread will call AppletStatus() before
// exiting its worker thread.
switch (pIAppLdr->AppletCleanup(5000)) // always synchronous shutdown
{ case APPLDR_NO_ERROR : // we are closing this applet
g_aAppLoaderInfo[nAppId].eStatus = APPLET_CLOSING;
// it is safe to unload the library
::FreeLibrary(g_aAppLoaderInfo[nAppId].hLibApplet); g_aAppLoaderInfo[nAppId].hLibApplet = NULL; break;
case APPLDR_CANCEL_EXIT: //
// The app didn't want to be unloaded
//
::EnterCriticalSection(&g_csAppLdrInfo); g_aAppLoaderInfo[nAppId].cLoads++; g_aAppLoaderInfo[nAppId].pIAppLoader = pIAppLdr; ::LeaveCriticalSection(&g_csAppLdrInfo); return GCC_APPLET_CANCEL_EXIT;
default: break; } } } return T120_NO_ERROR; } else { ERROR_OUT(("T120_CloseApplet: invalid applet ID=%u", nAppId)); } return T120_INVALID_PARAMETER; }
T120Error WINAPI T120_QueryApplet(APPLET_ID nAppId, APPLET_QUERY_ID eQueryId) { if (nAppId< APPLET_LAST) { if (g_fAppLdrInitialized) { ::EnterCriticalSection(&g_csAppLdrInfo); IAppletLoader *pIAppLdr = g_aAppLoaderInfo[nAppId].pIAppLoader; ::LeaveCriticalSection(&g_csAppLdrInfo); if (NULL != pIAppLdr) { if (APPLET_QUERY_NM2xNODE == eQueryId) { pIAppLdr->OnNM2xNodeJoin(); } else if (APPLDR_CANCEL_EXIT == pIAppLdr->AppletQuery(eQueryId)) { return GCC_APPLET_CANCEL_EXIT; } } } return T120_NO_ERROR; } else { ERROR_OUT(("T120_CloseApplet: invalid applet ID=%u", nAppId)); } return T120_INVALID_PARAMETER; }
// Applet itself
T120Error WINAPI T120_AppletStatus(APPLET_ID nAppId, APPLET_STATUS status) { if (nAppId < APPLET_LAST) { if (g_fAppLdrInitialized) { ::EnterCriticalSection(&g_csAppLdrInfo);
g_aAppLoaderInfo[nAppId].eStatus = status;
switch (status) { case APPLET_WORK_THREAD_EXITED: if (NULL != g_aAppLoaderInfo[nAppId].pIAppLoader) { g_aAppLoaderInfo[nAppId].pIAppLoader->ReleaseInterface(); g_aAppLoaderInfo[nAppId].pIAppLoader = NULL; } break; case APPLET_LIBRARY_FREED: // clean up this entry
::ZeroMemory(&g_aAppLoaderInfo[nAppId], sizeof(g_aAppLoaderInfo[0])); break; }
::LeaveCriticalSection(&g_csAppLdrInfo); } return T120_NO_ERROR; } else { ERROR_OUT(("T120_AppletStatus: invalid applet ID=%u", nAppId)); } return T120_INVALID_PARAMETER; }
T120Error AppLdr_Initialize(void) { ASSERT(count_of(g_aAppLoaderInfo) == APPLET_LAST);
::InitializeCriticalSection(&g_csAppLdrInfo); // clean all entries
::ZeroMemory(g_aAppLoaderInfo, sizeof(g_aAppLoaderInfo));
::CreateH221AppKeyFromGuid(CHAT_APP_PROTO_KEY.u.h221_non_standard.value, (GUID *)&guidNM2Chat ); CHAT_APP_PROTO_KEY.choice = h221_non_standard_chosen; CHAT_APP_PROTO_KEY.u.h221_non_standard.length = CHAT_KEY_SIZE;
g_fAppLdrInitialized = TRUE; return T120_NO_ERROR; }
void AppLdr_Shutdown(void) { g_fAppLdrInitialized = FALSE;
for (ULONG i = 0; i < APPLET_LAST; i++) { if (NULL != g_aAppLoaderInfo[i].pIAppLoader) { APPLDR_RESULT rc = g_aAppLoaderInfo[i].pIAppLoader->AppletCleanup(5000); // always synchronous shutdown
ASSERT(APPLDR_NO_ERROR == rc);
// it is safe to unload the library
::FreeLibrary(g_aAppLoaderInfo[i].hLibApplet); g_aAppLoaderInfo[i].hLibApplet = NULL; } }
// clean all entries
::ZeroMemory(g_aAppLoaderInfo, sizeof(g_aAppLoaderInfo));
::DeleteCriticalSection(&g_csAppLdrInfo); }
|