Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

336 lines
8.8 KiB

  1. //
  2. // User or remote site invokes applet
  3. //
  4. #include "precomp.h"
  5. #include "appldr.h"
  6. #include "cuserdta.hpp"
  7. #include "csap.h"
  8. #define count_of(array) (sizeof(array) / sizeof(array[0]))
  9. static CRITICAL_SECTION g_csAppLdrInfo;
  10. static AppLoaderInfo g_aAppLoaderInfo[APPLET_LAST];
  11. static BOOL g_fAppLdrInitialized = FALSE;
  12. const static CHAR *g_fnAppletDLL[APPLET_LAST] = {"nmwb.dll", "nmft.dll", "nmchat.dll"};
  13. // Chat session key
  14. static const GUID guidNM2Chat = { 0x340f3a60, 0x7067, 0x11d0,
  15. { 0xa0, 0x41, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0 } };
  16. #define CHAT_KEY_SIZE 25
  17. extern struct Key CHAT_APP_PROTO_KEY;
  18. // NetMeeting/UI, T.120
  19. T120Error WINAPI T120_LoadApplet
  20. (
  21. APPLET_ID nAppId,
  22. BOOL flocal,
  23. T120ConfID nConfId,
  24. BOOL fNoUI,
  25. LPSTR pszCmdLine
  26. )
  27. {
  28. T120Error rc = T120_NO_ERROR;
  29. LPFN_CREATE_APPLET_LOADER_INTERFACE pfnCreateInterface;
  30. if (nAppId >= APPLET_LAST)
  31. {
  32. ERROR_OUT(("T120_LoadApplet: invalid applet ID=%u", nAppId));
  33. return T120_INVALID_PARAMETER;
  34. }
  35. //
  36. // Check policies. Launch & auto-launch not allowed if corp has
  37. // disabled applet.
  38. //
  39. RegEntry rePol(POLICIES_KEY, HKEY_CURRENT_USER);
  40. switch (nAppId)
  41. {
  42. case APPLET_ID_WB:
  43. if (rePol.GetNumber(REGVAL_POL_NO_NEWWHITEBOARD, DEFAULT_POL_NO_NEWWHITEBOARD))
  44. {
  45. WARNING_OUT(("New WB disabled by policy, not starting"));
  46. return GCC_NO_SUCH_APPLICATION;
  47. }
  48. break;
  49. case APPLET_ID_FT:
  50. if (rePol.GetNumber(REGVAL_POL_NO_FILETRANSFER_SEND, DEFAULT_POL_NO_FILETRANSFER_SEND) &&
  51. rePol.GetNumber(REGVAL_POL_NO_FILETRANSFER_RECEIVE, DEFAULT_POL_NO_FILETRANSFER_RECEIVE))
  52. {
  53. WARNING_OUT(("FT disabled by policy, not starting"));
  54. return GCC_NO_SUCH_APPLICATION;
  55. }
  56. break;
  57. case APPLET_ID_CHAT:
  58. if (rePol.GetNumber(REGVAL_POL_NO_CHAT, DEFAULT_POL_NO_CHAT))
  59. {
  60. WARNING_OUT(("Chat disabled by policy, not starting"));
  61. return GCC_NO_SUCH_APPLICATION;
  62. }
  63. break;
  64. }
  65. ::EnterCriticalSection(&g_csAppLdrInfo);
  66. if (NULL != g_aAppLoaderInfo[nAppId].hLibApplet)
  67. {
  68. switch (g_aAppLoaderInfo[nAppId].eStatus)
  69. {
  70. case APPLET_CLOSING:
  71. case APPLET_WORK_THREAD_EXITED:
  72. WARNING_OUT(("T120_LoadApplet: applet is closing or work thread exited"));
  73. rc = GCC_APPLET_EXITING;
  74. break;
  75. default:
  76. if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletInvoke(flocal, nConfId, pszCmdLine))
  77. {
  78. g_aAppLoaderInfo[nAppId].cLoads++;
  79. }
  80. // rc = T120_NO_ERROR;
  81. break;
  82. }
  83. goto MyExit;
  84. }
  85. g_aAppLoaderInfo[nAppId].hLibApplet = ::LoadLibrary(g_fnAppletDLL[nAppId]);
  86. if (NULL != g_aAppLoaderInfo[nAppId].hLibApplet)
  87. {
  88. pfnCreateInterface = (LPFN_CREATE_APPLET_LOADER_INTERFACE)
  89. ::GetProcAddress(g_aAppLoaderInfo[nAppId].hLibApplet,
  90. CREATE_APPLET_LOADER_INTERFACE);
  91. if (NULL != pfnCreateInterface)
  92. {
  93. //g_aAppLoaderInfo[nAppId].pIAppLoader = (IAppletLoader*)(*pfnCreateInterface)();
  94. (*pfnCreateInterface)(&g_aAppLoaderInfo[nAppId].pIAppLoader);
  95. if (NULL != g_aAppLoaderInfo[nAppId].pIAppLoader)
  96. {
  97. if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletStartup(fNoUI))
  98. {
  99. if (APPLDR_NO_ERROR == g_aAppLoaderInfo[nAppId].pIAppLoader->AppletInvoke(flocal, nConfId, pszCmdLine))
  100. {
  101. g_aAppLoaderInfo[nAppId].cLoads++;
  102. // rc = T120_NO_ERROR;
  103. goto MyExit;
  104. }
  105. else
  106. {
  107. ERROR_OUT(("T120_LoadApplet: cannot invoke applet(%s), flocal=%u, nConfID=%u",
  108. g_fnAppletDLL[nAppId], flocal, nConfId));
  109. }
  110. }
  111. else
  112. {
  113. ERROR_OUT(("T120_LoadApplet: cannot start applet(%s)", g_fnAppletDLL[nAppId]));
  114. }
  115. g_aAppLoaderInfo[nAppId].pIAppLoader->ReleaseInterface();
  116. g_aAppLoaderInfo[nAppId].pIAppLoader = NULL;
  117. }
  118. else
  119. {
  120. ERROR_OUT(("T120_LoadApplet: Entry function of %s failed.\n", g_fnAppletDLL[nAppId]));
  121. }
  122. }
  123. else
  124. {
  125. WARNING_OUT(("T120_LoadApplet: Can't find entry point of %s.\n", g_fnAppletDLL[nAppId]));
  126. }
  127. ::FreeLibrary(g_aAppLoaderInfo[nAppId].hLibApplet);
  128. g_aAppLoaderInfo[nAppId].hLibApplet = NULL;
  129. }
  130. else
  131. {
  132. ERROR_OUT(("T120_LoadApplet: Can't open DLL %s, err %d.\n", g_fnAppletDLL[nAppId], GetLastError()));
  133. }
  134. rc = GCC_NO_SUCH_APPLICATION;
  135. MyExit:
  136. ::LeaveCriticalSection(&g_csAppLdrInfo);
  137. return rc;
  138. }
  139. // NetMeeting/UI shutdown
  140. T120Error WINAPI
  141. T120_CloseApplet(APPLET_ID nAppId, BOOL fNowRegardlessRefCount, BOOL fSync, DWORD dwTimeout)
  142. {
  143. if (nAppId< APPLET_LAST)
  144. {
  145. if (g_fAppLdrInitialized)
  146. {
  147. ::EnterCriticalSection(&g_csAppLdrInfo);
  148. IAppletLoader *pIAppLdr = g_aAppLoaderInfo[nAppId].pIAppLoader;
  149. if (NULL != pIAppLdr)
  150. {
  151. ASSERT(g_aAppLoaderInfo[nAppId].cLoads > 0);
  152. g_aAppLoaderInfo[nAppId].cLoads --;
  153. if ((! fNowRegardlessRefCount) && g_aAppLoaderInfo[nAppId].cLoads > 0)
  154. {
  155. pIAppLdr = NULL; // do not free the library
  156. }
  157. }
  158. ::LeaveCriticalSection(&g_csAppLdrInfo);
  159. if (NULL != pIAppLdr)
  160. {
  161. // AppletCleanup() must be outside of the critical section
  162. // because applet worker thread will call AppletStatus() before
  163. // exiting its worker thread.
  164. switch (pIAppLdr->AppletCleanup(5000)) // always synchronous shutdown
  165. {
  166. case APPLDR_NO_ERROR :
  167. // we are closing this applet
  168. g_aAppLoaderInfo[nAppId].eStatus = APPLET_CLOSING;
  169. // it is safe to unload the library
  170. ::FreeLibrary(g_aAppLoaderInfo[nAppId].hLibApplet);
  171. g_aAppLoaderInfo[nAppId].hLibApplet = NULL;
  172. break;
  173. case APPLDR_CANCEL_EXIT:
  174. //
  175. // The app didn't want to be unloaded
  176. //
  177. ::EnterCriticalSection(&g_csAppLdrInfo);
  178. g_aAppLoaderInfo[nAppId].cLoads++;
  179. g_aAppLoaderInfo[nAppId].pIAppLoader = pIAppLdr;
  180. ::LeaveCriticalSection(&g_csAppLdrInfo);
  181. return GCC_APPLET_CANCEL_EXIT;
  182. default:
  183. break;
  184. }
  185. }
  186. }
  187. return T120_NO_ERROR;
  188. }
  189. else
  190. {
  191. ERROR_OUT(("T120_CloseApplet: invalid applet ID=%u", nAppId));
  192. }
  193. return T120_INVALID_PARAMETER;
  194. }
  195. T120Error WINAPI
  196. T120_QueryApplet(APPLET_ID nAppId, APPLET_QUERY_ID eQueryId)
  197. {
  198. if (nAppId< APPLET_LAST)
  199. {
  200. if (g_fAppLdrInitialized)
  201. {
  202. ::EnterCriticalSection(&g_csAppLdrInfo);
  203. IAppletLoader *pIAppLdr = g_aAppLoaderInfo[nAppId].pIAppLoader;
  204. ::LeaveCriticalSection(&g_csAppLdrInfo);
  205. if (NULL != pIAppLdr)
  206. {
  207. if (APPLET_QUERY_NM2xNODE == eQueryId)
  208. {
  209. pIAppLdr->OnNM2xNodeJoin();
  210. }
  211. else if (APPLDR_CANCEL_EXIT == pIAppLdr->AppletQuery(eQueryId))
  212. {
  213. return GCC_APPLET_CANCEL_EXIT;
  214. }
  215. }
  216. }
  217. return T120_NO_ERROR;
  218. }
  219. else
  220. {
  221. ERROR_OUT(("T120_CloseApplet: invalid applet ID=%u", nAppId));
  222. }
  223. return T120_INVALID_PARAMETER;
  224. }
  225. // Applet itself
  226. T120Error WINAPI
  227. T120_AppletStatus(APPLET_ID nAppId, APPLET_STATUS status)
  228. {
  229. if (nAppId < APPLET_LAST)
  230. {
  231. if (g_fAppLdrInitialized)
  232. {
  233. ::EnterCriticalSection(&g_csAppLdrInfo);
  234. g_aAppLoaderInfo[nAppId].eStatus = status;
  235. switch (status)
  236. {
  237. case APPLET_WORK_THREAD_EXITED:
  238. if (NULL != g_aAppLoaderInfo[nAppId].pIAppLoader)
  239. {
  240. g_aAppLoaderInfo[nAppId].pIAppLoader->ReleaseInterface();
  241. g_aAppLoaderInfo[nAppId].pIAppLoader = NULL;
  242. }
  243. break;
  244. case APPLET_LIBRARY_FREED:
  245. // clean up this entry
  246. ::ZeroMemory(&g_aAppLoaderInfo[nAppId], sizeof(g_aAppLoaderInfo[0]));
  247. break;
  248. }
  249. ::LeaveCriticalSection(&g_csAppLdrInfo);
  250. }
  251. return T120_NO_ERROR;
  252. }
  253. else
  254. {
  255. ERROR_OUT(("T120_AppletStatus: invalid applet ID=%u", nAppId));
  256. }
  257. return T120_INVALID_PARAMETER;
  258. }
  259. T120Error AppLdr_Initialize(void)
  260. {
  261. ASSERT(count_of(g_aAppLoaderInfo) == APPLET_LAST);
  262. ::InitializeCriticalSection(&g_csAppLdrInfo);
  263. // clean all entries
  264. ::ZeroMemory(g_aAppLoaderInfo, sizeof(g_aAppLoaderInfo));
  265. ::CreateH221AppKeyFromGuid(CHAT_APP_PROTO_KEY.u.h221_non_standard.value,
  266. (GUID *)&guidNM2Chat );
  267. CHAT_APP_PROTO_KEY.choice = h221_non_standard_chosen;
  268. CHAT_APP_PROTO_KEY.u.h221_non_standard.length = CHAT_KEY_SIZE;
  269. g_fAppLdrInitialized = TRUE;
  270. return T120_NO_ERROR;
  271. }
  272. void AppLdr_Shutdown(void)
  273. {
  274. g_fAppLdrInitialized = FALSE;
  275. for (ULONG i = 0; i < APPLET_LAST; i++)
  276. {
  277. if (NULL != g_aAppLoaderInfo[i].pIAppLoader)
  278. {
  279. APPLDR_RESULT rc = g_aAppLoaderInfo[i].pIAppLoader->AppletCleanup(5000); // always synchronous shutdown
  280. ASSERT(APPLDR_NO_ERROR == rc);
  281. // it is safe to unload the library
  282. ::FreeLibrary(g_aAppLoaderInfo[i].hLibApplet);
  283. g_aAppLoaderInfo[i].hLibApplet = NULL;
  284. }
  285. }
  286. // clean all entries
  287. ::ZeroMemory(g_aAppLoaderInfo, sizeof(g_aAppLoaderInfo));
  288. ::DeleteCriticalSection(&g_csAppLdrInfo);
  289. }