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.

486 lines
12 KiB

  1. #include "precomp.h"
  2. DEBUG_FILEZONE(ZONE_T120_SAP);
  3. /*
  4. * sap.cpp
  5. *
  6. * Copyright (c) 1995 by DataBeam Corporation, Lexington, KY
  7. *
  8. * Abstract:
  9. * This is the implementation file for the class CBaseSap. This class is an
  10. * abstract base class for objects that act as Service Access Points (SAPs)
  11. * to external applications or the node controller.
  12. *
  13. * This class has two main responsibilities. First, it handles many of the
  14. * administrative tasks that are common to all types of SAPs. These
  15. * include handling command target registration responsibilities and
  16. * managing the message queue. It also handles all of the primitives that
  17. * are common between the Control SAP (CControlSAP class) and Application
  18. * SAPs (CAppSap class).
  19. *
  20. * Protected Member Functions:
  21. * AddToMessageQueue
  22. * This routine is used to place messages into the queue of messages
  23. * to be sent to applications or the node controller.
  24. * CreateDataToBeDeleted
  25. * This routine is used to create a structure which holds message data
  26. * to be delivered to applications or the node controller.
  27. * CopyDataToGCCMessage
  28. * This routine is used to fill in the messages to be delivered to
  29. * applications or the node controller with the necessary data.
  30. * FreeCallbackMessage
  31. * This is a virtual function which is used to free up any data which
  32. * was allocated in order to send a callback message. This function
  33. * is overloaded in CControlSAP to free messages which were sent to the
  34. * node controller. It is overloaded in CAppSap to free messages sent
  35. * to applications.
  36. *
  37. * Caveats:
  38. * None.
  39. *
  40. * Author:
  41. * blp
  42. */
  43. #include "ms_util.h"
  44. #include "sap.h"
  45. #include "conf.h"
  46. #include "gcontrol.h"
  47. #include "ernccm.hpp"
  48. /*
  49. * The node controller SAP handle is always 0.
  50. */
  51. #define NODE_CONTROLLER_SAP_HANDLE 0
  52. LRESULT CALLBACK SapNotifyWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  53. extern HINSTANCE g_hDllInst;
  54. extern char g_szGCCWndClassName[24];
  55. /*
  56. * CBaseSap::CBaseSap()
  57. *
  58. * Public Function Description
  59. * This is the CBaseSap constructor. The hash list used to hold command
  60. * target objects is initialized by this constructor.
  61. */
  62. #ifdef SHIP_BUILD
  63. CBaseSap::CBaseSap(void)
  64. :
  65. CRefCount(),
  66. #else
  67. CBaseSap::CBaseSap(DWORD dwStampID)
  68. :
  69. CRefCount(dwStampID),
  70. #endif
  71. m_nReqTag(GCC_INVALID_TAG)
  72. {
  73. //
  74. // LONCHANC: We have to create the hidden window first
  75. // because we may need to post PermissionToEnrollIndication
  76. // to this window for Chat and File Transfer.
  77. //
  78. ASSERT(g_szGCCWndClassName[0] == 'G' &&
  79. g_szGCCWndClassName[1] == 'C' &&
  80. g_szGCCWndClassName[2] == 'C');
  81. //
  82. // Create a hidden window for confirm and indication.
  83. // CAppSap or CControlSAP should check for the value of m_hwndNotify.
  84. //
  85. m_hwndNotify = CreateWindowA(g_szGCCWndClassName, NULL, WS_POPUP,
  86. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  87. NULL, NULL, g_hDllInst, NULL);
  88. ASSERT(NULL != m_hwndNotify);
  89. }
  90. CBaseSap::~CBaseSap(void)
  91. {
  92. //
  93. // Destroy window and unregister window class
  94. //
  95. if (NULL != m_hwndNotify)
  96. {
  97. ::DestroyWindow(m_hwndNotify);
  98. }
  99. }
  100. BOOL CBaseSap::IsThisNodeTopProvider(GCCConfID nConfID)
  101. {
  102. BOOL fRet;
  103. CConf *pConf;
  104. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
  105. {
  106. fRet = pConf->IsConfTopProvider();
  107. }
  108. else
  109. {
  110. fRet = FALSE;
  111. }
  112. return fRet;
  113. }
  114. GCCNodeID CBaseSap::GetTopProvider(GCCConfID nConfID)
  115. {
  116. GCCNodeID uRet;
  117. CConf *pConf;
  118. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
  119. {
  120. uRet = pConf->GetTopProvider();
  121. }
  122. else
  123. {
  124. uRet = 0;
  125. }
  126. return uRet;
  127. }
  128. /*
  129. * ConfRosterInquire()
  130. *
  131. * Public Function Description
  132. * This routine is used to retrieve the conference roster. This function
  133. * just passes this request to the controller via an owner callback. The
  134. * conference roster is delivered to the requesting command target object
  135. * in a Conference Roster inquire confirm.
  136. */
  137. GCCError CBaseSap::
  138. ConfRosterInquire(GCCConfID nConfID, GCCAppSapMsgEx **ppMsgEx)
  139. {
  140. GCCError rc;
  141. CConf *pConf;
  142. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
  143. {
  144. rc = pConf->ConfRosterInquireRequest(this, ppMsgEx);
  145. if (GCC_NO_ERROR != rc)
  146. {
  147. ERROR_OUT(("CBaseSap::ConfRosterInquire: can't inquire app roster, rc=%u", (UINT) rc));
  148. // goto MyExit;
  149. }
  150. }
  151. else
  152. {
  153. WARNING_OUT(("CBaseSap::ConfRosterInquire: invalid conf ID=%u", (UINT) nConfID));
  154. rc = GCC_INVALID_CONFERENCE;
  155. }
  156. return rc;
  157. }
  158. /*
  159. * GCCError AppRosterInquire()
  160. *
  161. * Public Function Description
  162. * This routine is used to retrieve a list of application rosters. This
  163. * function just passes this request to the controller via an owner
  164. * callback. This list is delivered to the requesting SAP through an
  165. * Application Roster inquire confirm message.
  166. */
  167. GCCError CBaseSap::
  168. AppRosterInquire(GCCConfID nConfID,
  169. GCCSessionKey *pSessionKey,
  170. GCCAppSapMsgEx **ppMsgEx) // nonzero for sync operation
  171. {
  172. GCCError rc;
  173. CConf *pConf;
  174. if (NULL == (pConf = g_pGCCController->GetConfObject(nConfID)))
  175. {
  176. WARNING_OUT(("CBaseSap::AppRosterInquire: invalid conf ID=%u", (UINT) nConfID));
  177. rc = GCC_INVALID_CONFERENCE;
  178. }
  179. else
  180. {
  181. CAppRosterMsg *pAppRosterMsg;
  182. rc = pConf->AppRosterInquireRequest(pSessionKey, &pAppRosterMsg);
  183. if (GCC_NO_ERROR == rc)
  184. {
  185. AppRosterInquireConfirm(nConfID, pAppRosterMsg, GCC_RESULT_SUCCESSFUL, ppMsgEx);
  186. pAppRosterMsg->Release();
  187. }
  188. else
  189. {
  190. ERROR_OUT(("CBaseSap::AppRosterInquire: can't inquire app roster, rc=%u", (UINT) rc));
  191. }
  192. }
  193. return rc;
  194. }
  195. /*
  196. * ConductorInquire()
  197. *
  198. * Public Function Description
  199. * This routine is called in order to retrieve conductorship information.
  200. * The conductorship information is returned in the confirm.
  201. *
  202. */
  203. GCCError CBaseSap::ConductorInquire(GCCConfID nConfID)
  204. {
  205. GCCError rc;
  206. CConf *pConf;
  207. /*
  208. ** Make sure the conference exists in the internal list before forwarding
  209. ** the call on to the conference object.
  210. */
  211. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
  212. {
  213. rc = pConf->ConductorInquireRequest(this);
  214. }
  215. else
  216. {
  217. rc = GCC_INVALID_CONFERENCE;
  218. }
  219. return rc;
  220. }
  221. /*
  222. * AppInvoke()
  223. *
  224. * Public Function Description
  225. * This routine is called in order to invoke other applications at remote
  226. * nodes. The request is passed on to the appropriate Conference objects.
  227. */
  228. GCCError CBaseSap::
  229. AppInvoke(GCCConfID nConfID,
  230. GCCAppProtEntityList *pApeList,
  231. GCCSimpleNodeList *pNodeList,
  232. GCCRequestTag *pnReqTag)
  233. {
  234. GCCError rc = GCC_NO_ERROR;
  235. CInvokeSpecifierListContainer *invoke_list;
  236. UINT i;
  237. CConf *pConf;
  238. DebugEntry(CBaseSap::AppInvoke);
  239. if (NULL == pApeList || NULL == pNodeList || NULL == pnReqTag)
  240. {
  241. rc = GCC_INVALID_PARAMETER;
  242. goto MyExit;
  243. }
  244. *pnReqTag = GenerateRequestTag();
  245. if (NULL != (pConf = g_pGCCController->GetConfObject(nConfID)))
  246. {
  247. if (pApeList->cApes != 0)
  248. {
  249. /*
  250. ** Create an object which is used to hold the list of application
  251. ** invoke specifiers.
  252. */
  253. DBG_SAVE_FILE_LINE
  254. invoke_list = new CInvokeSpecifierListContainer(
  255. pApeList->cApes,
  256. pApeList->apApes,
  257. &rc);
  258. if ((invoke_list != NULL) && (rc == GCC_NO_ERROR))
  259. {
  260. /*
  261. ** Here we must check the destination node list for invalid
  262. ** node IDs.
  263. */
  264. for (i = 0; i < pNodeList->cNodes; i++)
  265. {
  266. if (pNodeList->aNodeIDs[i] < MINIMUM_USER_ID_VALUE)
  267. {
  268. rc = GCC_INVALID_MCS_USER_ID;
  269. goto MyExit;
  270. }
  271. }
  272. /*
  273. ** If no error has occurred, send the request on to the
  274. ** command target (conference) object.
  275. */
  276. rc = pConf->AppInvokeRequest(invoke_list, pNodeList, this, *pnReqTag);
  277. /*
  278. ** Free here instead of delete in case the object
  279. ** must persist.
  280. */
  281. invoke_list->Release();
  282. }
  283. else if (invoke_list == NULL)
  284. {
  285. ERROR_OUT(("CBaseSap::AppInvoke: Error creating new AppInvokeSpecList"));
  286. rc = GCC_ALLOCATION_FAILURE;
  287. // goto MyExit;
  288. }
  289. else
  290. {
  291. invoke_list->Release();
  292. }
  293. }
  294. else
  295. {
  296. rc = GCC_BAD_NUMBER_OF_APES;
  297. // goto MyExit;
  298. }
  299. }
  300. else
  301. {
  302. rc = GCC_INVALID_CONFERENCE;
  303. // goto MyExit;
  304. }
  305. MyExit:
  306. DebugExitINT(CBaseSap::AppInvoke, rc);
  307. return rc;
  308. }
  309. GCCRequestTag CBaseSap::GenerateRequestTag(void)
  310. {
  311. GCCRequestTag nNewReqTag;
  312. ASSERT(sizeof(GCCRequestTag) == sizeof(LONG));
  313. nNewReqTag = ++m_nReqTag;
  314. if (GCC_INVALID_TAG == nNewReqTag)
  315. {
  316. nNewReqTag = ++m_nReqTag;
  317. }
  318. // we only take the lower word
  319. return (nNewReqTag & 0x0000FFFFL);
  320. }
  321. //
  322. // SapNotifyWndProc() is used to notify the sap clients (app in app sap,
  323. // node controller in control sap) in their respective thread.
  324. // The window handle is in CSap::m_hwndNotify.
  325. //
  326. LRESULT CALLBACK
  327. SapNotifyWndProc
  328. (
  329. HWND hwnd,
  330. UINT uMsg,
  331. WPARAM wParam,
  332. LPARAM lParam
  333. )
  334. {
  335. LRESULT wnd_rc = 0;
  336. if (CSAPMSG_BASE <= uMsg && uMsg < CSAPCONFIRM_BASE + MSG_RANGE)
  337. {
  338. ASSERT(CSAPMSG_BASE + MSG_RANGE == CSAPCONFIRM_BASE);
  339. if (uMsg < CSAPMSG_BASE + MSG_RANGE)
  340. {
  341. if (((CControlSAP *) lParam) == g_pControlSap)
  342. {
  343. g_pControlSap->NotifyProc((GCCCtrlSapMsgEx *) wParam);
  344. }
  345. else
  346. {
  347. WARNING_OUT(("SapNotifyWndProc: invalid control sap, uMsg=%u, lParam=0x%p, g_pControlSap=0x%p",
  348. uMsg, lParam, g_pControlSap));
  349. }
  350. }
  351. else
  352. {
  353. ASSERT(CSAPCONFIRM_BASE <= uMsg && uMsg < CSAPCONFIRM_BASE + MSG_RANGE);
  354. if (NULL != g_pControlSap)
  355. {
  356. g_pControlSap->WndMsgHandler(uMsg, wParam, lParam);
  357. }
  358. else
  359. {
  360. WARNING_OUT(("SapNotifyWndProc: invalid control sap, uMsg=%u, wParam=0x%x, lParam=0x%x",
  361. uMsg, (UINT) wParam, (UINT) lParam));
  362. }
  363. }
  364. }
  365. else
  366. if (ASAPMSG_BASE <= uMsg && uMsg < ASAPMSG_BASE + MSG_RANGE)
  367. {
  368. ASSERT(uMsg == ASAPMSG_BASE + (UINT) ((GCCAppSapMsgEx *) wParam)->Msg.eMsgType);
  369. ((CAppSap *) lParam)->NotifyProc((GCCAppSapMsgEx *) wParam);
  370. }
  371. else
  372. if (CONFMSG_BASE <= uMsg && uMsg < CONFMSG_BASE + MSG_RANGE)
  373. {
  374. ::EnterCriticalSection(&g_csGCCProvider);
  375. if (NULL != ((CConf *) lParam))
  376. {
  377. ((CConf *) lParam)->WndMsgHandler(uMsg);
  378. }
  379. else
  380. {
  381. ERROR_OUT(("SapNotifyWndProc: invalid conf object, uMsg=%u, lParam=0x%x",
  382. uMsg, (UINT) lParam));
  383. }
  384. ::LeaveCriticalSection(&g_csGCCProvider);
  385. }
  386. else
  387. if (GCTRLMSG_BASE <= uMsg && uMsg < GCTRLMSG_BASE + MSG_RANGE)
  388. {
  389. ::EnterCriticalSection(&g_csGCCProvider);
  390. if (((GCCController *) lParam) == g_pGCCController)
  391. {
  392. g_pGCCController->WndMsgHandler(uMsg);
  393. }
  394. else
  395. {
  396. WARNING_OUT(("SapNotifyWndProc: invalid gcc controller, uMsg=%u, lParam=0x%p, g_pGCCController=0x%p",
  397. uMsg, lParam, g_pGCCController));
  398. }
  399. ::LeaveCriticalSection(&g_csGCCProvider);
  400. }
  401. else
  402. if (MCTRLMSG_BASE <= uMsg && uMsg < MCTRLMSG_BASE + MSG_RANGE)
  403. {
  404. void CALLBACK MCSCallBackProcedure (UINT, LPARAM, PVoid);
  405. MCSCallBackProcedure (uMsg - MCTRLMSG_BASE, lParam, NULL);
  406. /*
  407. * If the msg contains user data, we need to unlock the
  408. * memory with it.
  409. */
  410. UnlockMemory ((PMemory) wParam);
  411. }
  412. else
  413. if (NCMSG_BASE <= uMsg && uMsg < NCMSG_BASE + MSG_RANGE)
  414. {
  415. if (((DCRNCConferenceManager *) wParam) == g_pNCConfMgr)
  416. {
  417. g_pNCConfMgr->WndMsgHandler(uMsg, lParam);
  418. }
  419. else
  420. {
  421. WARNING_OUT(("SapNotifyWndProc: invalid NC ConfMgr, uMsg=%u, lParam=0x%p, g_pNCConfMgr=0x%p",
  422. uMsg, lParam, g_pNCConfMgr));
  423. }
  424. }
  425. else
  426. {
  427. switch (uMsg)
  428. {
  429. case WM_CLOSE:
  430. DestroyWindow(hwnd);
  431. break;
  432. default:
  433. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  434. }
  435. }
  436. return wnd_rc;
  437. }
  438.