Leaked source code of windows server 2003
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.

1166 lines
30 KiB

  1. #include "precomp.h"
  2. //
  3. // Application Loader
  4. //
  5. #define MLZ_FILE_ZONE ZONE_OM
  6. //
  7. // ALP_Init()
  8. //
  9. BOOL ALP_Init(BOOL * pfCleanup)
  10. {
  11. BOOL fInit = FALSE;
  12. DebugEntry(ALP_Init);
  13. UT_Lock(UTLOCK_AL);
  14. if (g_putAL || g_palPrimary)
  15. {
  16. *pfCleanup = FALSE;
  17. ERROR_OUT(("Can't start AL primary task; already running"));
  18. DC_QUIT;
  19. }
  20. else
  21. {
  22. //
  23. // From this point on, there is cleanup to do.
  24. //
  25. *pfCleanup = TRUE;
  26. }
  27. //
  28. // Register AL task
  29. //
  30. if (!UT_InitTask(UTTASK_AL, &g_putAL))
  31. {
  32. ERROR_OUT(("Failed to start AL task"));
  33. DC_QUIT;
  34. }
  35. //
  36. // Allocate PRIMARY data
  37. //
  38. g_palPrimary = (PAL_PRIMARY)UT_MallocRefCount(sizeof(AL_PRIMARY), TRUE);
  39. if (!g_palPrimary)
  40. {
  41. ERROR_OUT(("Failed to allocate AL memory block"));
  42. DC_QUIT;
  43. }
  44. SET_STAMP(g_palPrimary, ALPRIMARY);
  45. g_palPrimary->putTask = g_putAL;
  46. //
  47. // Register an exit and event proc
  48. //
  49. UT_RegisterExit(g_putAL, ALPExitProc, g_palPrimary);
  50. g_palPrimary->exitProcRegistered = TRUE;
  51. UT_RegisterEvent(g_putAL, ALPEventProc, g_palPrimary, UT_PRIORITY_NORMAL);
  52. g_palPrimary->eventProcRegistered = TRUE;
  53. if (!CMS_Register(g_putAL, CMTASK_AL, &g_palPrimary->pcmClient))
  54. {
  55. ERROR_OUT(("Could not register ALP with CMS"));
  56. DC_QUIT;
  57. }
  58. //
  59. // Register as an OBMAN Secondary task (call OM_Register())
  60. //
  61. if (OM_Register(g_putAL, OMCLI_AL, &g_palPrimary->pomClient) != 0)
  62. {
  63. ERROR_OUT(( "Could not register ALP with OBMAN"));
  64. DC_QUIT;
  65. }
  66. fInit = TRUE;
  67. DC_EXIT_POINT:
  68. UT_Unlock(UTLOCK_AL);
  69. DebugExitBOOL(ALP_Init, fInit);
  70. return(fInit);
  71. }
  72. //
  73. // ALP_Term()
  74. //
  75. void ALP_Term(void)
  76. {
  77. DebugEntry(ALP_Term);
  78. UT_Lock(UTLOCK_AL);
  79. if (g_palPrimary)
  80. {
  81. ValidateALP(g_palPrimary);
  82. ValidateUTClient(g_putAL);
  83. //
  84. // Deregister from Call Manager (if registered call CM_Deregister())
  85. //
  86. if (g_palPrimary->pcmClient)
  87. {
  88. CMS_Deregister(&g_palPrimary->pcmClient);
  89. }
  90. //
  91. // Deregister from OBMAN (if registered call OM_Deregister())
  92. //
  93. if (g_palPrimary->pomClient)
  94. {
  95. OM_Deregister(&g_palPrimary->pomClient);
  96. }
  97. //
  98. // Do our own task termination
  99. //
  100. ALPExitProc(g_palPrimary);
  101. }
  102. UT_TermTask(&g_putAL);
  103. UT_Unlock(UTLOCK_AL);
  104. DebugExitVOID(ALP_Term);
  105. }
  106. //
  107. // ALPExitProc()
  108. //
  109. void CALLBACK ALPExitProc(LPVOID data)
  110. {
  111. PAL_PRIMARY palPrimary = (PAL_PRIMARY)data;
  112. UINT i;
  113. DebugEntry(ALPExitProc);
  114. UT_Lock(UTLOCK_AL);
  115. ValidateALP(palPrimary);
  116. ASSERT(palPrimary == g_palPrimary);
  117. //
  118. // Deregister event procedure
  119. //
  120. if (palPrimary->eventProcRegistered)
  121. {
  122. UT_DeregisterEvent(g_putAL, ALPEventProc, palPrimary);
  123. palPrimary->eventProcRegistered = FALSE;
  124. }
  125. //
  126. // Deregister exit procedure (if registered call UT_DeregisterExit()
  127. //
  128. if (palPrimary->exitProcRegistered)
  129. {
  130. UT_DeregisterExit(g_putAL, ALPExitProc, palPrimary);
  131. palPrimary->exitProcRegistered = FALSE;
  132. }
  133. //
  134. // Free memory
  135. //
  136. UT_FreeRefCount((void**)&g_palPrimary, TRUE);
  137. UT_Unlock(UTLOCK_AL);
  138. DebugExitVOID(ALPExitProc);
  139. }
  140. //
  141. // ALPEventProc()
  142. //
  143. BOOL CALLBACK ALPEventProc
  144. (
  145. LPVOID data,
  146. UINT event,
  147. UINT_PTR param1,
  148. UINT_PTR param2
  149. )
  150. {
  151. PAL_PRIMARY palPrimary = (PAL_PRIMARY)data;
  152. BOOL processed = FALSE;
  153. DebugEntry(ALPEventProc);
  154. UT_Lock(UTLOCK_AL);
  155. ValidateALP(palPrimary);
  156. switch (event)
  157. {
  158. case AL_INT_RETRY_NEW_CALL:
  159. // Retry new call
  160. ALNewCall(palPrimary, (UINT)param1, (UINT)param2);
  161. processed = TRUE;
  162. break;
  163. case CMS_NEW_CALL:
  164. // First try new call
  165. ALNewCall(palPrimary, AL_NEW_CALL_RETRY_COUNT, (UINT)param2);
  166. break;
  167. case CMS_END_CALL:
  168. ALEndCall(palPrimary, (UINT)param2);
  169. break;
  170. case OM_WSGROUP_REGISTER_CON:
  171. ALWorksetRegisterCon(palPrimary,
  172. ((POM_EVENT_DATA32)&param2)->correlator,
  173. ((POM_EVENT_DATA32)&param2)->result,
  174. ((POM_EVENT_DATA16)&param1)->hWSGroup);
  175. break;
  176. case OM_WORKSET_OPEN_CON:
  177. if ((((POM_EVENT_DATA16)&param1)->hWSGroup ==
  178. palPrimary->alWSGroupHandle) &&
  179. (((POM_EVENT_DATA16)&param1)->worksetID == 0) &&
  180. (((POM_EVENT_DATA32)&param2)->result == 0) )
  181. {
  182. TRACE_OUT(( "OM_WORKSET_OPEN_CON OK for AL workset 0"));
  183. palPrimary->alWorksetOpen = TRUE;
  184. if (palPrimary->alWBRegPend)
  185. ALLocalLoadResult(palPrimary, (palPrimary->alWBRegSuccess != FALSE));
  186. }
  187. break;
  188. case OM_WORKSET_NEW_IND:
  189. if (ALWorksetNewInd(palPrimary,
  190. ((POM_EVENT_DATA16)&param1)->hWSGroup,
  191. ((POM_EVENT_DATA16)&param1)->worksetID))
  192. {
  193. //
  194. // The event was for a workset the Application Loader was
  195. // expecting - don't pass it on
  196. //
  197. processed = TRUE;
  198. }
  199. break;
  200. case OM_OBJECT_ADD_IND:
  201. //
  202. // See if it is a new workset group in an OBMAN control workset
  203. // (call ALNewWorksetGroup())
  204. //
  205. // If it isn't then see if it is a load result in the
  206. // Application Loader result workset (call ALRemoteLoadResult())
  207. //
  208. //
  209. TRACE_OUT(( "OM_OBJECT_ADD_IND"));
  210. if (ALNewWorksetGroup(palPrimary, ((POM_EVENT_DATA16)&param1)->hWSGroup,
  211. (POM_OBJECT)param2))
  212. {
  213. //
  214. // OBJECT_ADD was for an OBMAN control workset object Don't
  215. // pass event on to other handlers.
  216. //
  217. TRACE_OUT(("OBJECT_ADD was for OBMAN workset group"));
  218. processed = TRUE;
  219. }
  220. else
  221. {
  222. if (ALRemoteLoadResult(palPrimary, ((POM_EVENT_DATA16)&param1)->hWSGroup,
  223. (POM_OBJECT)param2))
  224. {
  225. //
  226. // OBJECT_ADD was for an AL remote result workset
  227. // object Don't pass event on to other handlers.
  228. //
  229. TRACE_OUT(("OBJECT_ADD was for AL workset group"));
  230. processed = TRUE;
  231. }
  232. }
  233. break;
  234. case OM_WORKSET_CLEAR_IND:
  235. TRACE_OUT(( "OM_WORKSET_CLEAR_IND"));
  236. if (palPrimary->alWSGroupHandle ==
  237. ((POM_EVENT_DATA16)&param1)->hWSGroup)
  238. {
  239. TRACE_OUT(( "Confirming OM_WORKSET_CLEAR_IND event"));
  240. OM_WorksetClearConfirm(palPrimary->pomClient,
  241. ((POM_EVENT_DATA16)&param1)->hWSGroup,
  242. ((POM_EVENT_DATA16)&param1)->worksetID);
  243. }
  244. break;
  245. case OM_OBJECT_DELETE_IND:
  246. if (palPrimary->alWSGroupHandle ==
  247. ((POM_EVENT_DATA16)&param1)->hWSGroup)
  248. {
  249. OM_ObjectDeleteConfirm(palPrimary->pomClient,
  250. ((POM_EVENT_DATA16)&param1)->hWSGroup,
  251. ((POM_EVENT_DATA16)&param1)->worksetID,
  252. (POM_OBJECT)param2);
  253. }
  254. break;
  255. case OM_OBJECT_REPLACE_IND:
  256. if (palPrimary->alWSGroupHandle ==
  257. ((POM_EVENT_DATA16)&param1)->hWSGroup)
  258. {
  259. OM_ObjectReplaceConfirm(palPrimary->pomClient,
  260. ((POM_EVENT_DATA16)&param1)->hWSGroup,
  261. ((POM_EVENT_DATA16)&param1)->worksetID,
  262. (POM_OBJECT)param2);
  263. }
  264. break;
  265. case OM_OBJECT_UPDATE_IND:
  266. if (palPrimary->alWSGroupHandle ==
  267. ((POM_EVENT_DATA16)&param1)->hWSGroup)
  268. {
  269. OM_ObjectUpdateConfirm(palPrimary->pomClient,
  270. ((POM_EVENT_DATA16)&param1)->hWSGroup,
  271. ((POM_EVENT_DATA16)&param1)->worksetID,
  272. (POM_OBJECT)param2);
  273. }
  274. break;
  275. case AL_INT_STARTSTOP_WB:
  276. ALStartStopWB(palPrimary, (LPCTSTR)param2);
  277. processed = TRUE;
  278. break;
  279. default:
  280. break;
  281. }
  282. UT_Unlock(UTLOCK_AL);
  283. DebugExitBOOL(ALPEventProc, processed);
  284. return(processed);
  285. }
  286. //
  287. // ALNewCall()
  288. //
  289. void ALNewCall
  290. (
  291. PAL_PRIMARY palPrimary,
  292. UINT retryCount,
  293. UINT callID
  294. )
  295. {
  296. UINT rc;
  297. OM_WSGROUP_HANDLE hWSGroup;
  298. CM_STATUS status;
  299. DebugEntry(ALNewCall);
  300. ValidateALP(palPrimary);
  301. //
  302. // Can we handle a new call?
  303. //
  304. if (palPrimary->inCall)
  305. {
  306. WARNING_OUT(("No more room for calls"));
  307. DC_QUIT;
  308. }
  309. //
  310. // Is ObMan/AppLoader/OldWB disabled for this call?
  311. //
  312. CMS_GetStatus(&status);
  313. if (!(status.attendeePermissions & NM_PERMIT_USEOLDWBATALL))
  314. {
  315. WARNING_OUT(("Joining Meeting with no OLDWB AL at all"));
  316. DC_QUIT;
  317. }
  318. //
  319. // Register as a secondary with the OBMAN workset group for the new
  320. // call:
  321. //
  322. rc = OM_WSGroupRegisterS(palPrimary->pomClient,
  323. callID,
  324. OMFP_OM,
  325. OMWSG_OM,
  326. &hWSGroup);
  327. if ((rc == OM_RC_NO_PRIMARY) && (retryCount > 0))
  328. {
  329. //
  330. // Although a call has started, ObMan hasn't joined it yet - we
  331. // must have got the NEW_CALL event before it did. So, we'll try
  332. // again after a short delay.
  333. //
  334. // Note that we cannot post the CMS_NEW_CALL event itself back to
  335. // ourselves, because it is bad programming practice to post other
  336. // people's events (e.g. CM could register a hidden handler which
  337. // performs some non-repeatable operation on receipt of one of its
  338. // events).
  339. //
  340. // Therefore, we post an internal AL event which we treat in the
  341. // same way.
  342. //
  343. // To avoid retry forever, we use the first parameter of the event
  344. // as a countdown retry count. The first time this function is
  345. // called (on receipt of a genuine CMS_NEW_CALL) the count is set
  346. // to the default. Each time we post a delay event, we decrement
  347. // the value passed in and post that as param1. When it hits zero,
  348. // we give up.
  349. //
  350. TRACE_OUT(("Got OM_RC_NO_PRIMARY from 2nd reg for call %d, %d retries left",
  351. callID, retryCount));
  352. UT_PostEvent(palPrimary->putTask,
  353. palPrimary->putTask,
  354. AL_RETRY_DELAY,
  355. AL_INT_RETRY_NEW_CALL,
  356. --retryCount,
  357. callID);
  358. DC_QUIT;
  359. }
  360. if (rc) // includes NO_PRIMARY when retry count == 0
  361. {
  362. //
  363. // If we get any other error (or NO_PRIMARY when the retry count is
  364. // zero, it's more serious:
  365. //
  366. // lonchanc: was ERROR_OUT (happened when hang up immediately place a call)
  367. WARNING_OUT(( "Error registering with obman WSG, rc = %#x", rc));
  368. DC_QUIT;
  369. }
  370. TRACE_OUT(("Registered as OBMANCONTROL secondary in call %d", callID));
  371. //
  372. // Record the call ID and the correlator in the call information in
  373. // primary task memory
  374. //
  375. palPrimary->inCall = TRUE;
  376. palPrimary->omWSGroupHandle = hWSGroup;
  377. palPrimary->callID = callID;
  378. palPrimary->alWSGroupHandle = 0;
  379. //
  380. // Now we want to open workset #0 in the OBMAN workset group, but it
  381. // mightn't exist yet. As soon as it is created, we will get a
  382. // WORKSET_NEW event, so we wait (asynchronously) for that.
  383. //
  384. //
  385. // Now that we have opened the OBMAN workset group, we shall register
  386. // with the application loader workset group
  387. //
  388. if (OM_WSGroupRegisterPReq(palPrimary->pomClient, callID,
  389. OMFP_AL, OMWSG_AL, &palPrimary->omWSGCorrelator) != 0)
  390. {
  391. ERROR_OUT(( "Could not register AL workset group"));
  392. }
  393. DC_EXIT_POINT:
  394. DebugExitVOID(ALNewCall);
  395. }
  396. //
  397. // ALEndCall()
  398. //
  399. void ALEndCall
  400. (
  401. PAL_PRIMARY palPrimary,
  402. UINT callID
  403. )
  404. {
  405. UINT i;
  406. DebugEntry(ALEndCall);
  407. ValidateALP(palPrimary);
  408. //
  409. // See if we have information for this call
  410. //
  411. if (!palPrimary->inCall ||
  412. (palPrimary->callID != callID))
  413. {
  414. //
  415. // Not an error - we may not have joined the call yet.
  416. //
  417. TRACE_OUT(("Unexpected call %d", callID));
  418. DC_QUIT;
  419. }
  420. //
  421. // Deregister from the OBMAN workset group for the call (if registered
  422. // call OM_WSGroupDeregister())
  423. //
  424. if (palPrimary->omWSGroupHandle)
  425. {
  426. OM_WSGroupDeregister(palPrimary->pomClient,
  427. &palPrimary->omWSGroupHandle);
  428. ASSERT(palPrimary->omWSGroupHandle == 0);
  429. }
  430. //
  431. // Deregister from the AL workset group for the call (if registered
  432. // call OM_WSGroupDeregister())
  433. //
  434. if (palPrimary->alWSGroupHandle)
  435. {
  436. OM_WSGroupDeregister(palPrimary->pomClient,
  437. &palPrimary->alWSGroupHandle);
  438. ASSERT(palPrimary->alWSGroupHandle == 0);
  439. }
  440. //
  441. // Clear out all our call state variables
  442. //
  443. palPrimary->inCall = FALSE;
  444. palPrimary->omWSGCorrelator = 0;
  445. palPrimary->callID = 0;
  446. palPrimary->omWSCorrelator = 0;
  447. palPrimary->omUID = 0;
  448. palPrimary->alWorksetOpen = FALSE;
  449. palPrimary->alWBRegPend = FALSE;
  450. DC_EXIT_POINT:
  451. DebugExitVOID(ALEndCall);
  452. }
  453. //
  454. // ALWorksetNewInd()
  455. //
  456. BOOL ALWorksetNewInd
  457. (
  458. PAL_PRIMARY palPrimary,
  459. OM_WSGROUP_HANDLE hWSGroup,
  460. OM_WORKSET_ID worksetID
  461. )
  462. {
  463. BOOL fHandled = FALSE;
  464. DebugEntry(ALWorksetNewInd);
  465. ValidateALP(palPrimary);
  466. if (worksetID != 0)
  467. {
  468. TRACE_OUT(( "Workset ID is %u, ignoring and passing event on",
  469. worksetID));
  470. DC_QUIT;
  471. }
  472. if (!palPrimary->inCall ||
  473. (palPrimary->omWSGroupHandle != hWSGroup))
  474. {
  475. TRACE_OUT(("Got WORKSET_NEW_IND for WSG %d, but not in call", hWSGroup));
  476. DC_QUIT;
  477. }
  478. //
  479. // Now open the workset (secondary Open, so synchronous):
  480. //
  481. if (OM_WorksetOpenS(palPrimary->pomClient, palPrimary->omWSGroupHandle, 0) != 0)
  482. {
  483. ERROR_OUT(( "Error opening OBMAN control workset"));
  484. palPrimary->inCall = FALSE;
  485. DC_QUIT;
  486. }
  487. TRACE_OUT(("Opened OBMANCONTROL workset #0 in call %d", palPrimary->callID));
  488. fHandled = TRUE;
  489. DC_EXIT_POINT:
  490. DebugExitBOOL(ALWorksetNewInd, fHandled);
  491. return(fHandled);
  492. }
  493. //
  494. // ALNewWorksetGroup()
  495. //
  496. BOOL ALNewWorksetGroup
  497. (
  498. PAL_PRIMARY palPrimary,
  499. OM_WSGROUP_HANDLE omWSGroup,
  500. POM_OBJECT pObj
  501. )
  502. {
  503. BOOL fHandled = FALSE;
  504. POM_OBJECTDATA pData = NULL;
  505. OM_WSGROUP_INFO WSGInfo;
  506. OMFP fpHandler;
  507. BOOL fLoaded;
  508. DebugEntry(ALNewWorksetGroup);
  509. ValidateALP(palPrimary);
  510. //
  511. // If the workset group is not in out list of calls, then this event
  512. // is for a group the Application Loader has registered with. The
  513. // event should be passed onto other event procedures.
  514. //
  515. if (!palPrimary->inCall ||
  516. (palPrimary->omWSGroupHandle != omWSGroup))
  517. {
  518. TRACE_OUT(("WSG 0x%x not the OBMAN WSG", omWSGroup));
  519. DC_QUIT;
  520. }
  521. //
  522. // This event is for us
  523. //
  524. fHandled = TRUE;
  525. //
  526. // If the workset group was not created locally
  527. //
  528. TRACE_OUT(("About to read object 0x%08x in OMC", pObj));
  529. if (OM_ObjectRead(palPrimary->pomClient, omWSGroup, 0, pObj, &pData) != 0)
  530. {
  531. ERROR_OUT(( "Could not access object"));
  532. DC_QUIT;
  533. }
  534. //
  535. // Take a copy of the information so we can release the object straight
  536. // away
  537. //
  538. memcpy(&WSGInfo, pData, min(sizeof(WSGInfo), pData->length));
  539. //
  540. // Release the object
  541. //
  542. OM_ObjectRelease(palPrimary->pomClient, omWSGroup, 0, pObj, &pData);
  543. if (WSGInfo.idStamp != OM_WSGINFO_ID_STAMP)
  544. {
  545. TRACE_OUT(( "Not WSG Info - ignoring"));
  546. DC_QUIT;
  547. }
  548. TRACE_OUT(("New WSG FP %s, name %s, ID = 0x%08x in call %d",
  549. WSGInfo.functionProfile,
  550. WSGInfo.wsGroupName,
  551. WSGInfo.wsGroupID,
  552. palPrimary->callID));
  553. //
  554. // Store the UID for the local OBMAN in the new call
  555. //
  556. if (!palPrimary->omUID)
  557. {
  558. OM_GetNetworkUserID(palPrimary->pomClient, omWSGroup, &(palPrimary->omUID));
  559. }
  560. //
  561. // Ignore workset groups created by the local machine
  562. //
  563. if (WSGInfo.creator == palPrimary->omUID)
  564. {
  565. TRACE_OUT(("WSG %s created locally - ignoring", WSGInfo.functionProfile));
  566. DC_QUIT;
  567. }
  568. //
  569. // Is this a workset we care about? I.E. not a backlevel clipboard
  570. // or whatever thing.
  571. //
  572. fpHandler = OMMapNameToFP(WSGInfo.functionProfile);
  573. if (fpHandler != OMFP_WB)
  574. {
  575. //
  576. // We don't care about this one.
  577. //
  578. TRACE_OUT(("Obsolete workset %s from another party", WSGInfo.functionProfile));
  579. DC_QUIT;
  580. }
  581. //
  582. // If prevented by policy, don't launch it either.
  583. //
  584. if (g_asPolicies & SHP_POLICY_NOOLDWHITEBOARD)
  585. {
  586. WARNING_OUT(("Failing auto-launch of old whiteboard; prevented by policy"));
  587. }
  588. else
  589. {
  590. // Old whiteboard...
  591. fLoaded = ALStartStopWB(palPrimary, NULL);
  592. ALLocalLoadResult(palPrimary, fLoaded);
  593. }
  594. DC_EXIT_POINT:
  595. DebugExitBOOL(ALNewWorksetGroup, fHandled);
  596. return(fHandled);
  597. }
  598. //
  599. // ALLocalLoadResult()
  600. //
  601. void ALLocalLoadResult
  602. (
  603. PAL_PRIMARY palPrimary,
  604. BOOL success
  605. )
  606. {
  607. PTSHR_AL_LOAD_RESULT pAlLoadObject;
  608. POM_OBJECT pObjNew;
  609. POM_OBJECTDATA pDataNew;
  610. CM_STATUS cmStatus;
  611. DebugEntry(ALLocalLoadResult);
  612. //
  613. // Have we accessed the workset correctly yet?
  614. //
  615. if (!palPrimary->alWorksetOpen && palPrimary->inCall)
  616. {
  617. TRACE_OUT(("AL Workset not open yet; deferring local load result"));
  618. palPrimary->alWBRegPend = TRUE;
  619. palPrimary->alWBRegSuccess = (success != FALSE);
  620. DC_QUIT;
  621. }
  622. //
  623. // Clear out pending reg stuff
  624. //
  625. palPrimary->alWBRegPend = FALSE;
  626. //
  627. // Create an object to be used to inform remote sites of the result of
  628. // the load.
  629. //
  630. if (OM_ObjectAlloc(palPrimary->pomClient, palPrimary->alWSGroupHandle, 0,
  631. sizeof(*pAlLoadObject), &pDataNew) != 0)
  632. {
  633. ERROR_OUT(("Could not allocate AL object for WB load"));
  634. DC_QUIT;
  635. }
  636. //
  637. // Fill in information about object
  638. //
  639. pDataNew->length = sizeof(*pAlLoadObject);
  640. pAlLoadObject = (PTSHR_AL_LOAD_RESULT)pDataNew->data;
  641. //
  642. // HERE'S WHERE WE MAP the FP constant back to a string
  643. //
  644. lstrcpy(pAlLoadObject->szFunctionProfile, OMMapFPToName(OMFP_WB));
  645. CMS_GetStatus(&cmStatus);
  646. lstrcpy(pAlLoadObject->personName, cmStatus.localName);
  647. pAlLoadObject->result = (success ? AL_LOAD_SUCCESS : AL_LOAD_FAIL_BAD_EXE);
  648. //
  649. // Add object to Application Loader workset
  650. //
  651. if (OM_ObjectAdd(palPrimary->pomClient, palPrimary->alWSGroupHandle, 0,
  652. &pDataNew, 0, &pObjNew, LAST) != 0)
  653. {
  654. ERROR_OUT(("Could not add WB load object to AL WSG"));
  655. //
  656. // Free object
  657. //
  658. OM_ObjectDiscard(palPrimary->pomClient, palPrimary->alWSGroupHandle,
  659. 0, &pDataNew);
  660. DC_QUIT;
  661. }
  662. //
  663. // Now that we have added the object - lets delete it!
  664. //
  665. // This may sound strange, but every application that has this workset
  666. // open will receive OBJECT_ADD events and be able to read the object
  667. // before they confirm the delete. This means that all the Application
  668. // Loader primary tasks in the call will be able to record the result
  669. // of this attempted load.
  670. //
  671. // Deleting the object here is the simplest way of tidying up the
  672. // workset.
  673. //
  674. OM_ObjectDelete(palPrimary->pomClient, palPrimary->alWSGroupHandle,
  675. 0, pObjNew);
  676. DC_EXIT_POINT:
  677. DebugExitVOID(ALLocalLoadResult);
  678. }
  679. //
  680. // ALWorksetRegister()
  681. //
  682. void ALWorksetRegisterCon
  683. (
  684. PAL_PRIMARY palPrimary,
  685. UINT correlator,
  686. UINT result,
  687. OM_WSGROUP_HANDLE hWSGroup
  688. )
  689. {
  690. DebugEntry(ALWorksetRegisterCon);
  691. ValidateALP(palPrimary);
  692. //
  693. // See if this an event for the Application Loader function profile
  694. //
  695. if (!palPrimary->inCall ||
  696. (palPrimary->omWSGCorrelator != correlator))
  697. {
  698. TRACE_OUT(( "OM_WSGROUP_REGISTER_CON not for us"));
  699. DC_QUIT;
  700. }
  701. palPrimary->omWSGCorrelator = 0;
  702. //
  703. // Store the workset group handle if the registration was successful
  704. //
  705. if (result)
  706. {
  707. WARNING_OUT(("Could not register with AL function profile, %#hx",
  708. result));
  709. DC_QUIT;
  710. }
  711. palPrimary->alWSGroupHandle = hWSGroup;
  712. TRACE_OUT(("Opened AL workset group, handle 0x%x", hWSGroup));
  713. //
  714. // Open workset 0 in the workset group - this will be used to transfer
  715. // 'load results' from site to site
  716. //
  717. OM_WorksetOpenPReq(palPrimary->pomClient,
  718. palPrimary->alWSGroupHandle,
  719. 0,
  720. NET_LOW_PRIORITY,
  721. FALSE,
  722. &palPrimary->omWSCorrelator);
  723. DC_EXIT_POINT:
  724. DebugExitVOID(ALWorksetRegisterCon);
  725. }
  726. //
  727. // ALRemoteLoadResult()
  728. //
  729. BOOL ALRemoteLoadResult
  730. (
  731. PAL_PRIMARY palPrimary,
  732. OM_WSGROUP_HANDLE alWSGroup,
  733. POM_OBJECT pObj
  734. )
  735. {
  736. CM_STATUS cmStatus;
  737. BOOL fHandled = FALSE;
  738. POM_OBJECTDATA pData = NULL;
  739. TSHR_AL_LOAD_RESULT alLoadResult;
  740. DebugEntry(ALRemoteLoadResult);
  741. ValidateALP(palPrimary);
  742. //
  743. // Find the call information stored for this call
  744. //
  745. // If the workset group is not in out list of calls, then this event
  746. // is for a group the Application Loader has registered with. The
  747. // event should be passed onto other event procedures.
  748. //
  749. if (!palPrimary->inCall ||
  750. (palPrimary->alWSGroupHandle != alWSGroup))
  751. {
  752. TRACE_OUT(("WSG 0x%x not the AL WSG", alWSGroup));
  753. DC_QUIT;
  754. }
  755. //
  756. // We care
  757. //
  758. fHandled = TRUE;
  759. //
  760. // Read the object
  761. //
  762. if (OM_ObjectRead(palPrimary->pomClient, alWSGroup, 0, pObj, &pData) != 0)
  763. {
  764. ERROR_OUT(( "Could not access object"));
  765. DC_QUIT;
  766. }
  767. //
  768. // Take a copy of the information so we can release the object straight
  769. // away
  770. //
  771. memcpy(&alLoadResult, &pData->data, sizeof(alLoadResult));
  772. //
  773. // Release the object
  774. //
  775. OM_ObjectRelease(palPrimary->pomClient, alWSGroup, 0, pObj, &pData);
  776. //
  777. // Convert the machine name to a person handle for this machine
  778. //
  779. TRACE_OUT(("Load result for FP %s is %d for person %s",
  780. alLoadResult.szFunctionProfile,
  781. alLoadResult.result,
  782. alLoadResult.personName));
  783. //
  784. // If the load was successful, don't bother notifying WB; it isn't
  785. // going to do anything.
  786. //
  787. if (alLoadResult.result == AL_LOAD_SUCCESS)
  788. {
  789. TRACE_OUT(("Load was successful; Whiteboard doesn't care"));
  790. DC_QUIT;
  791. }
  792. //
  793. // If this was us, also don't notify WB.
  794. //
  795. CMS_GetStatus(&cmStatus);
  796. if (!lstrcmp(alLoadResult.personName, cmStatus.localName))
  797. {
  798. TRACE_OUT(("Load was for local dude; Whiteboard doesn't care"));
  799. DC_QUIT;
  800. }
  801. //
  802. // Map function profile to type
  803. //
  804. if (OMMapNameToFP(alLoadResult.szFunctionProfile) == OMFP_WB)
  805. {
  806. if (palPrimary->putWB != NULL)
  807. {
  808. UT_PostEvent(palPrimary->putTask,
  809. palPrimary->putWB,
  810. 0,
  811. ALS_REMOTE_LOAD_RESULT,
  812. alLoadResult.result,
  813. 0);
  814. }
  815. }
  816. DC_EXIT_POINT:
  817. DebugExitBOOL(ALRemoteLoadResult, fHandled);
  818. return(fHandled);
  819. }
  820. //
  821. // ALStartStopWB()
  822. //
  823. // This takes care of starting/stopping the old Whiteboard applet. This is
  824. // no longer a separate EXE. It is now a DLL (though still MFC) which gets
  825. // loaded in CONF's process. We take care of LoadLibrary()ing it the first
  826. // time it is pulled in, either via normal or auto launch. Then we call into
  827. // it to get a new thread/window.
  828. //
  829. // By having CONF post a message to the primary task, where autolaunch also
  830. // happens, we get the load synchronized. It is only ever done from the
  831. // same thread, meaning we don't have to create extra protection for our
  832. // variables.
  833. //
  834. // fNewWB is a TEMP HACK variable to launch the new whiteboard until we
  835. // have the T.120 wiring in place
  836. //
  837. BOOL ALStartStopWB(PAL_PRIMARY palPrimary, LPCTSTR szFileNameCopy)
  838. {
  839. BOOL fSuccess;
  840. DebugEntry(ALStartStopWB);
  841. if (!palPrimary->putWB)
  842. {
  843. //
  844. // Whiteboard isn't running, we can only start it.
  845. //
  846. // This won't return until WB is initialized and registered.
  847. // We own the AL lock, so we don't have to worry about starting
  848. // more than one thread at a time, etc.
  849. //
  850. DCS_StartThread(OldWBThreadProc);
  851. }
  852. fSuccess = (palPrimary->putWB != NULL);
  853. if (fSuccess)
  854. {
  855. UT_PostEvent(palPrimary->putTask, palPrimary->putWB,
  856. 0, ALS_LOCAL_LOAD, 0, (UINT_PTR)szFileNameCopy);
  857. }
  858. DebugExitBOOL(ALStartStopWB, fSuccess);
  859. return(fSuccess);
  860. }
  861. //
  862. // This is the whiteboard thread. We have the thread code actually in our
  863. // DLL, so we can control when WB is running. The proc loads the WB dll,
  864. // calls Run(), then frees the dll.
  865. //
  866. DWORD WINAPI OldWBThreadProc(LPVOID hEventWait)
  867. {
  868. DWORD rc = 0;
  869. HMODULE hLibWB;
  870. PFNINITWB pfnInitWB;
  871. PFNRUNWB pfnRunWB;
  872. PFNTERMWB pfnTermWB;
  873. DebugEntry(OldWBThreadProc);
  874. //
  875. // Load the WB library
  876. //
  877. hLibWB = NmLoadLibrary(TEXT("nmoldwb.dll"),FALSE);
  878. if (!hLibWB)
  879. {
  880. ERROR_OUT(("Can't start 2.x whiteboard; nmoldwb.dll not loaded"));
  881. DC_QUIT;
  882. }
  883. pfnInitWB = (PFNINITWB)GetProcAddress(hLibWB, "InitWB");
  884. pfnRunWB = (PFNRUNWB)GetProcAddress(hLibWB, "RunWB");
  885. pfnTermWB = (PFNTERMWB)GetProcAddress(hLibWB, "TermWB");
  886. if (!pfnInitWB || !pfnRunWB || !pfnTermWB)
  887. {
  888. ERROR_OUT(("Can't start 2.x whiteboard; nmoldwb.dll is wrong version"));
  889. DC_QUIT;
  890. }
  891. //
  892. // Let WB do its thing. When it has inited, it will pulse the event,
  893. // which will let the caller continue.
  894. //
  895. if (!pfnInitWB())
  896. {
  897. ERROR_OUT(("Couldn't initialize whiteboard"));
  898. }
  899. else
  900. {
  901. //
  902. // The AL/OM thread is blocked waiting for us to set the event.
  903. // It owns the AL critsect. So we can modify the global variable
  904. // without taking the critsect.
  905. //
  906. ASSERT(g_palPrimary != NULL);
  907. // Bump up shared mem ref count
  908. UT_BumpUpRefCount(g_palPrimary);
  909. // Save WB task for event posting
  910. ASSERT(g_autTasks[UTTASK_WB].dwThreadId);
  911. g_palPrimary->putWB = &g_autTasks[UTTASK_WB];
  912. // Register exit cleanup proc
  913. UT_RegisterExit(g_palPrimary->putWB, ALSExitProc, NULL);
  914. //
  915. // Let the caller continue. The run code is going to do message
  916. // loop stuff.
  917. //
  918. SetEvent((HANDLE)hEventWait);
  919. pfnRunWB();
  920. //
  921. // This will cleanup if we haven't already
  922. //
  923. ALSExitProc(NULL);
  924. }
  925. pfnTermWB();
  926. DC_EXIT_POINT:
  927. if (hLibWB != NULL)
  928. {
  929. //
  930. // Free the WB dll
  931. //
  932. FreeLibrary(hLibWB);
  933. }
  934. return(0);
  935. }
  936. //
  937. // ALSExitProc()
  938. //
  939. void CALLBACK ALSExitProc(LPVOID data)
  940. {
  941. DebugEntry(ALSecExitProc);
  942. UT_Lock(UTLOCK_AL);
  943. ASSERT(g_palPrimary != NULL);
  944. //
  945. // Deregister exit procedure (if registered call UT_DeregisterExit()
  946. // with ALSecExitProc()).
  947. //
  948. UT_DeregisterExit(g_palPrimary->putWB, ALSExitProc, NULL);
  949. g_palPrimary->putWB = NULL;
  950. //
  951. // Bump down ref count on AL primary
  952. //
  953. UT_FreeRefCount((void**)&g_palPrimary, TRUE);
  954. UT_Unlock(UTLOCK_AL);
  955. DebugExitVOID(ALSExitProc);
  956. }