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.

1458 lines
33 KiB

  1. #include "precomp.h"
  2. #include "gcchelp.h"
  3. #include "coder.hpp"
  4. #include "drawobj.hpp"
  5. #include "NMWbObj.h"
  6. extern Coder * g_pCoder;
  7. UINT AllocateFakeGCCHandle(void)
  8. {
  9. return g_localGCCHandle++;
  10. }
  11. void SetFakeGCCHandle(UINT fakeGCCHandle)
  12. {
  13. g_localGCCHandle = fakeGCCHandle;
  14. }
  15. //
  16. // Add drawings/bitmaps etc... to workspace
  17. //
  18. BOOL AddT126ObjectToWorkspace(T126Obj *pObj)
  19. {
  20. WorkspaceObj * pWorkspace = GetWorkspace(pObj->GetWorkspaceHandle());
  21. if(pWorkspace)
  22. {
  23. pWorkspace->AddTail(pObj);
  24. g_numberOfObjects++;
  25. return TRUE;
  26. }
  27. else
  28. {
  29. WARNING_OUT(("Object sent to invalid workspace %d, will be deleted now!!!", GetWorkspace(pObj->GetWorkspaceHandle())));
  30. delete pObj;
  31. return FALSE;
  32. }
  33. }
  34. //
  35. // Cleanup for all pdus we send
  36. //
  37. void SIPDUCleanUp(SIPDU *sipdu)
  38. {
  39. switch(sipdu->choice)
  40. {
  41. //
  42. // Simple cleanup
  43. //
  44. case bitmapDeletePDU_chosen:
  45. case drawingDeletePDU_chosen:
  46. case workspaceDeletePDU_chosen:
  47. case workspaceRefreshStatusPDU_chosen:
  48. break;
  49. //
  50. // Bitmap Create cleanup
  51. //
  52. case bitmapCreatePDU_chosen:
  53. {
  54. if(sipdu->u.bitmapCreatePDU.nonStandardParameters)
  55. {
  56. delete sipdu->u.bitmapCreatePDU.nonStandardParameters;
  57. }
  58. PBitmapCreatePDU_attributes pAttrib;
  59. PBitmapCreatePDU_attributes pNextAttrib;
  60. pAttrib = sipdu->u.bitmapCreatePDU.attributes;
  61. while(pAttrib)
  62. {
  63. pNextAttrib = pAttrib->next;
  64. delete pAttrib;
  65. pAttrib = pNextAttrib;
  66. }
  67. }
  68. break;
  69. case bitmapEditPDU_chosen:
  70. {
  71. BitmapEditPDU_attributeEdits * pAttrib;
  72. BitmapEditPDU_attributeEdits * pNextAttrib;
  73. pAttrib = sipdu->u.bitmapEditPDU.attributeEdits;
  74. while(pAttrib)
  75. {
  76. pNextAttrib = pAttrib->next;
  77. delete pAttrib;
  78. pAttrib = pNextAttrib;
  79. }
  80. }
  81. break;
  82. //
  83. // Bitmap Continue cleanup
  84. //
  85. case bitmapCreateContinuePDU_chosen:
  86. {
  87. if(sipdu->u.bitmapCreateContinuePDU.nonStandardParameters)
  88. {
  89. delete sipdu->u.bitmapCreateContinuePDU.nonStandardParameters;
  90. }
  91. }
  92. break;
  93. //
  94. // Drawing Edit Cleanup
  95. //
  96. case drawingEditPDU_chosen:
  97. {
  98. if(sipdu->u.drawingEditPDU.bit_mask & DrawingEditPDU_attributeEdits_present)
  99. {
  100. PDrawingEditPDU_attributeEdits pAttrib;
  101. PDrawingEditPDU_attributeEdits pNextAttrib;
  102. pAttrib = sipdu->u.drawingEditPDU.attributeEdits;
  103. while(pAttrib)
  104. {
  105. pNextAttrib = pAttrib->next;
  106. delete pAttrib;
  107. pAttrib = pNextAttrib;
  108. }
  109. }
  110. if(sipdu->u.drawingEditPDU.pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16)
  111. {
  112. PPointList_pointsDiff16 drawingPoint = sipdu->u.drawingEditPDU.pointListEdits.value[0].subsequentPointEdits.u.pointsDiff16;
  113. PPointList_pointsDiff16 drawingPointNext = drawingPoint;
  114. while(drawingPointNext)
  115. {
  116. drawingPointNext = drawingPoint->next;
  117. delete drawingPoint;
  118. drawingPoint = drawingPointNext;
  119. }
  120. }
  121. }
  122. break;
  123. //
  124. // Drawing Edit cleanup
  125. //
  126. case drawingCreatePDU_chosen:
  127. {
  128. PDrawingCreatePDU_attributes pNextAttrib;
  129. PDrawingCreatePDU_attributes pAttrib;
  130. pAttrib = sipdu->u.drawingCreatePDU.attributes;
  131. while(pAttrib)
  132. {
  133. pNextAttrib = pAttrib->next;
  134. delete pAttrib;
  135. pAttrib = pNextAttrib;
  136. }
  137. PPointList_pointsDiff16 pNextPoint;
  138. PPointList_pointsDiff16 pPoint;
  139. pPoint = sipdu->u.drawingCreatePDU.pointList.u.pointsDiff16;
  140. while(pPoint)
  141. {
  142. pNextPoint = pPoint->next;
  143. delete pPoint;
  144. pPoint = pNextPoint;
  145. }
  146. }
  147. break;
  148. //
  149. // Non Standard cleanup
  150. //
  151. case siNonStandardPDU_chosen:
  152. if(sipdu->u.siNonStandardPDU.nonStandardTransaction.data.value)
  153. {
  154. delete sipdu->u.siNonStandardPDU.nonStandardTransaction.data.value;
  155. }
  156. break;
  157. //
  158. // Workspace Edit cleanup
  159. //
  160. case workspaceEditPDU_chosen:
  161. {
  162. if(sipdu->u.workspaceEditPDU.bit_mask & viewEdits_present)
  163. {
  164. PWorkspaceEditPDU_viewEdits_Set_action_editView pEditView = sipdu->u.workspaceEditPDU.viewEdits->value.action.u.editView;
  165. PWorkspaceEditPDU_viewEdits_Set_action_editView pNextEditView = pEditView;
  166. while(pNextEditView)
  167. {
  168. pNextEditView = pEditView->next;
  169. delete pEditView;
  170. pEditView = pNextEditView;
  171. }
  172. delete sipdu->u.workspaceEditPDU.viewEdits;
  173. }
  174. }
  175. break;
  176. //
  177. // Workspace Create cleanup
  178. //
  179. case workspaceCreatePDU_chosen:
  180. {
  181. if(sipdu->u.workspaceCreatePDU.viewParameters)
  182. {
  183. if(sipdu->u.workspaceCreatePDU.viewParameters->value.viewAttributes)
  184. {
  185. delete sipdu->u.workspaceCreatePDU.viewParameters->value.viewAttributes;
  186. }
  187. delete sipdu->u.workspaceCreatePDU.viewParameters;
  188. }
  189. if(sipdu->u.workspaceCreatePDU.planeParameters)
  190. {
  191. PWorkspaceCreatePDU_planeParameters_Seq_usage pNextUsage;
  192. PWorkspaceCreatePDU_planeParameters_Seq_usage pUsage = sipdu->u.workspaceCreatePDU.planeParameters->value.usage;
  193. while(pUsage)
  194. {
  195. pNextUsage = pUsage->next;
  196. delete pUsage;
  197. pUsage = pNextUsage;
  198. }
  199. delete sipdu->u.workspaceCreatePDU.planeParameters->value.planeAttributes;
  200. PWorkspaceCreatePDU_planeParameters pNextPlaneParameters;
  201. PWorkspaceCreatePDU_planeParameters pPlaneParameters = sipdu->u.workspaceCreatePDU.planeParameters;
  202. while(pPlaneParameters)
  203. {
  204. pNextPlaneParameters = pPlaneParameters->next;
  205. delete pPlaneParameters;
  206. pPlaneParameters = pNextPlaneParameters;
  207. }
  208. }
  209. }
  210. break;
  211. default:
  212. ERROR_OUT(("UNKNOWN PDU TYPE = %d we may leak memory", sipdu->choice));
  213. break;
  214. }
  215. delete sipdu;
  216. }
  217. //
  218. // Cleans the retry list, when we close down or disconnect
  219. //
  220. void DeleteAllRetryPDUS(void)
  221. {
  222. SIPDU * sipdu;
  223. while((sipdu = (SIPDU *)g_pRetrySendList->RemoveTail()) != NULL)
  224. {
  225. SIPDUCleanUp(sipdu);
  226. }
  227. }
  228. //
  229. // Retry sending buffered pdus and send the new pdu
  230. //
  231. T120Error SendT126PDU(SIPDU * pPDU)
  232. {
  233. MLZ_EntryOut(ZONE_FUNCTION, "SendT126PDU");
  234. //
  235. // First send buffered pdus
  236. //
  237. RetrySend();
  238. //
  239. // Now send the current pdu
  240. //
  241. T120Error rc = SendPDU(pPDU, FALSE);
  242. return rc;
  243. }
  244. //
  245. // Retry sending pdus that couldn't be sent before
  246. //
  247. void RetrySend(void)
  248. {
  249. MLZ_EntryOut(ZONE_FUNCTION, "RetrySend");
  250. if(g_fWaitingForBufferAvailable)
  251. {
  252. return;
  253. }
  254. TRACE_MSG(("RetrySend"));
  255. SIPDU * sipdu;
  256. while((sipdu = (SIPDU *)g_pRetrySendList->RemoveTail()) != NULL)
  257. {
  258. TRACE_DEBUG(("RetrySend sipdu->choice = %d", sipdu->choice));
  259. T120Error rc = SendPDU(sipdu, TRUE);
  260. if(rc == T120_NO_ERROR)
  261. {
  262. TRACE_DEBUG(("RetrySend OK!!!"));
  263. SIPDUCleanUp(sipdu);
  264. }
  265. else
  266. {
  267. TRACE_DEBUG(("RetrySend Failed"));
  268. break;
  269. }
  270. }
  271. }
  272. //
  273. // Send T126 pdus down to the conference
  274. //
  275. T120Error SendPDU(SIPDU * pPDU, BOOL bRetry)
  276. {
  277. MLZ_EntryOut(ZONE_FUNCTION, "SendPDU");
  278. T120Error rc = T120_NO_ERROR;
  279. //
  280. // If we are in a conference
  281. //
  282. if(g_pNMWBOBJ->IsInConference() || g_bSavingFile)
  283. {
  284. ASN1_BUF encodedPDU;
  285. g_pCoder->Encode(pPDU, &encodedPDU);
  286. if(g_bSavingFile)
  287. {
  288. g_pMain->ObjectSave(TYPE_T126_ASN_OBJECT, encodedPDU.value, encodedPDU.length);
  289. }
  290. else
  291. {
  292. if(!g_fWaitingForBufferAvailable)
  293. {
  294. T120Priority ePriority = APPLET_LOW_PRIORITY;
  295. if(pPDU->choice == workspaceCreatePDU_chosen ||
  296. pPDU->choice == workspaceEditPDU_chosen ||
  297. pPDU->choice == workspaceDeletePDU_chosen)
  298. {
  299. //
  300. // Do what the standard says send the pdus in 3 different priorities
  301. //
  302. TRACE_MSG(("SendPDU sending PDU length = %d in APPLET_HIGH_PRIORITY", encodedPDU.length));
  303. rc = g_pNMWBOBJ->SendData(APPLET_HIGH_PRIORITY,
  304. encodedPDU.length,
  305. encodedPDU.value);
  306. TRACE_MSG(("SendPDU sending PDU length = %d in APPLET_MEDIUM_PRIORITY", encodedPDU.length));
  307. if(rc == T120_NO_ERROR)
  308. {
  309. rc = g_pNMWBOBJ->SendData(APPLET_MEDIUM_PRIORITY,
  310. encodedPDU.length,
  311. encodedPDU.value);
  312. }
  313. }
  314. TRACE_MSG(("SendPDU sending PDU length = %d in APPLET_LOW_PRIORITY", encodedPDU.length));
  315. if(rc == T120_NO_ERROR)
  316. {
  317. rc = g_pNMWBOBJ->SendData(ePriority,
  318. encodedPDU.length,
  319. encodedPDU.value);
  320. }
  321. if(rc == MCS_TRANSMIT_BUFFER_FULL)
  322. {
  323. g_fWaitingForBufferAvailable = TRUE;
  324. //
  325. // We need to add it back to the correct position
  326. //
  327. if(bRetry)
  328. {
  329. g_pRetrySendList->AddTail(pPDU);
  330. }
  331. else
  332. {
  333. g_pRetrySendList->AddHead(pPDU);
  334. }
  335. }
  336. }
  337. else
  338. {
  339. rc = MCS_TRANSMIT_BUFFER_FULL;
  340. g_pRetrySendList->AddHead(pPDU);
  341. }
  342. }
  343. // Free the encoder memory
  344. g_pCoder->Free(encodedPDU);
  345. }
  346. return rc;
  347. }
  348. BOOL T126_MCSSendDataIndication(ULONG uSize, LPBYTE pb, ULONG memberID, BOOL bResend)
  349. {
  350. BOOL bRet = TRUE;
  351. SIPDU * pDecodedPDU;
  352. ASN1_BUF InputBuffer;
  353. InputBuffer.length = uSize;
  354. InputBuffer.value = pb;
  355. //
  356. // Decode incoming PDU
  357. if(ASN1_SUCCEEDED(g_pCoder->Decode(&InputBuffer, &pDecodedPDU)))
  358. {
  359. switch(pDecodedPDU->choice)
  360. {
  361. // case (archiveAcknowledgePDU_chosen):
  362. // {
  363. // TRACE_DEBUG((">>> Received a archiveAcknowledgePDU"));
  364. // TRACE_DEBUG(("No action taken"));
  365. // break;
  366. // }
  367. // case (archiveClosePDU_chosen):
  368. // {
  369. // TRACE_DEBUG((">>> Received a archiveClosePDU"));
  370. // TRACE_DEBUG(("No action taken"));
  371. // break;
  372. // }
  373. // case (archiveErrorPDU_chosen):
  374. // {
  375. // TRACE_DEBUG((">>> Received a archiveErrorPDU"));
  376. // TRACE_DEBUG(("No action taken"));
  377. // break;
  378. // }
  379. // case (archiveOpenPDU_chosen):
  380. // {
  381. // TRACE_DEBUG((">>> Received a archiveOpenPDU"));
  382. // TRACE_DEBUG(("No action taken"));
  383. // break;
  384. // }
  385. case (bitmapAbortPDU_chosen):
  386. {
  387. TRACE_DEBUG((">>> Received a bitmapAbortPDU"));
  388. OnBitmapAbortPDU(&pDecodedPDU->u.bitmapAbortPDU, memberID);
  389. break;
  390. }
  391. case (bitmapCheckpointPDU_chosen):
  392. {
  393. TRACE_DEBUG((">>> Received a bitmapCheckpointPDU"));
  394. OnBitmapCheckpointPDU(&pDecodedPDU->u.bitmapCheckpointPDU, memberID);
  395. break;
  396. }
  397. case (bitmapCreatePDU_chosen):
  398. {
  399. TRACE_DEBUG((">>> Received a bitmapCreatePDU"));
  400. OnBitmapCreatePDU(&pDecodedPDU->u.bitmapCreatePDU, memberID, bResend);
  401. break;
  402. }
  403. case (bitmapCreateContinuePDU_chosen):
  404. {
  405. TRACE_DEBUG((">>> Received a bitmapCreateContinuePDU"));
  406. OnBitmapCreateContinuePDU(&pDecodedPDU->u.bitmapCreateContinuePDU, memberID, bResend);
  407. break;
  408. }
  409. case (bitmapDeletePDU_chosen):
  410. {
  411. TRACE_DEBUG((">>> Received a bitmapDeletePDU"));
  412. OnBitmapDeletePDU(&pDecodedPDU->u.bitmapDeletePDU, memberID);
  413. break;
  414. }
  415. case (bitmapEditPDU_chosen):
  416. {
  417. TRACE_DEBUG((">>> Received a bitmapEditPDU"));
  418. OnBitmapEditPDU(&pDecodedPDU->u.bitmapEditPDU, memberID);
  419. break;
  420. }
  421. case (conductorPrivilegeGrantPDU_chosen):
  422. {
  423. TRACE_DEBUG((">>> Received a conductorPrivilegeGrantPDU"));
  424. TRACE_DEBUG(("No action taken"));
  425. break;
  426. }
  427. case (conductorPrivilegeRequestPDU_chosen):
  428. {
  429. TRACE_DEBUG((">>> Received a conductorPrivilegeRequestPDU"));
  430. TRACE_DEBUG(("No action taken"));
  431. break;
  432. }
  433. case (drawingCreatePDU_chosen):
  434. {
  435. TRACE_DEBUG((">>> Received a drawingCreatePDU"));
  436. OnDrawingCreatePDU(&pDecodedPDU->u.drawingCreatePDU, memberID, bResend);
  437. break;
  438. }
  439. case (drawingDeletePDU_chosen):
  440. {
  441. TRACE_DEBUG((">>> Received a drawingDeletePDU"));
  442. OnDrawingDeletePDU(&pDecodedPDU->u.drawingDeletePDU, memberID);
  443. break;
  444. }
  445. case (drawingEditPDU_chosen):
  446. {
  447. TRACE_DEBUG((">>> Received a drawingEditPDU"));
  448. OnDrawingEditPDU(&pDecodedPDU->u.drawingEditPDU, memberID, bResend);
  449. break;
  450. }
  451. // case (remoteEventPermissionGrantPDU_chosen):
  452. // {
  453. // TRACE_DEBUG((">>> Received a remoteEventPermissionGrantPDU"));
  454. // TRACE_DEBUG(("No action taken"));
  455. // break;
  456. // }
  457. // case (remoteEventPermissionRequestPDU_chosen):
  458. // {
  459. // TRACE_DEBUG((">>> Received a remoteEventPermissionRequestPDU"));
  460. // TRACE_DEBUG(("No action taken"));
  461. // break;
  462. // }
  463. // case (remoteKeyboardEventPDU_chosen):
  464. // {
  465. // TRACE_DEBUG((">>> Received a remoteKeyboardEventPDU"));
  466. // TRACE_DEBUG(("No action taken"));
  467. // break;
  468. // }
  469. // case (remotePointingDeviceEventPDU_chosen):
  470. // {
  471. // TRACE_DEBUG((">>> Received a remotePointingDeviceEventPDU"));
  472. // TRACE_DEBUG(("No action taken"));
  473. // break;
  474. // }
  475. // case (remotePrintPDU_chosen):
  476. // {
  477. // TRACE_DEBUG((">>> Received a remotePrintPDU"));
  478. // TRACE_DEBUG(("No action taken"));
  479. // break;
  480. // }
  481. case (siNonStandardPDU_chosen):
  482. {
  483. if(pDecodedPDU->u.siNonStandardPDU.nonStandardTransaction.nonStandardIdentifier.choice == h221nonStandard_chosen)
  484. {
  485. PT126_VENDORINFO pVendorInfo = (PT126_VENDORINFO)pDecodedPDU->u.siNonStandardPDU.nonStandardTransaction.nonStandardIdentifier.u.h221nonStandard.value;
  486. if (!lstrcmp((LPSTR)&pVendorInfo->nonstandardString, NonStandardTextID))
  487. {
  488. TEXTPDU_HEADER *pHeader = (TEXTPDU_HEADER*) pDecodedPDU->u.siNonStandardPDU.nonStandardTransaction.data.value;
  489. switch(pHeader->nonStandardPDU)
  490. {
  491. case textCreatePDU_chosen:
  492. TRACE_DEBUG((">>> Received a textCreatePDU_chosen"));
  493. OnTextCreatePDU((MSTextPDU*)pHeader, memberID, bResend);
  494. break;
  495. case textEditPDU_chosen:
  496. TRACE_DEBUG((">>> Received a textEditPDU_chosen"));
  497. OnTextEditPDU((MSTextPDU*)pHeader, memberID);
  498. break;
  499. case textDeletePDU_chosen:
  500. TRACE_DEBUG((">>> Received a textDeletePDU_chosen"));
  501. OnTextDeletePDU(pHeader, memberID);
  502. break;
  503. default:
  504. TRACE_DEBUG(("Invalid text pdu"));
  505. break;
  506. }
  507. }
  508. }
  509. break;
  510. }
  511. case (workspaceCreatePDU_chosen):
  512. {
  513. TRACE_DEBUG((">>> Received a workspaceCreatePDU"));
  514. OnWorkspaceCreatePDU(&pDecodedPDU->u.workspaceCreatePDU, memberID, bResend);
  515. break;
  516. }
  517. case (workspaceCreateAcknowledgePDU_chosen):
  518. {
  519. TRACE_DEBUG((">>> Received a workspaceCreateAcknowledgePDU"));
  520. OnWorkspaceCreateAcknowledgePDU(&pDecodedPDU->u.workspaceCreateAcknowledgePDU, memberID);
  521. break;
  522. }
  523. case (workspaceDeletePDU_chosen):
  524. {
  525. TRACE_DEBUG((">>> Received a workspaceDeletePDU"));
  526. OnWorkspaceDeletePDU(&pDecodedPDU->u.workspaceDeletePDU, memberID);
  527. break;
  528. }
  529. case (workspaceEditPDU_chosen):
  530. {
  531. TRACE_DEBUG((">>> Received a workspaceEditPDU"));
  532. OnWorkspaceEditPDU(&pDecodedPDU->u.workspaceEditPDU, memberID);
  533. break;
  534. }
  535. case (workspacePlaneCopyPDU_chosen):
  536. {
  537. TRACE_DEBUG((">>> Received a workspacePlaneCopyPDU"));
  538. OnWorkspacePlaneCopyPDU(&pDecodedPDU->u.workspacePlaneCopyPDU, memberID);
  539. break;
  540. }
  541. case (workspaceReadyPDU_chosen):
  542. {
  543. TRACE_DEBUG((">>> Received a workspaceReadyPDU"));
  544. OnWorkspaceReadyPDU(&pDecodedPDU->u.workspaceReadyPDU, memberID);
  545. break;
  546. }
  547. case (workspaceRefreshStatusPDU_chosen):
  548. {
  549. TRACE_DEBUG((">>> Received a workspaceRefreshStatusPDU"));
  550. OnWorkspaceRefreshStatusPDU(&pDecodedPDU->u.workspaceRefreshStatusPDU, memberID);
  551. break;
  552. }
  553. // case (fontPDU_chosen):
  554. // {
  555. // TRACE_DEBUG((">>> Received a fontPDU"));
  556. // TRACE_DEBUG(("No action taken"));
  557. // break;
  558. // }
  559. // case (textCreatePDU_chosen):
  560. // {
  561. // TRACE_DEBUG((">>> Received a textCreatePDU"));
  562. // TRACE_DEBUG(("No action taken"));
  563. // break;
  564. // }
  565. // case (textDeletePDU_chosen):
  566. // {
  567. // TRACE_DEBUG((">>> Received a textDeletePDU"));
  568. // TRACE_DEBUG(("No action taken"));
  569. // break;
  570. // }
  571. // case (textEditPDU_chosen):
  572. // {
  573. // TRACE_DEBUG((">>> Received a textEditPDU"));
  574. // TRACE_DEBUG(("No action taken"));
  575. // break;
  576. // }
  577. // case (videoWindowCreatePDU_chosen):
  578. // {
  579. // TRACE_DEBUG((">>> Received a videoWindowCreatePDU"));
  580. // TRACE_DEBUG(("No action taken"));
  581. // break;
  582. // }
  583. // case (videoWindowDeleatePDU_chosen):
  584. // {
  585. // TRACE_DEBUG((">>> Received a videoWindowDeleatePDU"));
  586. // TRACE_DEBUG(("No action taken"));
  587. // break;
  588. // }
  589. // case (videoWindowEditPDU_chosen):
  590. // {
  591. // TRACE_DEBUG((">>> Received a videoWindowEditPDU"));
  592. // TRACE_DEBUG(("No action taken"));
  593. // break;
  594. // }
  595. default:
  596. bRet = FALSE;
  597. TRACE_DEBUG(("Receive an Unhandled PDU choice = %d", pDecodedPDU->choice));
  598. break;
  599. }
  600. }
  601. //
  602. // Free the decoded pdu
  603. // JOSEF: for performance in the future we could pass
  604. // the decoded buffer to the ui, avoiding more memory allocation.
  605. // But it will be hard to read the code, since the T126 structures
  606. // are a bit confusing.
  607. //
  608. g_pCoder->Free(pDecodedPDU);
  609. return bRet;
  610. }
  611. //
  612. // Delete All Workspaces sent and received
  613. //
  614. void DeleteAllWorkspaces(BOOL sendPDU)
  615. {
  616. T126Obj * pObj;
  617. if(g_pDraw && g_pDraw->m_pTextEditor)
  618. {
  619. g_pDraw->m_pTextEditor->AbortEditGently();
  620. }
  621. g_pCurrentWorkspace = NULL;
  622. g_pConferenceWorkspace = NULL;
  623. while ((pObj = (T126Obj *)g_pListOfWorkspaces->RemoveTail()) != NULL)
  624. {
  625. if(sendPDU)
  626. {
  627. pObj->DeletedLocally();
  628. }
  629. else
  630. {
  631. pObj->ClearDeletionFlags();
  632. }
  633. delete pObj;
  634. }
  635. if(g_pMain)
  636. {
  637. g_pMain->EnableToolbar(FALSE);
  638. g_pMain->UpdatePageButtons();
  639. }
  640. }
  641. /////////////////////////////////////////////////////////////////////////////////////////////
  642. // TEXT PDUS
  643. /////////////////////////////////////////////////////////////////////////////////////////////
  644. void OnTextCreatePDU(MSTextPDU* pCreatePDU, ULONG memberID, BOOL bForcedResend)
  645. {
  646. WorkspaceObj* pWObj;
  647. WbTextEditor * pText;
  648. //
  649. // Check for resend
  650. //
  651. if(!bForcedResend)
  652. {
  653. pWObj = GetWorkspace(pCreatePDU->header.workspaceHandle);
  654. if(pWObj)
  655. {
  656. pText = (WbTextEditor *)pWObj->FindObjectInWorkspace(pCreatePDU->header.textHandle);
  657. if(pText)
  658. {
  659. TRACE_DEBUG(("drawingHandle already used = %d", pCreatePDU->header.textHandle ));
  660. return;
  661. }
  662. }
  663. }
  664. //
  665. // New Drawing object
  666. //
  667. DBG_SAVE_FILE_LINE
  668. pText = new WbTextEditor();
  669. if(NULL == pText)
  670. {
  671. ERROR_OUT(("Failed to allocate new WbTextEditor"));
  672. return;
  673. }
  674. pText->SetWorkspaceHandle(pCreatePDU->header.workspaceHandle);
  675. pText->SetThisObjectHandle(pCreatePDU->header.textHandle);
  676. if(!bForcedResend)
  677. {
  678. //
  679. // Some one sent us this drawing, it is not created locally
  680. //
  681. pText->ClearCreationFlags();
  682. //
  683. // Add a this drawing to the correct workspace
  684. //
  685. if(!AddT126ObjectToWorkspace(pText))
  686. {
  687. return;
  688. }
  689. }
  690. else
  691. {
  692. //
  693. // Add this object and send Create PDU
  694. //
  695. pText->SetAllAttribs();
  696. pText->SetWorkspaceHandle(g_pCurrentWorkspace == NULL ? 0 : g_pCurrentWorkspace->GetWorkspaceHandle());
  697. pText->ClearSelectionFlags();
  698. pText->GetTextAttrib(&pCreatePDU->attrib);
  699. pText->AddToWorkspace();
  700. pText->Draw();
  701. return;
  702. }
  703. pText->TextEditObj(&pCreatePDU->attrib);
  704. pText->Draw();
  705. pText->ResetAttrib();
  706. }
  707. void OnTextDeletePDU(TEXTPDU_HEADER *pHeader, ULONG memberID)
  708. {
  709. T126Obj* pText;
  710. WorkspaceObj* pWorkspace;
  711. // We should find this drawing object
  712. if(FindObjectAndWorkspace(pHeader->textHandle, (T126Obj**)&pText, (WorkspaceObj**)&pWorkspace))
  713. {
  714. pText->SetOwnerID(memberID);
  715. pWorkspace->RemoveT126Object(pText);
  716. }
  717. }
  718. void OnTextEditPDU(MSTextPDU *pEditPDU, ULONG memberID)
  719. {
  720. TextObj* pText;
  721. WorkspaceObj* pWorkspace;
  722. // We should find this drawing object
  723. if(FindObjectAndWorkspace(pEditPDU->header.textHandle, (T126Obj **)&pText, (WorkspaceObj**)&pWorkspace))
  724. {
  725. pText->SetOwnerID(memberID);
  726. pText->TextEditObj(&pEditPDU->attrib);
  727. }
  728. }
  729. /////////////////////////////////////////////////////////////////////////////////////////////
  730. // DRAWING PDUS
  731. /////////////////////////////////////////////////////////////////////////////////////////////
  732. void OnDrawingCreatePDU(DrawingCreatePDU * pdrawingCreatePDU, ULONG memberID, BOOL bForcedResend)
  733. {
  734. WorkspaceObj* pWObj;
  735. DrawObj * pDraw;
  736. UINT workspace;
  737. UINT planeID;
  738. //
  739. // If we don't have a drawing handle dont take it
  740. //
  741. if(!(pdrawingCreatePDU->bit_mask & drawingHandle_present))
  742. {
  743. TRACE_DEBUG(("Got a DrawingCreatePDU but no drawingHandle" ));
  744. return;
  745. }
  746. GetDrawingDestinationAddress(&pdrawingCreatePDU->destinationAddress, &workspace, &planeID);
  747. //
  748. // Check for resend
  749. //
  750. if(!bForcedResend)
  751. {
  752. pWObj = GetWorkspace(workspace);
  753. if(pWObj)
  754. {
  755. pDraw = (DrawObj *)pWObj->FindObjectInWorkspace(pdrawingCreatePDU->drawingHandle);
  756. if(pDraw)
  757. {
  758. TRACE_DEBUG(("drawingHandle already used = %d", pdrawingCreatePDU->drawingHandle ));
  759. return;
  760. }
  761. }
  762. }
  763. //
  764. // New Drawing object
  765. //
  766. DBG_SAVE_FILE_LINE
  767. pDraw = new DrawObj(pdrawingCreatePDU);
  768. if(NULL == pDraw)
  769. {
  770. ERROR_OUT(("Failed to alocate DrawObj"));
  771. return;
  772. }
  773. pDraw->SetOwnerID(memberID);
  774. if(!bForcedResend)
  775. {
  776. //
  777. // Some one sent us this drawing, it is not created locally
  778. //
  779. pDraw->ClearCreationFlags();
  780. //
  781. // Add a this drawing to the correct workspace
  782. //
  783. if(!AddT126ObjectToWorkspace(pDraw))
  784. {
  785. return;
  786. }
  787. }
  788. else
  789. {
  790. //
  791. // Add this object and send Create PDU
  792. //
  793. pDraw->SetAllAttribs();
  794. pDraw->SetWorkspaceHandle(g_pCurrentWorkspace == NULL ? 0 : g_pCurrentWorkspace->GetWorkspaceHandle());
  795. pDraw->ClearSelectionFlags();
  796. pDraw->AddToWorkspace();
  797. pDraw->Draw();
  798. return;
  799. }
  800. //
  801. // Draw it
  802. //
  803. if(pDraw->GetPenThickness())
  804. {
  805. pDraw->Draw();
  806. pDraw->ResetAttrib();
  807. }
  808. }
  809. void OnDrawingDeletePDU(DrawingDeletePDU * pdrawingDeletePDU, ULONG memberID)
  810. {
  811. DrawObj* pDraw;
  812. WorkspaceObj* pWorkspace;
  813. // We should find this drawing object
  814. if(FindObjectAndWorkspace(pdrawingDeletePDU->drawingHandle, (T126Obj **)&pDraw, (WorkspaceObj**)&pWorkspace))
  815. {
  816. pDraw->SetOwnerID(memberID);
  817. pWorkspace->RemoveT126Object((T126Obj*)pDraw);
  818. }
  819. }
  820. void OnDrawingEditPDU(DrawingEditPDU * pdrawingEditPDU, ULONG memberID, BOOL bResend)
  821. {
  822. DrawObj* pDraw;
  823. WorkspaceObj* pWorkspace;
  824. // We should find this drawing object
  825. if(FindObjectAndWorkspace(pdrawingEditPDU->drawingHandle, (T126Obj **)&pDraw, (WorkspaceObj**)&pWorkspace))
  826. {
  827. pDraw->SetOwnerID(memberID);
  828. pDraw->DrawEditObj(pdrawingEditPDU);
  829. }
  830. else
  831. {
  832. //
  833. // We are reading this pdu from disk add the rest of the line to the previous freehand drawing
  834. //
  835. if(bResend)
  836. {
  837. T126Obj * pObj;
  838. pObj = g_pCurrentWorkspace->GetTail();
  839. if(pObj && pObj->GetType() == drawingCreatePDU_chosen &&
  840. (pObj->GraphicTool() == TOOLTYPE_PEN || pObj->GraphicTool() == TOOLTYPE_HIGHLIGHT))
  841. {
  842. pdrawingEditPDU->drawingHandle = pObj->GetThisObjectHandle();
  843. pObj->SetOwnerID(memberID);
  844. ((DrawObj*)pObj)->DrawEditObj(pdrawingEditPDU);
  845. }
  846. }
  847. }
  848. }
  849. /////////////////////////////////////////////////////////////////////////////////////////////
  850. // WORKSPACE PDUS
  851. /////////////////////////////////////////////////////////////////////////////////////////////
  852. BOOL FindObjectAndWorkspace(UINT objectHandle, T126Obj** pObj, WorkspaceObj**pWorkspace)
  853. {
  854. WorkspaceObj * pWrkspc;
  855. T126Obj * pT126Obj;
  856. WBPOSITION pos;
  857. pos = g_pListOfWorkspaces->GetHeadPosition();
  858. while (pos != NULL)
  859. {
  860. pWrkspc = (WorkspaceObj *) g_pListOfWorkspaces->GetNext(pos);
  861. if(pWrkspc)
  862. {
  863. pT126Obj = pWrkspc->FindObjectInWorkspace(objectHandle);
  864. if(pT126Obj)
  865. {
  866. *pObj = pT126Obj;
  867. *pWorkspace = pWrkspc;
  868. return TRUE;
  869. }
  870. }
  871. }
  872. return FALSE;
  873. }
  874. //
  875. // Retrieves workspace from the list of workspaces
  876. //
  877. WorkspaceObj * GetWorkspace(UINT activeWorkspace)
  878. {
  879. WorkspaceObj * pWorkspaceObj;
  880. WBPOSITION pos;
  881. pos = g_pListOfWorkspaces->GetHeadPosition();
  882. while (pos != NULL)
  883. {
  884. pWorkspaceObj = (WorkspaceObj *) g_pListOfWorkspaces->GetNext(pos);
  885. if(pWorkspaceObj->GetWorkspaceHandle() == activeWorkspace)
  886. {
  887. return pWorkspaceObj;
  888. }
  889. }
  890. return NULL;
  891. }
  892. //
  893. // The remote sent us a new workspace
  894. //
  895. void OnWorkspaceCreatePDU(WorkspaceCreatePDU * pWorkspaceCreatePDU, ULONG memberID, BOOL bForcedResend)
  896. {
  897. TRACE_DEBUG(("OnWorkspaceCreatePDU WorkspaceIdentifier = %d", pWorkspaceCreatePDU->workspaceIdentifier.u.activeWorkspace));
  898. WorkspaceObj * pWorkspaceObj;
  899. //
  900. // Check for resend
  901. //
  902. if(!bForcedResend)
  903. {
  904. pWorkspaceObj = GetWorkspace(WorkspaceObj::GetWorkspaceIdentifier(&pWorkspaceCreatePDU->workspaceIdentifier));
  905. if(pWorkspaceObj)
  906. {
  907. return;
  908. }
  909. DBG_SAVE_FILE_LINE
  910. pWorkspaceObj = new WorkspaceObj(pWorkspaceCreatePDU, bForcedResend);
  911. if(NULL == pWorkspaceObj)
  912. {
  913. ERROR_OUT(("Failed to allocated new WorkspaceObj"));
  914. return;
  915. }
  916. pWorkspaceObj->SetOwnerID(memberID);
  917. }
  918. else
  919. {
  920. DBG_SAVE_FILE_LINE
  921. pWorkspaceObj = new WorkspaceObj(pWorkspaceCreatePDU, bForcedResend);
  922. if(NULL == pWorkspaceObj)
  923. {
  924. ERROR_OUT(("Failed to allocated new WorkspaceObj"));
  925. return;
  926. }
  927. pWorkspaceObj->SetOwnerID(memberID);
  928. }
  929. }
  930. //
  931. // If we created an unsynchronized workspace the remote has to sen us
  932. // a WorkspaceCreateAcknowledgePDU. Why???
  933. //
  934. void OnWorkspaceCreateAcknowledgePDU(WorkspaceCreateAcknowledgePDU * pWorkspaceCreateAcknowledgePDU, ULONG memberID)
  935. {
  936. TRACE_DEBUG(("OnWorkspaceCreateAcknowledgePDU WorkspaceIdentifier = %d", pWorkspaceCreateAcknowledgePDU->workspaceIdentifier));
  937. }
  938. //
  939. // The remote is deleting the workspace
  940. //
  941. void OnWorkspaceDeletePDU(WorkspaceDeletePDU * pWorkspaceDeletePDU, ULONG memberID)
  942. {
  943. TRACE_DEBUG(("OnWorkspaceDeletePDU WorkspaceIdentifier = %d", pWorkspaceDeletePDU->workspaceIdentifier.u.activeWorkspace));
  944. //
  945. // Find the workspace
  946. //
  947. WorkspaceObj * pWorkspaceObj;
  948. pWorkspaceObj = GetWorkspace(WorkspaceObj::GetWorkspaceIdentifier(&pWorkspaceDeletePDU->workspaceIdentifier));
  949. if(!pWorkspaceObj)
  950. {
  951. return;
  952. }
  953. pWorkspaceObj->SetOwnerID(memberID);
  954. pWorkspaceObj->ClearDeletionFlags();
  955. //
  956. // Reason for deleting
  957. //
  958. TRACE_DEBUG(("OnWorkspaceDeletePDU reason = %d", pWorkspaceDeletePDU->reason.choice));
  959. //
  960. // Remove it from the List Of Workspaces
  961. //
  962. WBPOSITION prevPos;
  963. WBPOSITION pos;
  964. pos = g_pListOfWorkspaces->GetPosition(pWorkspaceObj);
  965. prevPos = g_pListOfWorkspaces->GetHeadPosition();
  966. //
  967. // This is the only workspace we have ?????
  968. //
  969. if(g_pListOfWorkspaces->GetHeadPosition() == g_pListOfWorkspaces->GetTailPosition())
  970. {
  971. RemoveWorkspace(pWorkspaceObj);
  972. g_pCurrentWorkspace = NULL;
  973. if(g_pMain)
  974. {
  975. g_pMain->EnableToolbar(FALSE);
  976. }
  977. }
  978. else
  979. {
  980. //
  981. // If we had a remote pointer
  982. //
  983. BOOL bRemote = FALSE;
  984. if(g_pMain->m_pLocalRemotePointer)
  985. {
  986. bRemote = TRUE;
  987. g_pMain->OnRemotePointer();
  988. }
  989. //
  990. // Remove the workspace and point the current one to the correct one.
  991. //
  992. pWorkspaceObj = RemoveWorkspace(pWorkspaceObj);
  993. g_pConferenceWorkspace = pWorkspaceObj;
  994. if(g_pDraw->IsSynced())
  995. {
  996. g_pMain->GoPage(pWorkspaceObj,FALSE);
  997. }
  998. //
  999. // If we had a remote pointer
  1000. //
  1001. if(bRemote)
  1002. {
  1003. g_pMain->OnRemotePointer();
  1004. }
  1005. }
  1006. }
  1007. //
  1008. // The remote is changing the workspace
  1009. //
  1010. void OnWorkspaceEditPDU(WorkspaceEditPDU * pWorkspaceEditPDU, ULONG memberID)
  1011. {
  1012. TRACE_DEBUG(("OnWorkspaceEditPDU WorkspaceIdentifier = %d",pWorkspaceEditPDU->workspaceIdentifier.u.activeWorkspace));
  1013. //
  1014. // Find the workspace
  1015. //
  1016. WorkspaceObj * pWorkspaceObj;
  1017. pWorkspaceObj = GetWorkspace(WorkspaceObj::GetWorkspaceIdentifier(&pWorkspaceEditPDU->workspaceIdentifier));
  1018. if(!pWorkspaceObj)
  1019. {
  1020. return;
  1021. }
  1022. pWorkspaceObj->SetOwnerID(memberID);
  1023. pWorkspaceObj->WorkspaceEditObj(pWorkspaceEditPDU);
  1024. }
  1025. void OnWorkspacePlaneCopyPDU(WorkspacePlaneCopyPDU * pWorkspacePlaneCopyPDU, ULONG memberID)
  1026. {
  1027. TRACE_DEBUG(("OnWorkspacePlaneCopyPDU WorkspaceIdentifier = %d",pWorkspacePlaneCopyPDU->sourceWorkspaceIdentifier));
  1028. }
  1029. void OnWorkspaceReadyPDU(WorkspaceReadyPDU * pWorkspaceReadyPDU, ULONG memberID)
  1030. {
  1031. TRACE_DEBUG(("OnWorkspaceReadyPDU WorkspaceIdentifier = %d",pWorkspaceReadyPDU->workspaceIdentifier));
  1032. //
  1033. // Find the workspace
  1034. //
  1035. WorkspaceObj * pWorkspaceObj;
  1036. pWorkspaceObj = GetWorkspace(WorkspaceObj::GetWorkspaceIdentifier(&pWorkspaceReadyPDU->workspaceIdentifier));
  1037. if(!pWorkspaceObj)
  1038. {
  1039. return;
  1040. }
  1041. pWorkspaceObj->SetOwnerID(memberID);
  1042. //
  1043. // This workspace is ready
  1044. //
  1045. pWorkspaceObj->m_bWorkspaceReady = TRUE;
  1046. }
  1047. //
  1048. // If we got a refreshStatus == TRUE, we have to refresh late joiners
  1049. //
  1050. void OnWorkspaceRefreshStatusPDU(WorkspaceRefreshStatusPDU * pWorkspaceRefreshStatusPDU, ULONG memberID)
  1051. {
  1052. if (pWorkspaceRefreshStatusPDU->refreshStatus == TRUE)
  1053. {
  1054. g_RefresherID = memberID;
  1055. }
  1056. else
  1057. {
  1058. //
  1059. // The token is out there, try to grab it
  1060. //
  1061. g_pNMWBOBJ->GrabRefresherToken();
  1062. }
  1063. }
  1064. /////////////////////////////////////////////////////////////////////////////////////////////
  1065. // BITMAP PDUS
  1066. /////////////////////////////////////////////////////////////////////////////////////////////
  1067. void OnBitmapCreatePDU(BitmapCreatePDU * pBitmapCreatePDU, ULONG memberID, BOOL bForcedResend)
  1068. {
  1069. TRACE_DEBUG(("drawingHandle = %d", pBitmapCreatePDU->bitmapHandle ));
  1070. //
  1071. // If we find this object, it is because T120 is broadcasting the drawing
  1072. // we just sent to T126
  1073. //
  1074. UINT workspace;
  1075. UINT planeID;
  1076. GetBitmapDestinationAddress(&pBitmapCreatePDU->destinationAddress, &workspace, &planeID);
  1077. //
  1078. // Check for resend
  1079. //
  1080. WorkspaceObj* pWObj;
  1081. BitmapObj * pBitmap;
  1082. if(!bForcedResend)
  1083. {
  1084. pWObj = GetWorkspace(workspace);
  1085. if(pWObj)
  1086. {
  1087. pBitmap = (BitmapObj*)pWObj->FindObjectInWorkspace(pBitmapCreatePDU->bitmapHandle);
  1088. if(pBitmap)
  1089. return;
  1090. }
  1091. }
  1092. //
  1093. // New Drawing object
  1094. //
  1095. DBG_SAVE_FILE_LINE
  1096. pBitmap = new BitmapObj(pBitmapCreatePDU);
  1097. if(NULL == pBitmap)
  1098. {
  1099. ERROR_OUT(("Failed to allocated new BitmapObj"));
  1100. return;
  1101. }
  1102. pBitmap->SetOwnerID(memberID);
  1103. if(!bForcedResend)
  1104. {
  1105. //
  1106. // Someone else sent us this bitmap, it was not created locally
  1107. //
  1108. pBitmap->ClearCreationFlags();
  1109. //
  1110. // Add a this drawing to the correct workspace
  1111. //
  1112. if(!AddT126ObjectToWorkspace(pBitmap))
  1113. {
  1114. return;
  1115. }
  1116. }
  1117. else
  1118. {
  1119. //
  1120. // If we are reading from disk, this has to be added in the current workspace
  1121. // and we have to wait until we have the whole bitmap to send it
  1122. //
  1123. if(pBitmap->m_fMoreToFollow)
  1124. {
  1125. pBitmap->SetWorkspaceHandle(g_pCurrentWorkspace == NULL ? 0 : g_pCurrentWorkspace->GetWorkspaceHandle());
  1126. AddT126ObjectToWorkspace(pBitmap);
  1127. }
  1128. else
  1129. {
  1130. //
  1131. // Add this object and send Create PDU
  1132. //
  1133. pBitmap->SetAllAttribs();
  1134. pBitmap->AddToWorkspace();
  1135. }
  1136. }
  1137. //
  1138. // PASS IT TO UI
  1139. //
  1140. if(!pBitmap->m_fMoreToFollow)
  1141. {
  1142. pBitmap->Draw();
  1143. }
  1144. }
  1145. void OnBitmapCreateContinuePDU(BitmapCreateContinuePDU * pBitmapCreateContinuePDU, ULONG memberID, BOOL bForcedResend)
  1146. {
  1147. WorkspaceObj* pWorkspace;
  1148. BitmapObj* pBitmap = NULL;
  1149. // We should find this drawing object
  1150. //
  1151. // If we are loading from file it is in the current workspace
  1152. //
  1153. if(bForcedResend)
  1154. {
  1155. ASSERT(g_pCurrentWorkspace);
  1156. if(g_pCurrentWorkspace)
  1157. {
  1158. pBitmap = (BitmapObj*)g_pCurrentWorkspace->FindObjectInWorkspace(pBitmapCreateContinuePDU->bitmapHandle);
  1159. }
  1160. }
  1161. else
  1162. {
  1163. FindObjectAndWorkspace(pBitmapCreateContinuePDU->bitmapHandle, (T126Obj **)&pBitmap, (WorkspaceObj**)&pWorkspace);
  1164. }
  1165. if(pBitmap)
  1166. {
  1167. pBitmap->SetOwnerID(memberID);
  1168. //
  1169. // Found the previous bitmap, concatenate the data
  1170. //
  1171. pBitmap->Continue(pBitmapCreateContinuePDU);
  1172. //
  1173. // PASS IT TO UI
  1174. //
  1175. if(!pBitmap->m_fMoreToFollow)
  1176. {
  1177. pBitmap->Draw();
  1178. if(bForcedResend)
  1179. {
  1180. pBitmap->SetAllAttribs();
  1181. pBitmap->AddToWorkspace();
  1182. }
  1183. }
  1184. }
  1185. }
  1186. void OnBitmapCheckpointPDU(BitmapCheckpointPDU * pBitmapCheckPointPDU, ULONG memberID)
  1187. {
  1188. }
  1189. void OnBitmapAbortPDU(BitmapAbortPDU * pBitmapAbortPDU, ULONG memberID)
  1190. {
  1191. BitmapDeletePDU bitmapDeletePDU;
  1192. bitmapDeletePDU.bitmapHandle = pBitmapAbortPDU->bitmapHandle;
  1193. bitmapDeletePDU.bit_mask = 0;
  1194. //
  1195. // Pass it to bitmapDeletePDU
  1196. //
  1197. OnBitmapDeletePDU(&bitmapDeletePDU, memberID);
  1198. }
  1199. void OnBitmapEditPDU(BitmapEditPDU * pBitmapEditPDU, ULONG memberID)
  1200. {
  1201. BitmapObj* pObj;
  1202. WorkspaceObj* pWorkspace;
  1203. // We should find this drawing object
  1204. if(FindObjectAndWorkspace(pBitmapEditPDU->bitmapHandle, (T126Obj **)&pObj, (WorkspaceObj**)&pWorkspace))
  1205. {
  1206. pObj->SetOwnerID(memberID);
  1207. pObj->BitmapEditObj(pBitmapEditPDU);
  1208. }
  1209. }
  1210. void OnBitmapDeletePDU(BitmapDeletePDU * pBitmapDeletePDU, ULONG memberID)
  1211. {
  1212. BitmapObj* pObj;
  1213. WorkspaceObj* pWorkspace;
  1214. // We should find this drawing object
  1215. if(FindObjectAndWorkspace(pBitmapDeletePDU->bitmapHandle, (T126Obj **)&pObj, (WorkspaceObj**)&pWorkspace))
  1216. {
  1217. pObj->SetOwnerID(memberID);
  1218. pWorkspace->RemoveT126Object((T126Obj*)pObj);
  1219. }
  1220. }