windows-nt/Source/XPSP1/NT/enduser/netmeeting/t120/mst120/appldr.cpp
2020-09-26 16:20:57 +08:00

337 lines
8.8 KiB
C++

//
// 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);
}