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.

2894 lines
117 KiB

  1. /**MOD+**********************************************************************/
  2. /* Module: cchannel.c */
  3. /* */
  4. /* Purpose: Virtual Channel Client functions */
  5. /* */
  6. /* Copyright(C) Microsoft Corporation 1997 */
  7. /* */
  8. /****************************************************************************/
  9. /* Changes: */
  10. /* $Log$ */
  11. /* */
  12. /**MOD-**********************************************************************/
  13. /****************************************************************************/
  14. /****************************************************************************/
  15. /* HEADERS */
  16. /****************************************************************************/
  17. /****************************************************************************/
  18. #include <adcg.h>
  19. extern "C" {
  20. #define TRC_GROUP TRC_GROUP_NETWORK
  21. #define TRC_FILE "cchannel"
  22. #include <atrcapi.h>
  23. }
  24. #include "autil.h"
  25. #include "wui.h"
  26. #include "sl.h"
  27. #include "nc.h"
  28. #include "cd.h"
  29. #include "cchan.h"
  30. CChan* CChan::pStaticClientInstance = NULL;
  31. /****************************************************************************/
  32. /****************************************************************************/
  33. /* Constants */
  34. /****************************************************************************/
  35. /****************************************************************************/
  36. #define CHANNEL_MSG_SEND 1
  37. #define CHANNEL_MSG_SUSPEND 2
  38. #ifndef UNREFERENCED_PARAMETER
  39. #define UNREFERENCED_PARAMETER(P) (P)
  40. #endif
  41. #define WEBCTRL_DLL_NAME TEXT("mstscax.dll")
  42. #ifdef DEBUG_CCHAN_COMPRESSION
  43. _inline ULONG DbgUserPrint(TCHAR* Format, ...)
  44. {
  45. va_list arglist;
  46. TCHAR Buffer[512];
  47. ULONG retval;
  48. //
  49. // Format the output into a buffer and then print it.
  50. //
  51. va_start(arglist, Format);
  52. retval = _vsntprintf(Buffer, sizeof(Buffer), Format, arglist);
  53. if (retval != -1) {
  54. OutputDebugString(Buffer);
  55. }
  56. return retval;
  57. }
  58. #endif
  59. CChan::CChan(CObjs* objs)
  60. {
  61. DC_BEGIN_FN("CChan");
  62. _pClientObjs = objs;
  63. _pInitHandle = NULL;
  64. _pFirstWrite = NULL;
  65. _pLastWrite = NULL;
  66. _connected = CONNECTION_NONE;
  67. _inChannelEntry = FALSE;
  68. _ChannelInitCalled = FALSE;
  69. _channelCount = 0;
  70. _fCapsVCCompressionSupported = FALSE;
  71. _fCompressChannels = FALSE;
  72. if(!CChan::pStaticClientInstance)
  73. {
  74. //
  75. // Legacy addins can only talk to the initial instance of the client
  76. //
  77. CChan::pStaticClientInstance = this;
  78. }
  79. _pMPPCContext = NULL;
  80. _CompressFlushes = 0;
  81. _fCompressionFlushed = 0;
  82. _pUserOutBuf = NULL;
  83. _fNeedToResetContext = TRUE;
  84. _fLockInitalized = FALSE;
  85. #ifdef DEBUG_CCHAN_COMPRESSION
  86. _pDbgRcvDecompr8K = NULL;
  87. _fDbgVCTriedAllocRecvContext = FALSE;
  88. _fDbgAllocFailedForVCRecvContext = TRUE;
  89. #endif
  90. _iDbgCompressFailedCount = 0;
  91. _iChanSuspendCount = 0;
  92. _iChanResumeCount = 0;
  93. _iChanCapsRecvdCount = 0;
  94. DC_END_FN();
  95. }
  96. CChan::~CChan()
  97. {
  98. if(_fLockInitalized)
  99. {
  100. DeleteCriticalSection(&_VirtualChannelInitLock);
  101. }
  102. if(this == CChan::pStaticClientInstance)
  103. {
  104. CChan::pStaticClientInstance = NULL;
  105. }
  106. }
  107. VOID CChan::SetCapabilities(LONG caps)
  108. {
  109. DC_BEGIN_FN("SetCapabilities");
  110. //
  111. // Determine if we can send compressed VC data to the server
  112. // NOTE: for a few whistler builds the server supported 64K
  113. // compressed channels from the client, but this capability
  114. // has been removed to enhance server scalability.
  115. //
  116. // The capability in the other direction, e.g can the server send
  117. // us compressed data is something the client exposes to the server
  118. //
  119. _iChanCapsRecvdCount++;
  120. _fCapsVCCompressionSupported = (caps & TS_VCCAPS_COMPRESSION_8K) ?
  121. TRUE : FALSE;
  122. TRC_NRM((TB,_T("VC Caps, compression supported: %d"),
  123. _fCapsVCCompressionSupported));
  124. _fCompressChannels = (_fCapsVCCompressionSupported & _pUi->UI_GetCompress());
  125. TRC_NRM((TB,_T("Compress virtual channels: %d"),
  126. _fCompressChannels));
  127. DC_END_FN();
  128. }
  129. void CChan::OnDeviceChange(ULONG_PTR params)
  130. {
  131. PDEVICE_PARAMS deviceParams = (PDEVICE_PARAMS)params;
  132. if (deviceParams->deviceObj != NULL) {
  133. deviceParams->deviceObj->OnDeviceChange(deviceParams->wParam, deviceParams->lParam);
  134. }
  135. }
  136. /****************************************************************************/
  137. /****************************************************************************/
  138. /* API Functions */
  139. /****************************************************************************/
  140. /****************************************************************************/
  141. /****************************************************************************/
  142. /* VirtualChannelInit - see cchannel.h */
  143. /****OC-*********************************************************************/
  144. UINT VCAPITYPE DCEXPORT VirtualChannelInitEx(
  145. PVOID lpUserParam,
  146. PVOID pInitHandle,
  147. PCHANNEL_DEF pChannel,
  148. INT channelCount,
  149. DWORD versionRequested,
  150. PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
  151. {
  152. DC_BEGIN_FN("VirtualChannelInitEx");
  153. UINT rc = CHANNEL_RC_OK;
  154. /************************************************************************/
  155. /* Check parameters */
  156. /************************************************************************/
  157. if (NULL == pInitHandle)
  158. {
  159. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  160. DC_QUIT;
  161. }
  162. if (((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst == NULL)
  163. {
  164. TRC_ERR((TB, _T("Null Init Handle")));
  165. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  166. DC_QUIT;
  167. }
  168. rc = ((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst->IntVirtualChannelInit(
  169. lpUserParam,
  170. NULL, pChannel,
  171. channelCount,
  172. versionRequested,
  173. NULL,
  174. pChannelInitEventProcEx);
  175. DC_EXIT_POINT:
  176. return (rc);
  177. DC_END_FN();
  178. }
  179. UINT VCAPITYPE DCEXPORT VirtualChannelInit(
  180. PVOID * ppInitHandle,
  181. PCHANNEL_DEF pChannel,
  182. INT channelCount,
  183. DWORD versionRequested,
  184. PCHANNEL_INIT_EVENT_FN pChannelInitEventProc)
  185. {
  186. DC_BEGIN_FN("VirtualChannelInit");
  187. UINT rc = CHANNEL_RC_OK;
  188. /************************************************************************/
  189. /* Check parameters */
  190. /************************************************************************/
  191. TRC_ASSERT( CChan::pStaticClientInstance,
  192. (TB, _T("CChan::pStaticClientInstance is NULL in VirtualChannelInit\n")));
  193. if (NULL == CChan::pStaticClientInstance)
  194. {
  195. rc = CHANNEL_RC_INVALID_INSTANCE;
  196. DC_QUIT;
  197. }
  198. rc = (CChan::pStaticClientInstance)->IntVirtualChannelInit(
  199. NULL,
  200. ppInitHandle, pChannel,
  201. channelCount,
  202. versionRequested,
  203. pChannelInitEventProc,
  204. NULL);
  205. DC_EXIT_POINT:
  206. return (rc);
  207. DC_END_FN();
  208. }
  209. UINT VCAPITYPE DCEXPORT CChan::IntVirtualChannelInit(
  210. PVOID pParam,
  211. PVOID * ppInitHandle,
  212. PCHANNEL_DEF pChannel,
  213. INT channelCount,
  214. DWORD versionRequested,
  215. PCHANNEL_INIT_EVENT_FN pChannelInitEventProc,
  216. PCHANNEL_INIT_EVENT_EX_FN pChannelInitEventProcEx)
  217. {
  218. UINT rc = CHANNEL_RC_OK;
  219. INT i, j, k;
  220. PCHANNEL_INIT_HANDLE pRealInitHandle;
  221. DC_BEGIN_FN("IntVirtualChannelInit");
  222. UNREFERENCED_PARAMETER( versionRequested );
  223. EnterCriticalSection(&_VirtualChannelInitLock);
  224. /************************************************************************/
  225. /* Check parameters */
  226. /************************************************************************/
  227. if( versionRequested > VIRTUAL_CHANNEL_VERSION_WIN2000)
  228. {
  229. rc = CHANNEL_RC_UNSUPPORTED_VERSION;
  230. DC_QUIT;
  231. }
  232. //
  233. // ppInitHandle is not used by the EX version of the API
  234. //
  235. if (pChannelInitEventProc && ppInitHandle == NULL)
  236. {
  237. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  238. DC_QUIT;
  239. }
  240. if(pChannelInitEventProc && IsBadWritePtr(ppInitHandle, sizeof(PVOID)))
  241. {
  242. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  243. DC_QUIT;
  244. }
  245. if (pChannel == NULL)
  246. {
  247. rc = CHANNEL_RC_BAD_CHANNEL;
  248. DC_QUIT;
  249. }
  250. if(channelCount <= 0)
  251. {
  252. rc = CHANNEL_RC_BAD_CHANNEL;
  253. DC_QUIT;
  254. }
  255. if ((IsBadReadPtr(pChannel, channelCount * sizeof(CHANNEL_DEF))) ||
  256. (IsBadWritePtr(pChannel, channelCount * sizeof(CHANNEL_DEF))))
  257. {
  258. rc = CHANNEL_RC_BAD_CHANNEL;
  259. DC_QUIT;
  260. }
  261. if ((_channelCount + channelCount) > CHANNEL_MAX_COUNT)
  262. {
  263. rc = CHANNEL_RC_TOO_MANY_CHANNELS;
  264. DC_QUIT;
  265. }
  266. for (i = 0; i < channelCount; i++)
  267. {
  268. for (j = 0; j <= CHANNEL_NAME_LEN; j++)
  269. {
  270. if (pChannel[i].name[j] == '\0')
  271. {
  272. break;
  273. }
  274. }
  275. if (!j || j > CHANNEL_NAME_LEN)
  276. {
  277. /****************************************************************/
  278. /* There was no terminating null in this channel name string */
  279. /* or the channel name was zero length */
  280. /****************************************************************/
  281. rc = CHANNEL_RC_BAD_CHANNEL;
  282. DC_QUIT;
  283. }
  284. }
  285. if (pChannelInitEventProc == NULL && pChannelInitEventProcEx == NULL)
  286. {
  287. rc = CHANNEL_RC_BAD_PROC;
  288. DC_QUIT;
  289. }
  290. /************************************************************************/
  291. /* Check state */
  292. /************************************************************************/
  293. if (_connected != CONNECTION_NONE)
  294. {
  295. rc = CHANNEL_RC_ALREADY_CONNECTED;
  296. DC_QUIT;
  297. }
  298. if (!_inChannelEntry)
  299. {
  300. TRC_ERR((TB,_T("VirtualChannelInit called outside VirtualChannelEntry")));
  301. rc = CHANNEL_RC_NOT_IN_VIRTUALCHANNELENTRY;
  302. DC_QUIT;
  303. }
  304. /************************************************************************/
  305. /* Save the fact that VirtualChannelInit has been called, so that */
  306. /* IntChannelLoad knows it's done. */
  307. /************************************************************************/
  308. _ChannelInitCalled = TRUE;
  309. /************************************************************************/
  310. /* Initialize a handle (allocated by VirtualChannelEntry) */
  311. /************************************************************************/
  312. pRealInitHandle = _newInitHandle;
  313. pRealInitHandle->pInitEventFn = pChannelInitEventProc;
  314. pRealInitHandle->pInitEventExFn = pChannelInitEventProcEx;
  315. pRealInitHandle->channelCount = channelCount;
  316. pRealInitHandle->dwFlags = 0;
  317. if(pChannelInitEventProcEx)
  318. {
  319. pRealInitHandle->lpParam = pParam;
  320. pRealInitHandle->fUsingExApi = TRUE;
  321. }
  322. else
  323. {
  324. pRealInitHandle->fUsingExApi = FALSE;
  325. }
  326. /************************************************************************/
  327. /* Process all Channel data */
  328. /************************************************************************/
  329. for (i = 0, j = _channelCount; i < channelCount; i++)
  330. {
  331. /********************************************************************/
  332. /* Assume it's going to be OK */
  333. /********************************************************************/
  334. pChannel[i].options |= CHANNEL_OPTION_INITIALIZED;
  335. /********************************************************************/
  336. /* Check for duplicate names */
  337. /********************************************************************/
  338. for (k = 0; k < j; k++)
  339. {
  340. #ifdef UNICODE
  341. TRC_DBG((TB, _T("Test %S (#%d) for (case insensitive) dup with %S ((#%d)"),
  342. pChannel[i].name, i, _channel[k].name, k));
  343. #else
  344. TRC_DBG((TB, _T("Test %s (#%d) for (case insensitive) dup with %s ((#%d)"),
  345. pChannel[i].name, i, _channel[k].name, k));
  346. #endif
  347. if (0 == DC_ASTRNICMP(pChannel[i].name, _channel[k].name,
  348. CHANNEL_NAME_LEN))
  349. {
  350. /************************************************************/
  351. /* Tell the caller this channel is not initialized */
  352. /************************************************************/
  353. #ifdef UNICODE
  354. TRC_ERR((TB, _T("Dup channel name %S (#%d/#%d)"),
  355. pChannel[i].name, i, k));
  356. #else
  357. TRC_ERR((TB, _T("Dup channel name %s (#%d/#%d)"),
  358. pChannel[i].name, i, k));
  359. #endif
  360. pChannel[i].options &= (~(CHANNEL_OPTION_INITIALIZED));
  361. pRealInitHandle->channelCount--;
  362. break;
  363. }
  364. }
  365. if (pChannel[i].options & CHANNEL_OPTION_INITIALIZED)
  366. {
  367. /****************************************************************/
  368. /* Channel is OK - save its data */
  369. /****************************************************************/
  370. DC_MEMCPY(_channel[j].name, pChannel[i].name, CHANNEL_NAME_LEN);
  371. //name length is CHANNEL_NAME_LEN+1, ensure null termination
  372. _channel[j].name[CHANNEL_NAME_LEN] = 0;
  373. /****************************************************************/
  374. /* Channels are lower case */
  375. /****************************************************************/
  376. DC_ACSLWR(_channel[j].name);
  377. _channel[j].options = pChannel[i].options;
  378. #ifdef UNICODE
  379. TRC_NRM((TB, _T("Channel #%d, %S"), i, _channel[j].name));
  380. #else
  381. TRC_NRM((TB, _T("Channel #%d, %s"), i, _channel[j].name));
  382. #endif
  383. _channelData[j].pOpenEventFn = NULL;
  384. _channelData[j].pOpenEventExFn = NULL;
  385. _channelData[j].MCSChannelID = 0;
  386. _channelData[j].pInitHandle = pRealInitHandle;
  387. _channelData[j].status = CHANNEL_STATUS_CLOSED;
  388. _channelData[j].priority =
  389. (_channel[j].options & CHANNEL_OPTION_PRI_HIGH) ? TS_HIGHPRIORITY:
  390. (_channel[j].options & CHANNEL_OPTION_PRI_MED) ? TS_MEDPRIORITY:
  391. TS_LOWPRIORITY;
  392. TRC_NRM((TB, _T(" Priority %d"), _channelData[j].priority));
  393. //Ignore all flags, channels always encrypt
  394. _channelData[j].SLFlags = RNS_SEC_ENCRYPT;
  395. _channelData[j].VCFlags =
  396. (_channel[j].options & CHANNEL_OPTION_SHOW_PROTOCOL) ?
  397. CHANNEL_FLAG_SHOW_PROTOCOL : 0;
  398. #ifdef UNICODE
  399. TRC_NRM((TB, _T("Channel %S has %s shadow persistent option"), _channel[j].name,
  400. (_channel[j].options & CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT)? _T(""): _T("NO")));
  401. #else
  402. TRC_NRM((TB, _T("Channel %S has %s shadow persistent option"), _channel[j].name,
  403. (_channel[j].options & CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT) ? _T(""): _T("NO")));
  404. #endif
  405. if (_channel[j].options & CHANNEL_OPTION_REMOTE_CONTROL_PERSISTENT) {
  406. _channelData[j].VCFlags |= CHANNEL_FLAG_SHADOW_PERSISTENT;
  407. // if one channel is shadow persistent then the whole plugin is too.
  408. pRealInitHandle->dwFlags |= CHANNEL_FLAG_SHADOW_PERSISTENT;
  409. }
  410. TRC_NRM((TB, _T("VC Flags: %#x"), _channelData[j].VCFlags));
  411. j++;
  412. }
  413. }
  414. _channelCount += pRealInitHandle->channelCount;
  415. /************************************************************************/
  416. /* Set return code */
  417. /************************************************************************/
  418. if(!pRealInitHandle->fUsingExApi)
  419. {
  420. *ppInitHandle = pRealInitHandle;
  421. TRC_NRM((TB, _T("Return handle %p"), *ppInitHandle));
  422. }
  423. rc = CHANNEL_RC_OK;
  424. DC_EXIT_POINT:
  425. LeaveCriticalSection(&_VirtualChannelInitLock);
  426. DC_END_FN();
  427. return(rc);
  428. } /* VirtualChannelInit */
  429. /****************************************************************************/
  430. /* VirtualChannelOpen - see cchannel.h */
  431. /****************************************************************************/
  432. UINT VCAPITYPE DCEXPORT VirtualChannelOpen(
  433. PVOID pInitHandle,
  434. PDWORD pOpenHandle,
  435. PCHAR pChannelName,
  436. PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc)
  437. {
  438. DC_BEGIN_FN("VirtualChannelOpen");
  439. UINT rc = CHANNEL_RC_OK;
  440. if (pInitHandle == NULL)
  441. {
  442. TRC_ERR((TB, _T("Null Init Handle")));
  443. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  444. DC_QUIT;
  445. }
  446. if (((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst == NULL)
  447. {
  448. TRC_ERR((TB, _T("Null Init Handle")));
  449. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  450. DC_QUIT;
  451. }
  452. rc = ((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst->IntVirtualChannelOpen(pInitHandle,
  453. pOpenHandle,
  454. pChannelName,
  455. pChannelOpenEventProc,
  456. NULL);
  457. DC_EXIT_POINT:
  458. return (rc);
  459. DC_END_FN();
  460. }
  461. UINT VCAPITYPE DCEXPORT VirtualChannelOpenEx(
  462. PVOID pInitHandle,
  463. PDWORD pOpenHandle,
  464. PCHAR pChannelName,
  465. PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
  466. {
  467. DC_BEGIN_FN("VirtualChannelOpenEx");
  468. UINT rc = CHANNEL_RC_OK;
  469. if (pInitHandle == NULL)
  470. {
  471. TRC_ERR((TB, _T("Null Init Handle")));
  472. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  473. DC_QUIT;
  474. }
  475. if (((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst == NULL)
  476. {
  477. TRC_ERR((TB, _T("Null Init Handle")));
  478. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  479. DC_QUIT;
  480. }
  481. rc = ((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst->IntVirtualChannelOpen(pInitHandle,
  482. pOpenHandle,
  483. pChannelName,
  484. NULL,
  485. pChannelOpenEventProcEx);
  486. DC_EXIT_POINT:
  487. return (rc);
  488. DC_END_FN();
  489. }
  490. UINT VCAPITYPE CChan::IntVirtualChannelOpen(
  491. PVOID pInitHandle,
  492. PDWORD pOpenHandle,
  493. PCHAR pChannelName,
  494. PCHANNEL_OPEN_EVENT_FN pChannelOpenEventProc,
  495. PCHANNEL_OPEN_EVENT_EX_FN pChannelOpenEventProcEx)
  496. {
  497. PCHANNEL_INIT_HANDLE pRealInitHandle;
  498. UINT channelID;
  499. UINT rc = CHANNEL_RC_OK;
  500. DC_BEGIN_FN("IntVirtualChannelOpen");
  501. pRealInitHandle = (PCHANNEL_INIT_HANDLE)pInitHandle;
  502. /************************************************************************/
  503. /* Check parameters */
  504. /************************************************************************/
  505. if (pInitHandle == NULL)
  506. {
  507. TRC_ERR((TB, _T("Null Init Handle")));
  508. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  509. DC_QUIT;
  510. }
  511. if (pRealInitHandle->signature != CHANNEL_INIT_SIGNATURE)
  512. {
  513. TRC_ERR((TB, _T("Invalid init handle signature %#lx"),
  514. pRealInitHandle->signature));
  515. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  516. DC_QUIT;
  517. }
  518. if (pOpenHandle == NULL)
  519. {
  520. TRC_ERR((TB, _T("NULL Open Handle")));
  521. rc = CHANNEL_RC_BAD_CHANNEL_HANDLE;
  522. DC_QUIT;
  523. }
  524. if(pRealInitHandle->fUsingExApi)
  525. {
  526. if (pChannelOpenEventProcEx == NULL)
  527. {
  528. rc = CHANNEL_RC_BAD_PROC;
  529. DC_QUIT;
  530. }
  531. }
  532. else
  533. {
  534. if (pChannelOpenEventProc == NULL)
  535. {
  536. rc = CHANNEL_RC_BAD_PROC;
  537. DC_QUIT;
  538. }
  539. }
  540. /************************************************************************/
  541. /* Check connection state */
  542. /************************************************************************/
  543. if ((_connected != CONNECTION_VC) &&
  544. (_connected != CONNECTION_SUSPENDED))
  545. {
  546. TRC_ERR((TB, _T("Not yet connected")));
  547. rc = CHANNEL_RC_NOT_CONNECTED;
  548. DC_QUIT;
  549. }
  550. /************************************************************************/
  551. /* Find the requested channel */
  552. /* channel names are lowercase but do a case insensitve cmp */
  553. /* Just incase an older plugin passed in an upper case name (doc was */
  554. /* not clear channel names had to be lower case */
  555. /************************************************************************/
  556. for (channelID = 0; channelID < _channelCount; channelID++)
  557. {
  558. if (0 == DC_ASTRNICMP(pChannelName, _channel[channelID].name,
  559. CHANNEL_NAME_LEN))
  560. {
  561. break;
  562. }
  563. }
  564. if (channelID == _channelCount)
  565. {
  566. #ifdef UNICODE
  567. TRC_ERR((TB, _T("Unregistered channel %S"), pChannelName));
  568. #else
  569. TRC_ERR((TB, _T("Unregistered channel %s"), pChannelName));
  570. #endif
  571. rc = CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
  572. DC_QUIT;
  573. }
  574. /************************************************************************/
  575. /* Check this channel is registered by this user */
  576. /************************************************************************/
  577. if (_channelData[channelID].pInitHandle != pInitHandle)
  578. {
  579. #ifdef UNICODE
  580. TRC_ERR((TB, _T("Channel %S not registered to this user"), pChannelName));
  581. #else
  582. TRC_ERR((TB, _T("Channel %s not registered to this user"), pChannelName));
  583. #endif
  584. rc = CHANNEL_RC_UNKNOWN_CHANNEL_NAME;
  585. DC_QUIT;
  586. }
  587. /************************************************************************/
  588. /* Check that this channel is not already open */
  589. /************************************************************************/
  590. if (_channelData[channelID].status == CHANNEL_STATUS_OPEN)
  591. {
  592. #ifdef UNICODE
  593. TRC_ERR((TB, _T("Channel %S already open"), pChannelName));
  594. #else
  595. TRC_ERR((TB, _T("Channel %s already open"), pChannelName));
  596. #endif
  597. rc = CHANNEL_RC_ALREADY_OPEN;
  598. DC_QUIT;
  599. }
  600. /************************************************************************/
  601. /* Well, everything seems to be in order. Mark the channel as open and */
  602. /* return its index as the handle. */
  603. /************************************************************************/
  604. _channelData[channelID].status = CHANNEL_STATUS_OPEN;
  605. _channelData[channelID].pOpenEventFn = pChannelOpenEventProc;
  606. _channelData[channelID].pOpenEventExFn = pChannelOpenEventProcEx;
  607. *pOpenHandle = channelID;
  608. rc = CHANNEL_RC_OK;
  609. DC_EXIT_POINT:
  610. DC_END_FN();
  611. return(rc);
  612. } /* VirtualChannelOpen */
  613. /****************************************************************************/
  614. /* VirtualChannelClose - see cchannel.h */
  615. /****************************************************************************/
  616. UINT VCAPITYPE DCEXPORT VirtualChannelClose(DWORD openHandle)
  617. {
  618. UINT rc = CHANNEL_RC_OK;
  619. DC_BEGIN_FN("VirtualChannelClose");
  620. TRC_ASSERT( CChan::pStaticClientInstance,
  621. (TB, _T("CChan::pStaticClientInstance is NULL in VirtualChannelInit\n")));
  622. if (NULL == CChan::pStaticClientInstance)
  623. {
  624. rc = CHANNEL_RC_INVALID_INSTANCE;
  625. DC_QUIT;
  626. }
  627. else
  628. {
  629. rc = (CChan::pStaticClientInstance)->IntVirtualChannelClose(openHandle);
  630. }
  631. DC_END_FN();
  632. DC_EXIT_POINT:
  633. return rc;
  634. }
  635. UINT VCAPITYPE DCEXPORT VirtualChannelCloseEx(LPVOID pInitHandle,
  636. DWORD openHandle)
  637. {
  638. DC_BEGIN_FN("VirtualChannelCloseEx");
  639. UINT rc = CHANNEL_RC_OK;
  640. /************************************************************************/
  641. /* Check parameters */
  642. /************************************************************************/
  643. if (NULL == pInitHandle)
  644. {
  645. return CHANNEL_RC_NULL_DATA;
  646. DC_QUIT;
  647. }
  648. if (((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst == NULL)
  649. {
  650. TRC_ERR((TB, _T("Null Init Handle")));
  651. return CHANNEL_RC_BAD_INIT_HANDLE;
  652. DC_QUIT;
  653. }
  654. rc = ((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst->IntVirtualChannelClose(
  655. openHandle);
  656. DC_EXIT_POINT:
  657. DC_END_FN();
  658. return rc;
  659. }
  660. UINT VCAPITYPE DCEXPORT CChan::IntVirtualChannelClose(DWORD openHandle)
  661. {
  662. UINT rc = CHANNEL_RC_OK;
  663. DWORD chanIndex;
  664. DC_BEGIN_FN("VirtualChannelClose");
  665. chanIndex = openHandle;
  666. /************************************************************************/
  667. /* Check parameters */
  668. /************************************************************************/
  669. if (chanIndex >= _channelCount)
  670. {
  671. TRC_ERR((TB, _T("Invalid handle %ul ...(channel index portion '%ul' invalid)"),
  672. openHandle, chanIndex));
  673. rc = CHANNEL_RC_BAD_CHANNEL_HANDLE;
  674. DC_QUIT;
  675. }
  676. /************************************************************************/
  677. /* Check we're connected */
  678. /************************************************************************/
  679. if ((_connected != CONNECTION_VC) &&
  680. (_connected != CONNECTION_SUSPENDED))
  681. {
  682. TRC_ALT((TB, _T("Not connected")));
  683. rc = CHANNEL_RC_NOT_CONNECTED;
  684. DC_QUIT;
  685. }
  686. /************************************************************************/
  687. /* Check channel status */
  688. /************************************************************************/
  689. if (_channelData[chanIndex].status != CHANNEL_STATUS_OPEN)
  690. {
  691. TRC_ERR((TB, _T("Channel %ul not open"), chanIndex));
  692. rc = CHANNEL_RC_NOT_OPEN;
  693. DC_QUIT;
  694. }
  695. /************************************************************************/
  696. /* Close the channel */
  697. /************************************************************************/
  698. TRC_NRM((TB, _T("Close channel %ul"), chanIndex));
  699. _channelData[chanIndex].status = CHANNEL_STATUS_CLOSED;
  700. _channelData[chanIndex].pOpenEventFn = NULL;
  701. _channelData[chanIndex].pOpenEventExFn = NULL;
  702. /************************************************************************/
  703. /* Er, that's it */
  704. /************************************************************************/
  705. rc = CHANNEL_RC_OK;
  706. DC_EXIT_POINT:
  707. DC_END_FN();
  708. return(rc);
  709. } /* VirtualChannelClose */
  710. /****************************************************************************/
  711. /* VirtualChannelWrite - see cchannel.h */
  712. /****************************************************************************/
  713. UINT VCAPITYPE DCEXPORT VirtualChannelWrite(DWORD openHandle,
  714. LPVOID pData,
  715. ULONG dataLength,
  716. LPVOID pUserData)
  717. {
  718. DC_BEGIN_FN("VirtualChannelWrite");
  719. UINT rc = CHANNEL_RC_OK;
  720. TRC_ASSERT( CChan::pStaticClientInstance,
  721. (TB, _T("CChan::pStaticClientInstance is NULL in VirtualChannelInit\n")));
  722. if (NULL == CChan::pStaticClientInstance)
  723. {
  724. rc = CHANNEL_RC_INVALID_INSTANCE;
  725. DC_QUIT;
  726. }
  727. else
  728. {
  729. rc = (CChan::pStaticClientInstance)->IntVirtualChannelWrite(openHandle,
  730. pData,
  731. dataLength,
  732. pUserData);
  733. }
  734. DC_END_FN();
  735. DC_EXIT_POINT:
  736. return rc;
  737. }
  738. UINT VCAPITYPE DCEXPORT VirtualChannelWriteEx(LPVOID pInitHandle,
  739. DWORD openHandle,
  740. LPVOID pData,
  741. ULONG dataLength,
  742. LPVOID pUserData)
  743. {
  744. DC_BEGIN_FN("VirtualChannelWriteEx");
  745. /************************************************************************/
  746. /* Check parameters */
  747. /************************************************************************/
  748. UINT rc = CHANNEL_RC_OK;
  749. if (NULL == pInitHandle)
  750. {
  751. rc = CHANNEL_RC_NULL_DATA;
  752. DC_QUIT;
  753. }
  754. if (((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst == NULL)
  755. {
  756. TRC_ERR((TB, _T("Null Init Handle")));
  757. rc = CHANNEL_RC_BAD_INIT_HANDLE;
  758. DC_QUIT;
  759. }
  760. rc = ((PCHANNEL_INIT_HANDLE)pInitHandle)->pInst->IntVirtualChannelWrite(
  761. openHandle,
  762. pData,
  763. dataLength,
  764. pUserData);
  765. DC_EXIT_POINT:
  766. DC_END_FN();
  767. return rc;
  768. }
  769. UINT VCAPITYPE DCEXPORT CChan::IntVirtualChannelWrite(DWORD openHandle,
  770. LPVOID pData,
  771. ULONG dataLength,
  772. LPVOID pUserData)
  773. {
  774. UINT rc = CHANNEL_RC_OK;
  775. PCHANNEL_WRITE_DECOUPLE pDecouple;
  776. UINT chanIndex;
  777. DC_BEGIN_FN("VirtualChannelWrite");
  778. chanIndex = openHandle;
  779. TRC_DBG((TB, _T("Got channel index: %ul from handle: %d"), chanIndex, openHandle));
  780. /************************************************************************/
  781. /* Check that we're connected */
  782. /************************************************************************/
  783. if ((_connected != CONNECTION_VC) &&
  784. (_connected != CONNECTION_SUSPENDED))
  785. {
  786. TRC_ERR((TB, _T("Not connected")));
  787. rc = CHANNEL_RC_NOT_CONNECTED;
  788. DC_QUIT;
  789. }
  790. /************************************************************************/
  791. /* Check that this channel is open */
  792. /************************************************************************/
  793. if(chanIndex > _channelCount)
  794. {
  795. TRC_ERR((TB, _T("Invalid channel index %ul from handle %ul"), chanIndex,
  796. openHandle));
  797. rc = CHANNEL_RC_BAD_CHANNEL_HANDLE;
  798. DC_QUIT;
  799. }
  800. /************************************************************************/
  801. /* Check that this channel is open */
  802. /************************************************************************/
  803. if (_channelData[chanIndex].status != CHANNEL_STATUS_OPEN)
  804. {
  805. TRC_ERR((TB, _T("Channel %ul not open"), chanIndex));
  806. rc = CHANNEL_RC_BAD_CHANNEL_HANDLE;
  807. DC_QUIT;
  808. }
  809. /************************************************************************/
  810. /* Check parameters */
  811. /************************************************************************/
  812. if (!pData)
  813. {
  814. TRC_ERR((TB, _T("No data passed")));
  815. rc = CHANNEL_RC_NULL_DATA;
  816. DC_QUIT;
  817. }
  818. if (dataLength == 0)
  819. {
  820. TRC_ERR((TB, _T("Zero data length")));
  821. rc = CHANNEL_RC_ZERO_LENGTH;
  822. DC_QUIT;
  823. }
  824. /************************************************************************/
  825. /* Queue the write operation */
  826. /************************************************************************/
  827. pDecouple = (PCHANNEL_WRITE_DECOUPLE) UT_Malloc(_pUt, sizeof(CHANNEL_WRITE_DECOUPLE));
  828. if (pDecouple == NULL)
  829. {
  830. TRC_ERR((TB, _T("Failed to allocate decouple structure")));
  831. rc = CHANNEL_RC_NO_MEMORY;
  832. DC_QUIT;
  833. }
  834. TRC_NRM((TB, _T("Decouple structure allocated at %p"), pDecouple));
  835. pDecouple->signature = CHANNEL_DECOUPLE_SIGNATURE;
  836. pDecouple->pData = pData;
  837. pDecouple->pNextData = pData;
  838. pDecouple->dataLength = dataLength;
  839. pDecouple->dataLeft = dataLength;
  840. pDecouple->dataSent = 0;
  841. pDecouple->openHandle = openHandle;
  842. pDecouple->pUserData = pUserData;
  843. pDecouple->pNext = NULL;
  844. pDecouple->pPrev = NULL;
  845. pDecouple->chanOptions = _channel[chanIndex].options;
  846. pDecouple->flags = _channelData[chanIndex].VCFlags | CHANNEL_FLAG_FIRST;
  847. /************************************************************************/
  848. /* Pass the request to the SND thread */
  849. /************************************************************************/
  850. TRC_NRM((TB, _T("Decouple, pass %p -> %p"), &pDecouple, pDecouple));
  851. _pCd->CD_DecoupleNotification(CD_SND_COMPONENT,
  852. this,
  853. CD_NOTIFICATION_FUNC(CChan,IntChannelWrite),
  854. &pDecouple,
  855. sizeof(pDecouple));
  856. /************************************************************************/
  857. /* All done! */
  858. /************************************************************************/
  859. rc = CHANNEL_RC_OK;
  860. DC_EXIT_POINT:
  861. DC_END_FN();
  862. return(rc);
  863. } /* VirtualChannelWrite */
  864. /****************************************************************************/
  865. /****************************************************************************/
  866. /* Callback Functions */
  867. /****************************************************************************/
  868. /****************************************************************************/
  869. /**PROC+*********************************************************************/
  870. /* Name: ChannelOnInitialized */
  871. /* */
  872. /* Purpose: Called when MSTSC completes initialization */
  873. /* */
  874. /* Returns: none */
  875. /* */
  876. /* Params: none */
  877. /* */
  878. /**PROC-*********************************************************************/
  879. DCVOID DCCALLBACK CChan::ChannelOnInitialized(DCVOID)
  880. {
  881. DC_BEGIN_FN("ChannelOnInitialized");
  882. /************************************************************************/
  883. /* Call Initialized callbacks */
  884. /************************************************************************/
  885. TRC_NRM((TB, _T("Call callbacks ...")));
  886. IntChannelCallCallbacks(CHANNEL_EVENT_INITIALIZED, NULL, 0);
  887. DC_END_FN();
  888. return;
  889. } /* ChannelOnInitialized */
  890. /**PROC+*********************************************************************/
  891. /* Name: ChannelOnTerminating */
  892. /* */
  893. /* Purpose: Call when MSTSC is terminating */
  894. /* */
  895. /* Returns: none */
  896. /* */
  897. /* Params: none */
  898. /* */
  899. /**PROC-*********************************************************************/
  900. DCVOID DCCALLBACK CChan::ChannelOnTerminating(DCVOID)
  901. {
  902. PCHANNEL_INIT_HANDLE pInitHandle;
  903. PCHANNEL_INIT_HANDLE pFreeHandle;
  904. DC_BEGIN_FN("ChannelOnTerminating");
  905. /************************************************************************/
  906. /* Loop through all handles */
  907. /************************************************************************/
  908. pInitHandle = _pInitHandle;
  909. while (pInitHandle != NULL)
  910. {
  911. TRC_NRM((TB, _T("Terminate handle %p"), pInitHandle));
  912. /********************************************************************/
  913. /* Call the terminated callback */
  914. /********************************************************************/
  915. if(pInitHandle->fUsingExApi)
  916. {
  917. pInitHandle->pInitEventExFn(
  918. pInitHandle->lpParam,
  919. pInitHandle,
  920. CHANNEL_EVENT_TERMINATED,
  921. NULL, 0);
  922. }
  923. else
  924. {
  925. pInitHandle->pInitEventFn(pInitHandle,
  926. CHANNEL_EVENT_TERMINATED,
  927. NULL, 0);
  928. }
  929. /********************************************************************/
  930. /* Free the library */
  931. /********************************************************************/
  932. FreeLibrary(pInitHandle->hMod);
  933. /********************************************************************/
  934. /* Free the handle */
  935. /********************************************************************/
  936. pFreeHandle = pInitHandle;
  937. pInitHandle = pInitHandle->pNext;
  938. pFreeHandle->signature = 0;
  939. UT_Free(_pUt, pFreeHandle);
  940. }
  941. if(_pMPPCContext)
  942. {
  943. UT_Free(_pUt, _pMPPCContext);
  944. _pMPPCContext = NULL;
  945. }
  946. if(_pUserOutBuf)
  947. {
  948. UT_Free(_pUt, _pUserOutBuf);
  949. _pUserOutBuf = NULL;
  950. }
  951. /************************************************************************/
  952. /* Clear key data */
  953. /************************************************************************/
  954. _pInitHandle = NULL;
  955. _channelCount = 0;
  956. _connected = CONNECTION_NONE;
  957. DC_END_FN();
  958. DC_EXIT_POINT:
  959. return;
  960. } /* ChannelOnTerminating */
  961. /**PROC+*********************************************************************/
  962. /* Name: ChannelOnConnected */
  963. /* */
  964. /* Purpose: Called when a connection is established */
  965. /* */
  966. /* Returns: None */
  967. /* */
  968. /* Params: channelID - T128 MCS channel ID */
  969. /* serverVersion - software version of Server */
  970. /* pUserData - Server-Client Net user data */
  971. /* userDataLength - length of user data */
  972. /* */
  973. /**PROC-*********************************************************************/
  974. DCVOID DCCALLBACK CChan::ChannelOnConnected(DCUINT channelID,
  975. DCUINT32 serverVersion,
  976. PDCVOID pUserData,
  977. DCUINT userDataLength)
  978. {
  979. PRNS_UD_SC_NET pNetUserData;
  980. PDCUINT16 pMCSChannel;
  981. UINT i;
  982. UINT expectedLength;
  983. UINT event;
  984. DCTCHAR serverName[UT_MAX_ADDRESS_LENGTH];
  985. DC_BEGIN_FN("ChannelOnConnected");
  986. UNREFERENCED_PARAMETER( channelID );
  987. #ifndef DC_DEBUG
  988. UNREFERENCED_PARAMETER( userDataLength );
  989. #endif
  990. /************************************************************************/
  991. /* Check Server software version */
  992. /************************************************************************/
  993. if (_RNS_MINOR_VERSION(serverVersion) < 2)
  994. {
  995. TRC_ALT((TB, _T("Old Server - no channel support")));
  996. event = CHANNEL_EVENT_V1_CONNECTED;
  997. _connected = CONNECTION_V1;
  998. }
  999. else
  1000. {
  1001. TRC_NRM((TB, _T("New Server version - channels supported")));
  1002. /********************************************************************/
  1003. /* Set up local pointers */
  1004. /********************************************************************/
  1005. pNetUserData = (PRNS_UD_SC_NET)pUserData;
  1006. pMCSChannel = (PDCUINT16)(pNetUserData + 1);
  1007. /********************************************************************/
  1008. /* Check parameters */
  1009. /********************************************************************/
  1010. TRC_ASSERT((pNetUserData->channelCount == _channelCount),
  1011. (TB, _T("Channel count changed by Server: was %hd, is %d"),
  1012. _channelCount, pNetUserData->channelCount));
  1013. expectedLength = sizeof(RNS_UD_SC_NET) +
  1014. (pNetUserData->channelCount * sizeof(DCUINT16));
  1015. if (userDataLength < expectedLength) {
  1016. TRC_ABORT((TB,_T("SC NET user data too short - is %d, expect %d"),
  1017. userDataLength, expectedLength));
  1018. _pSl->SL_DropLinkImmediate(SL_ERR_INVALIDPACKETFORMAT);
  1019. DC_QUIT;
  1020. }
  1021. /********************************************************************/
  1022. /* Save channel data */
  1023. /********************************************************************/
  1024. for (i = 0; i < _channelCount; i++)
  1025. {
  1026. _channelData[i].MCSChannelID = pMCSChannel[i];
  1027. }
  1028. /********************************************************************/
  1029. /* Update our state */
  1030. /********************************************************************/
  1031. _connected = CONNECTION_VC;
  1032. event = CHANNEL_EVENT_CONNECTED;
  1033. }
  1034. /************************************************************************/
  1035. /* Call Connected callbacks */
  1036. /************************************************************************/
  1037. _pUi->UI_GetServerName(serverName, SIZE_TCHARS(serverName));
  1038. IntChannelCallCallbacks(event, serverName, UT_MAX_ADDRESS_LENGTH);
  1039. DC_EXIT_POINT:
  1040. DC_END_FN();
  1041. return;
  1042. } /* ChannelOnConnected */
  1043. /**PROC+*********************************************************************/
  1044. /* Name: ChannelOnDisconnected */
  1045. /* */
  1046. /* Purpose: Called when a session is disconnected */
  1047. /* */
  1048. /* Returns: none */
  1049. /* */
  1050. /* Params: reason - disconnect reason code */
  1051. /* */
  1052. /* */
  1053. /**PROC-*********************************************************************/
  1054. DCVOID DCCALLBACK CChan::ChannelOnDisconnected(DCUINT reason)
  1055. {
  1056. UINT i;
  1057. DC_BEGIN_FN("ChannelOnDisconnected");
  1058. UNREFERENCED_PARAMETER( reason );
  1059. /************************************************************************/
  1060. /* Don't do anything if we haven't told the callbacks we're connected. */
  1061. /************************************************************************/
  1062. if (_connected == CONNECTION_NONE)
  1063. {
  1064. TRC_ALT((TB, _T("Disconnected callback when not connected")));
  1065. DC_QUIT;
  1066. }
  1067. /************************************************************************/
  1068. /* Change state */
  1069. /************************************************************************/
  1070. _connected = CONNECTION_NONE;
  1071. /************************************************************************/
  1072. /* Call Disconnected callbacks */
  1073. /************************************************************************/
  1074. TRC_NRM((TB, _T("Call disconnected callbacks")));
  1075. IntChannelCallCallbacks(CHANNEL_EVENT_DISCONNECTED, NULL, 0);
  1076. /************************************************************************/
  1077. /* Disconnection implies that all channels are closed */
  1078. /************************************************************************/
  1079. for (i = 0; i < _channelCount; i++)
  1080. {
  1081. TRC_NRM((TB, _T("'Close' channel %d"), i));
  1082. _channelData[i].status = CHANNEL_STATUS_CLOSED;
  1083. }
  1084. /************************************************************************/
  1085. /* Switch to SND thread to cancel all outstanding sends */
  1086. /************************************************************************/
  1087. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1088. this,
  1089. CD_NOTIFICATION_FUNC(CChan,IntChannelCancelSend),
  1090. CHANNEL_MSG_SEND);
  1091. DC_EXIT_POINT:
  1092. DC_END_FN();
  1093. return;
  1094. } /* ChannelOnDisconnected */
  1095. /**PROC+*********************************************************************/
  1096. /* Name: ChannelOnSuspended */
  1097. /* */
  1098. /* Purpose: Called when a session is suspended (shadow client) */
  1099. /* */
  1100. /* Returns: none */
  1101. /* */
  1102. /* Params: reason - disconnect reason code */
  1103. /* */
  1104. /* */
  1105. /**PROC-*********************************************************************/
  1106. DCVOID DCCALLBACK CChan::ChannelOnSuspended(DCUINT reason)
  1107. {
  1108. UINT i;
  1109. DC_BEGIN_FN("ChannelOnDisconnected");
  1110. UNREFERENCED_PARAMETER( reason );
  1111. /************************************************************************/
  1112. /* Don't do anything if we haven't told the callbacks we're connected. */
  1113. /************************************************************************/
  1114. if (_connected == CONNECTION_NONE)
  1115. {
  1116. TRC_ALT((TB, _T("Disconnected callback when not connected")));
  1117. DC_QUIT;
  1118. }
  1119. _iChanSuspendCount++;
  1120. /************************************************************************/
  1121. /* Change state */
  1122. /************************************************************************/
  1123. _connected = CONNECTION_SUSPENDED;
  1124. /************************************************************************/
  1125. /* Call Disconnected callbacks */
  1126. /************************************************************************/
  1127. TRC_NRM((TB, _T("Call disconnected callbacks")));
  1128. IntChannelCallCallbacks(CHANNEL_EVENT_REMOTE_CONTROL_START, NULL, 0);
  1129. /************************************************************************/
  1130. /* Disconnection implies that all channels are closed */
  1131. /************************************************************************/
  1132. for (i = 0; i < _channelCount; i++)
  1133. {
  1134. TRC_NRM((TB, _T("'Close' channel %d"), i));
  1135. // If a plug-in specified at least one of its channels shadow persistent,
  1136. // then it will be notified with the shadow start event instead of the
  1137. // disconnected event. In this case the plug-in is supposed to shutdown
  1138. // only its non-shadow-persistent channels. So close only channels that
  1139. // are not shadow persistent.
  1140. if (!(_channelData[i].VCFlags & CHANNEL_FLAG_SHADOW_PERSISTENT))
  1141. _channelData[i].status = CHANNEL_STATUS_CLOSED;
  1142. }
  1143. /************************************************************************/
  1144. /* Switch to SND thread to cancel all outstanding sends */
  1145. /************************************************************************/
  1146. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1147. this,
  1148. CD_NOTIFICATION_FUNC(CChan,IntChannelCancelSend),
  1149. CHANNEL_MSG_SUSPEND);
  1150. DC_EXIT_POINT:
  1151. DC_END_FN();
  1152. return;
  1153. } /* ChannelOnSuspended */
  1154. /**PROC+*********************************************************************/
  1155. /* Name: ChannelOnPacketReceived */
  1156. /* */
  1157. /* Purpose: Called when data is received from the Server */
  1158. /* */
  1159. /* Returns: none */
  1160. /* */
  1161. /* Params: pData - data received */
  1162. /* dataLen - length of data received */
  1163. /* flags - security flags (meaningless to this function) */
  1164. /* channelID - ID of channel on which data received */
  1165. /* priority - priority on which data was sent */
  1166. /* */
  1167. /**PROC-*********************************************************************/
  1168. DCVOID DCCALLBACK CChan::ChannelOnPacketReceived(PDCUINT8 pData,
  1169. DCUINT dataLen,
  1170. DCUINT flags,
  1171. DCUINT channelID,
  1172. DCUINT priority)
  1173. {
  1174. UINT i;
  1175. PCHANNEL_PDU_HEADER pHdr;
  1176. UINT32 len;
  1177. DCTCHAR serverName[UT_MAX_ADDRESS_LENGTH];
  1178. UINT32 Hdrflags;
  1179. UINT32 Hdrlength;
  1180. DC_BEGIN_FN("ChannelOnPacketReceived");
  1181. UNREFERENCED_PARAMETER( priority );
  1182. UNREFERENCED_PARAMETER( flags );
  1183. /************************************************************************/
  1184. /* First of all, handle suspend/resume messages */
  1185. /************************************************************************/
  1186. if (dataLen < sizeof(CHANNEL_PDU_HEADER)) {
  1187. TRC_ERR((TB,_T("Not enough data: 0x%x need at least: 0x%x"),
  1188. dataLen, sizeof(CHANNEL_PDU_HEADER)));
  1189. DC_QUIT;
  1190. }
  1191. pHdr = (PCHANNEL_PDU_HEADER)pData;
  1192. memcpy(&Hdrflags,(UNALIGNED UINT32 *)&(pHdr->flags),sizeof(Hdrflags));
  1193. memcpy(&Hdrlength,(UNALIGNED UINT32 *)&(pHdr->length),sizeof(Hdrlength));
  1194. if (Hdrflags & CHANNEL_FLAG_SUSPEND)
  1195. {
  1196. TRC_ALT((TB, _T("VC suspended")));
  1197. /********************************************************************/
  1198. /* Treat as a disconnection */
  1199. /********************************************************************/
  1200. ChannelOnSuspended(0);
  1201. DC_QUIT;
  1202. }
  1203. if (Hdrflags & CHANNEL_FLAG_RESUME)
  1204. {
  1205. TRC_ALT((TB, _T("VC resumed")));
  1206. /********************************************************************/
  1207. /* Update our state */
  1208. /********************************************************************/
  1209. _connected = CONNECTION_VC;
  1210. _iChanResumeCount++;
  1211. /********************************************************************/
  1212. /* Call Connected callbacks */
  1213. /********************************************************************/
  1214. _pUi->UI_GetServerName(serverName, SIZE_TCHARS(serverName));
  1215. IntChannelCallCallbacks(CHANNEL_EVENT_REMOTE_CONTROL_STOP,
  1216. serverName,
  1217. UT_MAX_ADDRESS_LENGTH);
  1218. DC_QUIT;
  1219. }
  1220. /************************************************************************/
  1221. /* Check we're still connected */
  1222. /************************************************************************/
  1223. if ((_connected != CONNECTION_VC) &&
  1224. (_connected != CONNECTION_SUSPENDED))
  1225. {
  1226. TRC_ASSERT((_connected != CONNECTION_V1),
  1227. (TB,_T("Channel data received from V1 Server!")));
  1228. TRC_NRM((TB, _T("Discard packet received when we're not connected")));
  1229. DC_QUIT;
  1230. }
  1231. /************************************************************************/
  1232. /* Find the channel data for this channel */
  1233. /************************************************************************/
  1234. for (i = 0; i < _channelCount; i++)
  1235. {
  1236. if (_channelData[i].MCSChannelID == channelID)
  1237. {
  1238. //
  1239. // Note it's important to do the decompression even if the channel
  1240. // is closed otherwise the context could get out of sync
  1241. //
  1242. /****************************************************************/
  1243. /* call the callback */
  1244. /****************************************************************/
  1245. TRC_NRM((TB, _T("MCS channel %x = channel %d"), channelID, i));
  1246. pData = (PDCUINT8)(pHdr + 1);
  1247. len = dataLen - sizeof(CHANNEL_PDU_HEADER);
  1248. UCHAR vcCompressFlags = (Hdrflags >> VC_FLAG_COMPRESS_SHIFT) &
  1249. VC_FLAG_COMPRESS_MASK;
  1250. //Data that is returned to user
  1251. PDCUINT8 pVCUserData = pData;
  1252. UINT32 cbVCUserDataLen = len;
  1253. if(vcCompressFlags & PACKET_COMPRESSED)
  1254. {
  1255. UCHAR *buf;
  1256. int bufSize;
  1257. //Decompress channel data
  1258. if(vcCompressFlags & PACKET_FLUSHED)
  1259. {
  1260. initrecvcontext (&_pUi->_UI.Context1,
  1261. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  1262. PACKET_COMPR_TYPE_64K);
  1263. }
  1264. #ifdef DC_DEBUG
  1265. //Update compression stats (debug only)
  1266. _cbCompressedBytesRecvd += len;
  1267. #endif
  1268. if (decompress(pData,
  1269. len,
  1270. (vcCompressFlags & PACKET_AT_FRONT),
  1271. &buf,
  1272. &bufSize,
  1273. &_pUi->_UI.Context1,
  1274. (RecvContext2_Generic*)_pUi->_UI.pRecvContext2,
  1275. vcCompressFlags & PACKET_COMPR_TYPE_MASK))
  1276. {
  1277. if(!_pUserOutBuf)
  1278. {
  1279. _pUserOutBuf = (PUCHAR)UT_Malloc(_pUt, VC_USER_OUTBUF);
  1280. }
  1281. TRC_ASSERT(_pUserOutBuf, (TB,_T("_pUserOutBuf is NULL")));
  1282. TRC_ASSERT((bufSize < VC_USER_OUTBUF),
  1283. (TB,_T("Decompressed buffer to big!!!")));
  1284. if(_pUserOutBuf && (bufSize < VC_USER_OUTBUF))
  1285. {
  1286. //
  1287. // Make a copy of the buffer as we can't hand off
  1288. // a pointer to the decompression context to the
  1289. // user because a badly behaved plugin can corrupt
  1290. // the decompression context causing all sorts of
  1291. // horrible and hard to debug problems.
  1292. //
  1293. memcpy(_pUserOutBuf, buf, bufSize);
  1294. pVCUserData = _pUserOutBuf;
  1295. cbVCUserDataLen = bufSize;
  1296. }
  1297. else
  1298. {
  1299. DC_QUIT;
  1300. }
  1301. }
  1302. else {
  1303. TRC_ABORT((TB, _T("Decompression FAILURE!!!")));
  1304. _pSl->SL_DropLinkImmediate(SL_ERR_INVALIDPACKETFORMAT);
  1305. DC_QUIT;
  1306. }
  1307. }
  1308. #ifdef DC_DEBUG
  1309. //Update compression stats (debug only)
  1310. _cbBytesRecvd += len;
  1311. _cbDecompressedBytesRecvd += cbVCUserDataLen;
  1312. #endif
  1313. //
  1314. // Turn off header flags to hide internal
  1315. // protocol info from user
  1316. //
  1317. Hdrflags &= ~VC_FLAG_PRIVATE_PROTOCOL_MASK;
  1318. //
  1319. // Drop the packet at the last moment if the channel is closed
  1320. //
  1321. if (_channelData[i].status != CHANNEL_STATUS_OPEN)
  1322. {
  1323. TRC_ALT((TB, _T("Data received on un-opened channel %x"),
  1324. channelID));
  1325. DC_QUIT;
  1326. }
  1327. if(_channelData[i].pInitHandle->fUsingExApi)
  1328. {
  1329. _channelData[i].pOpenEventExFn(
  1330. _channelData[i].pInitHandle->lpParam,
  1331. i,
  1332. CHANNEL_EVENT_DATA_RECEIVED,
  1333. pVCUserData,
  1334. cbVCUserDataLen,
  1335. Hdrlength,
  1336. Hdrflags);
  1337. }
  1338. else
  1339. {
  1340. _channelData[i].pOpenEventFn(i,
  1341. CHANNEL_EVENT_DATA_RECEIVED,
  1342. pVCUserData,
  1343. cbVCUserDataLen,
  1344. Hdrlength,
  1345. Hdrflags);
  1346. }
  1347. DC_QUIT;
  1348. }
  1349. }
  1350. /************************************************************************/
  1351. /* If we get here, we didn't find this channel */
  1352. /************************************************************************/
  1353. TRC_ALT((TB, _T("Data received on unknown channel %x"), channelID));
  1354. DC_EXIT_POINT:
  1355. DC_END_FN();
  1356. return;
  1357. } /* ChannelOnPacketReceived */
  1358. /**PROC+*********************************************************************/
  1359. /* Name: ChannelOnBufferAvailable */
  1360. /* */
  1361. /* Purpose: Called when a buffer is available, after a write has failed */
  1362. /* because no buffer was available */
  1363. /* */
  1364. /* Returns: none */
  1365. /* */
  1366. /* Params: none */
  1367. /* */
  1368. /**PROC-*********************************************************************/
  1369. DCVOID DCCALLBACK CChan::ChannelOnBufferAvailable(DCVOID)
  1370. {
  1371. DC_BEGIN_FN("ChannelOnBufferAvailable");
  1372. /************************************************************************/
  1373. /* Kick the send process into restarting */
  1374. /************************************************************************/
  1375. TRC_NRM((TB, _T("Write pending %p"), _pFirstWrite));
  1376. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  1377. this,
  1378. CD_NOTIFICATION_FUNC(CChan,IntChannelSend),
  1379. CHANNEL_MSG_SEND);
  1380. DC_END_FN();
  1381. return;
  1382. } /* ChannelOnBufferAvailable */
  1383. /**PROC+*********************************************************************/
  1384. /* Name: ChannelOnConnecting */
  1385. /* */
  1386. /* Purpose: Called when a connection is being established - returns */
  1387. /* virtual channel user data to be sent to the Server */
  1388. /* */
  1389. /* Returns: None */
  1390. /* */
  1391. /* Params: ppChannel (returned) - virtual channel user data */
  1392. /* pChannelCount (returned) - number of channels returned */
  1393. /* */
  1394. /**PROC-*********************************************************************/
  1395. DCVOID DCCALLBACK CChan::ChannelOnConnecting(PPCHANNEL_DEF ppChannel,
  1396. PDCUINT32 pChannelCount)
  1397. {
  1398. DC_BEGIN_FN("ChannelOnConnecting");
  1399. //Reset the context on each new connection
  1400. _fNeedToResetContext = TRUE;
  1401. *ppChannel = _channel;
  1402. *pChannelCount = _channelCount;
  1403. DC_END_FN();
  1404. return;
  1405. } /* ChannelOnConnecting */
  1406. /**PROC+*********************************************************************/
  1407. /* Name: ChannelOnInitializing */
  1408. /* */
  1409. /* Purpose: Called when MSTSC Network Layer is initializing - loads all */
  1410. /* configured application DLLs */
  1411. /* */
  1412. /* Returns: none */
  1413. /* */
  1414. /* Params: none */
  1415. /* */
  1416. /**PROC-*********************************************************************/
  1417. DCVOID DCCALLBACK CChan::ChannelOnInitializing(DCVOID)
  1418. {
  1419. HINSTANCE hInst;
  1420. PDCTCHAR szAddinDllList = NULL;
  1421. DWORD status = ERROR_SUCCESS;
  1422. PRDPDR_DATA pdrInitData = NULL;
  1423. DC_BEGIN_FN("ChannelOnInitializing");
  1424. //
  1425. // Initialize private member pointers
  1426. //
  1427. _pCd = _pClientObjs->_pCdObject;
  1428. _pSl = _pClientObjs->_pSlObject;
  1429. _pUt = _pClientObjs->_pUtObject;
  1430. _pUi = _pClientObjs->_pUiObject;
  1431. /************************************************************************/
  1432. /* Create the exported function table */
  1433. /************************************************************************/
  1434. _channelEntryPoints.cbSize = sizeof(CHANNEL_ENTRY_POINTS);
  1435. _channelEntryPoints.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
  1436. hInst = _pUi->UI_GetInstanceHandle();
  1437. _channelEntryPoints.pVirtualChannelInit =
  1438. (PVIRTUALCHANNELINIT)(MakeProcInstance
  1439. ((FARPROC)VirtualChannelInit, hInst));
  1440. _channelEntryPoints.pVirtualChannelOpen =
  1441. (PVIRTUALCHANNELOPEN)(MakeProcInstance
  1442. ((FARPROC)VirtualChannelOpen, hInst));
  1443. _channelEntryPoints.pVirtualChannelClose =
  1444. (PVIRTUALCHANNELCLOSE)(MakeProcInstance
  1445. ((FARPROC)VirtualChannelClose, hInst));
  1446. _channelEntryPoints.pVirtualChannelWrite =
  1447. (PVIRTUALCHANNELWRITE)(MakeProcInstance
  1448. ((FARPROC)VirtualChannelWrite, hInst));
  1449. _channelEntryPointsEx.cbSize = sizeof(CHANNEL_ENTRY_POINTS);
  1450. _channelEntryPointsEx.protocolVersion = VIRTUAL_CHANNEL_VERSION_WIN2000;
  1451. _channelEntryPointsEx.pVirtualChannelInitEx =
  1452. (PVIRTUALCHANNELINITEX)(MakeProcInstance
  1453. ((FARPROC)VirtualChannelInitEx, hInst));
  1454. _channelEntryPointsEx.pVirtualChannelOpenEx =
  1455. (PVIRTUALCHANNELOPENEX)(MakeProcInstance
  1456. ((FARPROC)VirtualChannelOpenEx, hInst));
  1457. _channelEntryPointsEx.pVirtualChannelCloseEx =
  1458. (PVIRTUALCHANNELCLOSEEX)(MakeProcInstance
  1459. ((FARPROC)VirtualChannelCloseEx, hInst));
  1460. _channelEntryPointsEx.pVirtualChannelWriteEx =
  1461. (PVIRTUALCHANNELWRITEEX)(MakeProcInstance
  1462. ((FARPROC)VirtualChannelWriteEx, hInst));
  1463. //
  1464. // Initialize the single instance VC critical
  1465. // section lock. This is used to ensure only one
  1466. // VC plugin at a time can be in the Initialize fn.
  1467. //
  1468. //
  1469. __try
  1470. {
  1471. InitializeCriticalSection(&_VirtualChannelInitLock);
  1472. }
  1473. __except(EXCEPTION_EXECUTE_HANDLER)
  1474. {
  1475. status = GetExceptionCode();
  1476. }
  1477. if(ERROR_SUCCESS == status)
  1478. {
  1479. _fLockInitalized = TRUE;
  1480. }
  1481. else
  1482. {
  1483. //
  1484. // Without the lock we can't ensure we won't get re-entered
  1485. // because the API's did not make it clear that we did
  1486. // not support re-entrancy in the VirtualChannelInit fn
  1487. // so this is fatal just bail out and don't load plugins.
  1488. //
  1489. _fLockInitalized = FALSE;
  1490. TRC_ERR((TB,_T("InitializeCriticalSection failed 0x%x.")
  1491. _T("NOT LOADING PLUGINS"),status));
  1492. DC_QUIT;
  1493. }
  1494. //
  1495. // RDPDR is statically linked in
  1496. //
  1497. // Initialize and pass in initialization info to rdpdr
  1498. // rdpdr keeps a pointer to this struct accross connections
  1499. // (because there is no clean way to pass it back in again)
  1500. // On each connection, the core reinitalizes the struct settings.
  1501. _pUi->UI_InitRdpDrSettings();
  1502. pdrInitData = _pUi->UI_GetRdpDrInitData();
  1503. if(!_pUi->_UI.fDisableInternalRdpDr)
  1504. {
  1505. if(!IntChannelInitAddin( NULL, RDPDR_VirtualChannelEntryEx, NULL,WEBCTRL_DLL_NAME,
  1506. pdrInitData))
  1507. {
  1508. TRC_ERR((TB, _T("Failed to load internal addin 'RDPDR'")));
  1509. }
  1510. }
  1511. else
  1512. {
  1513. TRC_NRM((TB, _T("NOT LOADING Internal RDPDR, fDisableInternalRdpDr is set")));
  1514. }
  1515. //
  1516. // Ts ActiveX control's exposed interfaces to the virtual channel API
  1517. // are also statically linked in
  1518. //
  1519. if(!IntChannelInitAddin( NULL, MSTSCAX_VirtualChannelEntryEx, NULL, WEBCTRL_DLL_NAME,
  1520. (PVOID)_pUi->_UI.pUnkAxControlInstance))
  1521. {
  1522. TRC_NRM((TB, _T("Internal addin (scriptable vchans) did not load: possibly none requested")));
  1523. }
  1524. //Get a comma separated list of dll's to load (passed down from control)
  1525. szAddinDllList = _pUi->UI_GetVChanAddinList();
  1526. if(!szAddinDllList)
  1527. {
  1528. TRC_DBG((TB, _T("Not loading any external plugins")));
  1529. DC_QUIT;
  1530. }
  1531. else
  1532. {
  1533. PDCTCHAR szTok = NULL;
  1534. DCUINT len = DC_TSTRLEN(szAddinDllList);
  1535. PDCTCHAR szCopyAddinList = (PDCTCHAR) UT_Malloc( _pUt,sizeof(DCTCHAR) *
  1536. (len+1));
  1537. TRC_ASSERT(szCopyAddinList, (TB, _T("Could not allocate mem for addin list")));
  1538. if(!szCopyAddinList)
  1539. {
  1540. DC_QUIT;
  1541. }
  1542. StringCchCopy(szCopyAddinList, len+1, szAddinDllList);
  1543. szTok = DC_TSTRTOK( szCopyAddinList, _T(","));
  1544. while(szTok)
  1545. {
  1546. //
  1547. // Load the DLL
  1548. //
  1549. if (_tcsicmp(szTok, _T("rdpdr.dll")))
  1550. {
  1551. IntChannelLoad( szTok);
  1552. }
  1553. else
  1554. {
  1555. //
  1556. // Don't load the crusty rdpdr.dll since
  1557. // we have a newer better one built-in
  1558. //
  1559. TRC_ERR((TB,_T("Skiping load of rdpdr.dll")));
  1560. }
  1561. szTok = DC_TSTRTOK( NULL, _T(","));
  1562. }
  1563. UT_Free( _pUt, szCopyAddinList);
  1564. }
  1565. #ifdef DC_DEBUG
  1566. //Debug compression counters
  1567. _cbBytesRecvd = 0;
  1568. _cbCompressedBytesRecvd = 0;
  1569. _cbDecompressedBytesRecvd = 0;
  1570. _cbTotalBytesUserAskSend = 0;
  1571. _cbTotalBytesSent = 0;
  1572. _cbComprInput = 0;
  1573. _cbComprOutput = 0;
  1574. #endif
  1575. DC_EXIT_POINT:
  1576. DC_END_FN();
  1577. return;
  1578. } /* ChannelOnInitializing */
  1579. /****************************************************************************/
  1580. /****************************************************************************/
  1581. /* Internal Functions */
  1582. /****************************************************************************/
  1583. /****************************************************************************/
  1584. /**PROC+*********************************************************************/
  1585. /* Name: IntChannelCallCallbacks */
  1586. /* */
  1587. /* Purpose: Call all ChannelInitEvent callbacks with a specified event */
  1588. /* */
  1589. /* Returns: none */
  1590. /* */
  1591. /* Params: event - event to pass to callbacks */
  1592. /* pData - additional data */
  1593. /* dataLength - length of additional data */
  1594. /* */
  1595. /**PROC-*********************************************************************/
  1596. DCVOID DCINTERNAL CChan::IntChannelCallCallbacks(DCUINT event,
  1597. PDCVOID pData,
  1598. DCUINT dataLength)
  1599. {
  1600. PCHANNEL_INIT_HANDLE pInitHandle;
  1601. DCUINT altEvent, sentEvent;
  1602. if (event == CHANNEL_EVENT_REMOTE_CONTROL_START) {
  1603. altEvent = CHANNEL_EVENT_DISCONNECTED;
  1604. } else if (event == CHANNEL_EVENT_REMOTE_CONTROL_STOP) {
  1605. altEvent = CHANNEL_EVENT_CONNECTED;
  1606. } else {
  1607. altEvent = event;
  1608. }
  1609. DC_BEGIN_FN("IntChannelCallCallbacks");
  1610. pInitHandle = _pInitHandle;
  1611. while (pInitHandle != NULL)
  1612. {
  1613. if (pInitHandle->dwFlags & CHANNEL_FLAG_SHADOW_PERSISTENT) {
  1614. // The plug-in supports the new events, don't change it.
  1615. sentEvent = event;
  1616. } else {
  1617. // No support or the new event is not wanted.
  1618. sentEvent = altEvent;
  1619. }
  1620. if(pInitHandle->fUsingExApi)
  1621. {
  1622. TRC_NRM((TB, _T("Call callback (Ex) at %p, handle %p, event %d"),
  1623. pInitHandle->pInitEventExFn, pInitHandle, sentEvent));
  1624. pInitHandle->pInitEventExFn(pInitHandle->lpParam,
  1625. pInitHandle, sentEvent, pData, dataLength);
  1626. }
  1627. else
  1628. {
  1629. TRC_NRM((TB, _T("Call callback at %p, handle %p, event %d"),
  1630. pInitHandle->pInitEventFn, pInitHandle, sentEvent));
  1631. pInitHandle->pInitEventFn(pInitHandle, sentEvent, pData, dataLength);
  1632. }
  1633. pInitHandle = pInitHandle->pNext;
  1634. }
  1635. DC_END_FN();
  1636. return;
  1637. } /* IntChannelCallCallbacks */
  1638. /**PROC+*********************************************************************/
  1639. /* Name: IntChannelFreeLibrary */
  1640. /* */
  1641. /* Purpose: Decoupled function to unload a DLL */
  1642. /* */
  1643. /* Returns: none */
  1644. /* */
  1645. /* Params: value - hMod of DLL to free */
  1646. /* */
  1647. /**PROC-*********************************************************************/
  1648. DCVOID DCINTERNAL CChan::IntChannelFreeLibrary(DCUINT value)
  1649. {
  1650. BOOL bRc;
  1651. DC_BEGIN_FN("IntChannelFreeLibrary");
  1652. if(value)
  1653. {
  1654. //
  1655. // Statically linked extenstions (e.g RDPDR) have a null hModule
  1656. //
  1657. #ifdef OS_WIN32
  1658. bRc = FreeLibrary(
  1659. #ifndef OS_WINCE
  1660. (HMODULE)ULongToPtr(value)
  1661. #else
  1662. (HMODULE)value
  1663. #endif
  1664. );
  1665. if (bRc)
  1666. {
  1667. TRC_NRM((TB, _T("Free library %#x OK"), value));
  1668. }
  1669. else
  1670. {
  1671. TRC_ERR((TB, _T("Failed to free library %#x"), value));
  1672. }
  1673. #else //OS_WIN32
  1674. FreeLibrary((HMODULE)value);
  1675. #endif // OS_WIN32
  1676. }
  1677. DC_END_FN();
  1678. return;
  1679. } /* IntChannelFreeLibrary */
  1680. //
  1681. // IntChannelCompressData
  1682. // Compressed the buffer directly into the outbuf.
  1683. // Caller MUST decide if input buf is in size range for compression
  1684. // and should handle copying over the buffer directly in that case.
  1685. //
  1686. // Params:
  1687. // pSrcData - input buffer
  1688. // cbSrcLen - length of input buffer
  1689. // pOutBuf - output buffer
  1690. // pcbOutLen- compressed output size
  1691. // Returns:
  1692. // Compression result (see compress() fn)
  1693. //
  1694. UCHAR CChan::IntChannelCompressData(UCHAR* pSrcData, ULONG cbSrcLen,
  1695. UCHAR* pOutBuf, ULONG* pcbOutLen)
  1696. {
  1697. UCHAR compressResult = 0;
  1698. ULONG CompressedSize = cbSrcLen;
  1699. DC_BEGIN_FN("IntChannelCompressData");
  1700. TRC_ASSERT(((cbSrcLen > VC_MIN_COMPRESS_INPUT_BUF) &&
  1701. (cbSrcLen < VC_MAX_COMPRESSED_BUFFER)),
  1702. (TB,_T("Compression src len out of range: %d"),
  1703. cbSrcLen));
  1704. TRC_ASSERT(_pMPPCContext,(TB,_T("_pMPPCContext is null")));
  1705. //Attempt to compress directly into the outbuf
  1706. compressResult = compress(pSrcData,
  1707. pOutBuf,
  1708. &CompressedSize,
  1709. _pMPPCContext);
  1710. if(compressResult & PACKET_COMPRESSED)
  1711. {
  1712. //Successful compression.
  1713. TRC_ASSERT((CompressedSize >= CompressedSize),
  1714. (TB,_T("Compression created larger size than uncompr")));
  1715. compressResult |= _fCompressionFlushed;
  1716. _fCompressionFlushed = 0;
  1717. #ifdef DC_DEBUG
  1718. //Compr counters
  1719. _cbComprInput += cbSrcLen;
  1720. _cbComprOutput += CompressedSize;
  1721. #endif
  1722. }
  1723. else if(compressResult & PACKET_FLUSHED)
  1724. {
  1725. //Overran compression history, copy over the
  1726. //uncompressed buffer.
  1727. _fCompressionFlushed = PACKET_FLUSHED;
  1728. memcpy(pOutBuf, pSrcData, cbSrcLen);
  1729. _CompressFlushes++;
  1730. }
  1731. else
  1732. {
  1733. TRC_ALT((TB, _T("Compression FAILURE")));
  1734. }
  1735. DC_END_FN();
  1736. *pcbOutLen = CompressedSize;
  1737. return compressResult;
  1738. }
  1739. /**PROC+*********************************************************************/
  1740. /* Name: IntChannelSend */
  1741. /* */
  1742. /* Purpose: Internal function to send data to the Server */
  1743. /* */
  1744. /* Returns: None */
  1745. /* */
  1746. /* Params: value - message passed from caller */
  1747. /* */
  1748. /* Operation: Called on SND thread */
  1749. /* */
  1750. /**PROC-*********************************************************************/
  1751. DCVOID DCINTERNAL CChan::IntChannelSend(ULONG_PTR value)
  1752. {
  1753. PCHANNEL_WRITE_DECOUPLE pDecouple;
  1754. DCBOOL bRc;
  1755. PDCUINT8 pBuffer;
  1756. SL_BUFHND bufHnd;
  1757. PCHANNEL_PDU_HEADER pHdr;
  1758. ULONG thisLength;
  1759. DWORD chanIndex = 0xFDFDFDFD;
  1760. ULONG cbOutLen = 0;
  1761. UCHAR compressResult = 0;
  1762. BOOL fNeedToDirectCopy = TRUE;
  1763. DC_BEGIN_FN("IntChannelSend");
  1764. //
  1765. // CD passes param as PVOID
  1766. //
  1767. #ifndef DC_DEBUG
  1768. UNREFERENCED_PARAMETER(value);
  1769. #endif
  1770. /************************************************************************/
  1771. /* Assert parameters */
  1772. /************************************************************************/
  1773. TRC_ASSERT((value == CHANNEL_MSG_SEND),
  1774. (TB, _T("Unexpected value %d"), value));
  1775. /************************************************************************/
  1776. /* Exit immediately if there's nothing to do. */
  1777. /************************************************************************/
  1778. if (_pFirstWrite == NULL)
  1779. {
  1780. TRC_NRM((TB, _T("Nothing to do")));
  1781. DC_QUIT;
  1782. }
  1783. TRC_ASSERT((_pFirstWrite->signature == CHANNEL_DECOUPLE_SIGNATURE),
  1784. (TB,_T("Invalid first signature %#lx"), _pFirstWrite->signature));
  1785. TRC_ASSERT((_pLastWrite->signature == CHANNEL_DECOUPLE_SIGNATURE),
  1786. (TB,_T("Invalid last signature %#lx"), _pLastWrite->signature));
  1787. /************************************************************************/
  1788. /* Get the next queued request */
  1789. /************************************************************************/
  1790. pDecouple = _pFirstWrite;
  1791. /************************************************************************/
  1792. /* Calculate the length to send */
  1793. /************************************************************************/
  1794. thisLength = CHANNEL_CHUNK_LENGTH;
  1795. /************************************************************************/
  1796. /* Truncate the data sent if we're about to send more than is left */
  1797. /************************************************************************/
  1798. if (thisLength >= pDecouple->dataLeft)
  1799. {
  1800. thisLength = pDecouple->dataLeft;
  1801. pDecouple->flags |= CHANNEL_FLAG_LAST;
  1802. }
  1803. TRC_NRM((TB,
  1804. _T("pDecouple %p, src %p, this %lu, left %lu, flags %#lx"),
  1805. pDecouple, pDecouple->pNextData, thisLength,
  1806. pDecouple->dataLeft, pDecouple->flags));
  1807. /************************************************************************/
  1808. /* Get a buffer */
  1809. /************************************************************************/
  1810. bRc = _pSl->SL_GetBuffer(thisLength + sizeof(CHANNEL_PDU_HEADER),
  1811. &pBuffer, &bufHnd);
  1812. if (!bRc)
  1813. {
  1814. /********************************************************************/
  1815. /* Failed to get a buffer. This is not entirely unexpected and is */
  1816. /* most likely simply due to back-pressure. The write will be */
  1817. /* retried when a buffer becomes available (signalled by a call to */
  1818. /* ChannelOnBufferAvailable). */
  1819. /********************************************************************/
  1820. TRC_NRM((TB, _T("Failed to get %d-byte buffer"), thisLength +
  1821. sizeof(CHANNEL_PDU_HEADER)));
  1822. DC_QUIT;
  1823. }
  1824. /************************************************************************/
  1825. /* Fill in the Channel PDU */
  1826. /************************************************************************/
  1827. pHdr = (PCHANNEL_PDU_HEADER)pBuffer;
  1828. memcpy((UNALIGNED UINT32 *)&(pHdr->length),
  1829. &(pDecouple->dataLength),sizeof(pDecouple->dataLength));
  1830. memcpy((UNALIGNED UINT32 *)&(pHdr->flags),
  1831. &(pDecouple->flags),sizeof(pDecouple->flags));
  1832. cbOutLen = thisLength;
  1833. compressResult = 0;
  1834. fNeedToDirectCopy = TRUE;
  1835. if(_fCompressChannels &&
  1836. (pDecouple->chanOptions & CHANNEL_OPTION_COMPRESS_RDP))
  1837. {
  1838. if((thisLength > VC_MIN_COMPRESS_INPUT_BUF) &&
  1839. (thisLength < VC_MAX_COMPRESSED_BUFFER))
  1840. {
  1841. //Compress the packet
  1842. if(!_pMPPCContext)
  1843. {
  1844. //Deferred init of the send context
  1845. _pMPPCContext = (SendContext*) UT_Malloc(_pUt,
  1846. VC_MAX_COMPRESSED_BUFFER+
  1847. sizeof(SendContext));
  1848. if(!_pMPPCContext)
  1849. {
  1850. #ifdef OS_WINCE //Applies to OS_WINNT too
  1851. _pSl->SL_FreeBuffer(bufHnd);
  1852. #endif
  1853. TRC_ERR((TB,_T("Failed to alloc MPPC send context")));
  1854. DC_QUIT;
  1855. }
  1856. _fNeedToResetContext = TRUE;
  1857. }
  1858. #ifdef DEBUG_CCHAN_COMPRESSION
  1859. if (!_pDbgRcvDecompr8K)
  1860. {
  1861. _fDbgVCTriedAllocRecvContext = TRUE;
  1862. _pDbgRcvDecompr8K = (RecvContext2_8K*)
  1863. LocalAlloc(LPTR, sizeof(RecvContext2_8K));
  1864. if (_pDbgRcvDecompr8K)
  1865. {
  1866. _pDbgRcvDecompr8K->cbSize = sizeof(RecvContext2_8K);
  1867. initrecvcontext(&_DbgRcvContext1,
  1868. (RecvContext2_Generic*)_pDbgRcvDecompr8K,
  1869. PACKET_COMPR_TYPE_8K);
  1870. }
  1871. else
  1872. {
  1873. _fDbgAllocFailedForVCRecvContext = TRUE;
  1874. TRC_ERR((TB,_T("Fail to alloc debug decompression context")));
  1875. DC_QUIT;
  1876. }
  1877. }
  1878. #endif
  1879. if(_fNeedToResetContext)
  1880. {
  1881. //
  1882. //Reset the context at the start of every connection.
  1883. //
  1884. // Server only supports 8K compression from client
  1885. // i.e. it will only decompress with 8K of history
  1886. //
  1887. initsendcontext(_pMPPCContext, PACKET_COMPR_TYPE_8K);
  1888. _fNeedToResetContext = FALSE;
  1889. }
  1890. TRC_ASSERT((_pMPPCContext),
  1891. (TB,_T("_pMPPCContext is null")));
  1892. compressResult = IntChannelCompressData( (UCHAR*)pDecouple->pNextData,
  1893. thisLength,
  1894. (UCHAR*)(pHdr+1),
  1895. &cbOutLen );
  1896. if(0 != compressResult)
  1897. {
  1898. #ifdef DEBUG_CCHAN_COMPRESSION
  1899. //
  1900. // debug: decompresss the packet
  1901. //
  1902. PUCHAR pDecompOutBuf = NULL;
  1903. INT cbDecompLen;
  1904. if (compressResult & PACKET_COMPRESSED)
  1905. {
  1906. if (compressResult & PACKET_FLUSHED)
  1907. {
  1908. initrecvcontext(&_DbgRcvContext1,
  1909. (RecvContext2_Generic*)_pDbgRcvDecompr8K,
  1910. PACKET_COMPR_TYPE_8K);
  1911. }
  1912. if (decompress((PUCHAR)(pHdr+1),
  1913. cbOutLen,
  1914. (compressResult & PACKET_AT_FRONT), //0 start
  1915. &pDecompOutBuf,
  1916. &cbDecompLen,
  1917. &_DbgRcvContext1,
  1918. (RecvContext2_Generic*)_pDbgRcvDecompr8K,
  1919. PACKET_COMPR_TYPE_8K))
  1920. {
  1921. if (cbDecompLen != thisLength)
  1922. {
  1923. DbgUserPrint(_T("Decompress check failed. Inlen!=outlen\n"));
  1924. DbgUserPrint(_T("Mail tsstress - orig len %d, decompressed len %d\n"),
  1925. thisLength,cbDecompLen);
  1926. DbgUserPrint(_T("pHdr 0x%x, inlen %d\n"),
  1927. pHdr, thisLength);
  1928. DbgUserPrint(_T("compression result %d\n"),compressResult);
  1929. DbgUserPrint(_T("pDecompOutBuf 0x%x, cbDecompLen %d\n"),
  1930. pDecompOutBuf, cbDecompLen);
  1931. DebugBreak();
  1932. }
  1933. if (memcmp(pDecompOutBuf, (PUCHAR)(pDecouple->pNextData), cbDecompLen))
  1934. {
  1935. DbgUserPrint(_T("Decompressed buffer does not match original!"));
  1936. DbgUserPrint(_T("Mail tsstress!"));
  1937. DbgUserPrint(_T("pHdr 0x%x, inlen %d\n"),
  1938. pHdr, thisLength);
  1939. DbgUserPrint(_T("compression result %d\n"),compressResult);
  1940. DbgUserPrint(_T("pDecompOutBuf 0x%x, cbDecompLen %d\n"),
  1941. pDecompOutBuf, cbDecompLen);
  1942. DebugBreak();
  1943. }
  1944. }
  1945. else
  1946. {
  1947. DbgUserPrint(_T("Decompression check failed!"));
  1948. DbgUserPrint(_T("Mail tsstress!"));
  1949. DbgUserPrint(_T("pHdr 0x%x, inlen %d\n"),pHdr, thisLength);
  1950. DbgUserPrint(_T("compression result %d\n"),compressResult);
  1951. DbgUserPrint(_T("pDecompOutBuf 0x%x, cbDecompLen %d\n"),
  1952. pDecompOutBuf, cbDecompLen);
  1953. DebugBreak();
  1954. }
  1955. }
  1956. #endif
  1957. //Update the VC packet header flags with the compression info
  1958. UINT32 newFlags = (pDecouple->flags |
  1959. ((compressResult & VC_FLAG_COMPRESS_MASK) <<
  1960. VC_FLAG_COMPRESS_SHIFT));
  1961. memcpy((UNALIGNED UINT32 *)&(pHdr->flags),
  1962. &newFlags,sizeof(newFlags));
  1963. //Succesfully compressed no need to direct copy
  1964. fNeedToDirectCopy = FALSE;
  1965. cbOutLen += sizeof(CHANNEL_PDU_HEADER);
  1966. }
  1967. else
  1968. {
  1969. _iDbgCompressFailedCount++;
  1970. #ifdef DEBUG_CCHAN_COMPRESSION
  1971. DebugBreak();
  1972. #endif
  1973. TRC_ERR((TB, _T("IntChannelCompressData failed")));
  1974. _pSl->SL_FreeBuffer(bufHnd);
  1975. DC_QUIT;
  1976. }
  1977. }
  1978. }
  1979. //Copy buffer directly if compression not enabled
  1980. //or the buffer does not fit size range for compression
  1981. if(fNeedToDirectCopy)
  1982. {
  1983. DC_MEMCPY(pHdr+1, pDecouple->pNextData, thisLength);
  1984. cbOutLen = thisLength + sizeof(CHANNEL_PDU_HEADER);
  1985. }
  1986. #ifdef DC_DEBUG
  1987. //Compr counters
  1988. _cbTotalBytesUserAskSend += thisLength;
  1989. _cbTotalBytesSent += cbOutLen;
  1990. #endif
  1991. TRC_DATA_DBG("Send channel data", pBuffer, cbOutLen);
  1992. /************************************************************************/
  1993. /* Get the channel index */
  1994. /************************************************************************/
  1995. chanIndex = pDecouple->openHandle;
  1996. /************************************************************************/
  1997. /* Send the Channel PDU */
  1998. /************************************************************************/
  1999. _pSl->SL_SendPacket(pBuffer,
  2000. cbOutLen,
  2001. _channelData[chanIndex].SLFlags,
  2002. bufHnd,
  2003. _pUi->UI_GetClientMCSID(),
  2004. _channelData[chanIndex].MCSChannelID,
  2005. _channelData[chanIndex].priority);
  2006. /************************************************************************/
  2007. /* Set up for next iteration */
  2008. /************************************************************************/
  2009. pDecouple->pNextData = ((HPDCUINT8)(pDecouple->pNextData)) + thisLength;
  2010. pDecouple->dataLeft -= thisLength;
  2011. pDecouple->dataSent += thisLength;
  2012. pDecouple->flags = _channelData[chanIndex].VCFlags;
  2013. TRC_NRM((TB, _T("Done write %p, src %p, sent %lu, left %lu, flags %#lx"),
  2014. pDecouple, pDecouple->pNextData, pDecouple->dataSent,
  2015. pDecouple->dataLeft, pDecouple->flags));
  2016. /************************************************************************/
  2017. /* See if we've finished this operation */
  2018. /************************************************************************/
  2019. if (pDecouple->dataLeft <= 0)
  2020. {
  2021. /********************************************************************/
  2022. /* Remove the operation from the queue */
  2023. /********************************************************************/
  2024. _pFirstWrite = pDecouple->pNext;
  2025. if (_pFirstWrite == NULL)
  2026. {
  2027. TRC_NRM((TB, _T("Finished last write")));
  2028. _pLastWrite = NULL;
  2029. }
  2030. else
  2031. {
  2032. TRC_NRM((TB, _T("New first in queue: %p"), _pFirstWrite));
  2033. _pFirstWrite->pPrev = NULL;
  2034. }
  2035. /********************************************************************/
  2036. /* Operation complete - call the callback */
  2037. /********************************************************************/
  2038. TRC_NRM((TB, _T("Write %p complete"), pDecouple));
  2039. if(_channelData[chanIndex].pInitHandle->fUsingExApi)
  2040. {
  2041. TRC_ASSERT((NULL != _channelData[chanIndex].pOpenEventExFn),
  2042. (TB, _T("Callback %p, handle %ld"),
  2043. _channelData[chanIndex].pOpenEventExFn,
  2044. pDecouple->openHandle));
  2045. /************************************************************************/
  2046. /* Is the channel still open? This was checked in */
  2047. /* IntVirtualChannelWrite, but that was before the post to this thread. */
  2048. /* If the VC was closed, it's possible we no longer have callback */
  2049. /* pointers. */
  2050. /************************************************************************/
  2051. if (NULL != _channelData[chanIndex].pOpenEventExFn)
  2052. {
  2053. _channelData[chanIndex].pOpenEventExFn(
  2054. _channelData[chanIndex].pInitHandle->lpParam,
  2055. pDecouple->openHandle,
  2056. CHANNEL_EVENT_WRITE_COMPLETE,
  2057. pDecouple->pUserData,
  2058. 0, 0, 0);
  2059. }
  2060. }
  2061. else
  2062. {
  2063. TRC_ASSERT((NULL != _channelData[chanIndex].pOpenEventFn),
  2064. (TB, _T("Callback %p, handle %ld"),
  2065. _channelData[chanIndex].pOpenEventFn,
  2066. pDecouple->openHandle));
  2067. if (NULL != _channelData[chanIndex].pOpenEventFn)
  2068. {
  2069. _channelData[chanIndex].pOpenEventFn( pDecouple->openHandle,
  2070. CHANNEL_EVENT_WRITE_COMPLETE,
  2071. pDecouple->pUserData,
  2072. 0, 0, 0);
  2073. }
  2074. }
  2075. /********************************************************************/
  2076. /* Free the request */
  2077. /********************************************************************/
  2078. UT_Free( _pUt,pDecouple);
  2079. }
  2080. /************************************************************************/
  2081. /* Kick the process again if there's anything left to do */
  2082. /************************************************************************/
  2083. if (_pFirstWrite != NULL)
  2084. {
  2085. TRC_NRM((TB, _T("More work to do %p"), _pFirstWrite));
  2086. _pCd->CD_DecoupleSimpleNotification(CD_SND_COMPONENT,
  2087. this,
  2088. CD_NOTIFICATION_FUNC(CChan,IntChannelSend),
  2089. CHANNEL_MSG_SEND);
  2090. }
  2091. /************************************************************************/
  2092. /* Note that if we failed to get a buffer above, we won't kick the */
  2093. /* process into continuing. This is done later, on receipt of an */
  2094. /* OnBufferAvailable callback from SL. */
  2095. /************************************************************************/
  2096. DC_EXIT_POINT:
  2097. DC_END_FN();
  2098. return;
  2099. } /* IntChannelSend */
  2100. /**PROC+*********************************************************************/
  2101. /* Name: IntChannelWrite */
  2102. /* */
  2103. /* Purpose: Start writing data to the Server */
  2104. /* */
  2105. /* Returns: none */
  2106. /* */
  2107. /* Params: pData - CHANNEL_WRITE_DECOUPLE structure */
  2108. /* dataLength - length of pData */
  2109. /* */
  2110. /* Operation: Called on SND thread */
  2111. /* */
  2112. /**PROC-*********************************************************************/
  2113. DCVOID DCINTERNAL CChan::IntChannelWrite(PDCVOID pData, DCUINT dataLength)
  2114. {
  2115. PCHANNEL_WRITE_DECOUPLE pDecouple;
  2116. DC_BEGIN_FN("IntChannelWrite");
  2117. #ifndef DC_DEBUG
  2118. UNREFERENCED_PARAMETER(dataLength);
  2119. #endif
  2120. /************************************************************************/
  2121. /* Check parameters */
  2122. /************************************************************************/
  2123. TRC_ASSERT((dataLength == sizeof(PCHANNEL_WRITE_DECOUPLE)),
  2124. (TB, _T("Wrong size data: is/expect %d/%d"),
  2125. dataLength, sizeof(PCHANNEL_WRITE_DECOUPLE)));
  2126. TRC_ASSERT((((_pFirstWrite == NULL) && (_pLastWrite == NULL)) ||
  2127. ((_pFirstWrite != NULL) && (_pLastWrite != NULL))),
  2128. (TB,_T("Invalid queue, pFirst %p, pLast %p"),
  2129. _pFirstWrite, _pLastWrite));
  2130. pDecouple = *((PPCHANNEL_WRITE_DECOUPLE)pData);
  2131. TRC_NRM((TB, _T("Receive %p -> %p"), pData, pDecouple));
  2132. TRC_ASSERT((pDecouple->signature == CHANNEL_DECOUPLE_SIGNATURE),
  2133. (TB,_T("Invalid decouple signature %#lx"), pDecouple->signature));
  2134. /************************************************************************/
  2135. /* Add this request to the queue */
  2136. /************************************************************************/
  2137. if (_pFirstWrite == NULL)
  2138. {
  2139. /********************************************************************/
  2140. /* Empty queue */
  2141. /********************************************************************/
  2142. TRC_NRM((TB, _T("Empty queue")));
  2143. _pFirstWrite = pDecouple;
  2144. _pLastWrite = pDecouple;
  2145. }
  2146. else
  2147. {
  2148. /********************************************************************/
  2149. /* Non-empty queue */
  2150. /********************************************************************/
  2151. TRC_NRM((TB, _T("Non-empty queue: first %p, last %p"),
  2152. _pFirstWrite, _pLastWrite));
  2153. pDecouple->pPrev = _pLastWrite;
  2154. _pLastWrite->pNext = pDecouple;
  2155. _pLastWrite = pDecouple;
  2156. }
  2157. TRC_ASSERT((_pFirstWrite->signature == CHANNEL_DECOUPLE_SIGNATURE),
  2158. (TB,_T("Invalid first signature %#lx"), _pFirstWrite->signature));
  2159. TRC_ASSERT((_pLastWrite->signature == CHANNEL_DECOUPLE_SIGNATURE),
  2160. (TB,_T("Invalid last signature %#lx"), _pLastWrite->signature));
  2161. /************************************************************************/
  2162. /* Try to send the data */
  2163. /************************************************************************/
  2164. IntChannelSend(CHANNEL_MSG_SEND);
  2165. DC_END_FN();
  2166. return;
  2167. } /* IntChannelWrite */
  2168. /**PROC+*********************************************************************/
  2169. /* Name: IntChannelLoad */
  2170. /* */
  2171. /* Purpose: Load an Addin */
  2172. /* */
  2173. /* Returns: none */
  2174. /* */
  2175. /* Params: DLLName - name of Addin DLL to load */
  2176. /* */
  2177. /**PROC-*********************************************************************/
  2178. DCVOID DCINTERNAL CChan::IntChannelLoad(PDCTCHAR DLLName)
  2179. {
  2180. DCBOOL rc = FALSE;
  2181. PVIRTUALCHANNELENTRY pChannelEntry;
  2182. PVIRTUALCHANNELENTRYEX pChannelEntryEx;
  2183. HMODULE hMod;
  2184. PCHANNEL_INIT_HANDLE pAddin;
  2185. DC_BEGIN_FN("IntChannelLoad");
  2186. /************************************************************************/
  2187. /* Load the DLL */
  2188. /************************************************************************/
  2189. hMod = LoadLibrary(DLLName);
  2190. if (!hMod)
  2191. {
  2192. TRC_ERR((TB, _T("Failed to load %s"), DLLName));
  2193. DC_QUIT;
  2194. }
  2195. TRC_NRM((TB, _T("Loaded %s (%p)"), DLLName, hMod));
  2196. /************************************************************************/
  2197. /* Search the already-loaded Addins in case this is a duplicate */
  2198. /************************************************************************/
  2199. for (pAddin = _pInitHandle; pAddin != NULL; pAddin = pAddin->pNext)
  2200. {
  2201. TRC_DBG((TB, _T("Compare %s, %p, %p"), DLLName, pAddin->hMod, hMod));
  2202. if (pAddin->hMod == hMod)
  2203. {
  2204. TRC_ERR((TB, _T("Reloading %s (%p)"), DLLName, hMod));
  2205. DC_QUIT;
  2206. }
  2207. }
  2208. /************************************************************************/
  2209. /* DLL loaded OK - find its VirtualChannelEntry function */
  2210. /************************************************************************/
  2211. //
  2212. // First try to find the Ex entry point
  2213. //
  2214. pChannelEntryEx = (PVIRTUALCHANNELENTRYEX)GetProcAddress(hMod,
  2215. CE_WIDETEXT("VirtualChannelEntryEx"));
  2216. if(pChannelEntryEx)
  2217. {
  2218. TRC_NRM((TB,_T("Found EX entry point, Init using ex api: %s"), DLLName));
  2219. IntChannelInitAddin( NULL, pChannelEntryEx, hMod, DLLName, NULL);
  2220. }
  2221. else
  2222. {
  2223. //
  2224. // Only try to load legacy DLL's from the first instance
  2225. //
  2226. if( CChan::pStaticClientInstance == this)
  2227. {
  2228. TRC_NRM((TB,_T("Did not find EX entry point, looking for old api: %s"), DLLName));
  2229. pChannelEntry = (PVIRTUALCHANNELENTRY)GetProcAddress(hMod,
  2230. CE_WIDETEXT("VirtualChannelEntry"));
  2231. if (pChannelEntry == NULL)
  2232. {
  2233. TRC_ERR((TB, _T("Failed to find VirtualChannelEntry in %s"),
  2234. DLLName));
  2235. DC_QUIT;
  2236. }
  2237. IntChannelInitAddin( pChannelEntry, NULL, hMod, DLLName, NULL);
  2238. }
  2239. }
  2240. DC_EXIT_POINT:
  2241. DC_END_FN();
  2242. return;
  2243. } /* IntChannelLoad */
  2244. /**PROC+*********************************************************************/
  2245. /* Name: IntChannelInitAddin */
  2246. /* */
  2247. /* Purpose: Initialize addin given it's entry point */
  2248. /* */
  2249. /* Returns: Success flag */
  2250. /* */
  2251. /* Params: pChannelEntry - Addin entry point */
  2252. /* */
  2253. /**PROC-*********************************************************************/
  2254. DCBOOL DCINTERNAL CChan::IntChannelInitAddin(PVIRTUALCHANNELENTRY pChannelEntry,
  2255. PVIRTUALCHANNELENTRYEX pChannelEntryEx,
  2256. HMODULE hMod,
  2257. PDCTCHAR DLLName,
  2258. PVOID pPassParamToEx)
  2259. {
  2260. DCBOOL rc = FALSE;
  2261. PCHANNEL_ENTRY_POINTS pTempEntryPoints = NULL;
  2262. PCHANNEL_ENTRY_POINTS_EX pTempEntryPointsEx = NULL;
  2263. UINT i=0;
  2264. DC_BEGIN_FN("IntChannelInitAddin");
  2265. _newInitHandle = NULL;
  2266. if (pChannelEntry == NULL && pChannelEntryEx == NULL)
  2267. {
  2268. TRC_ERR((TB, _T("Invalid VirtualChannelEntry")));
  2269. DC_QUIT;
  2270. }
  2271. if (DLLName == NULL)
  2272. {
  2273. TRC_ERR((TB, _T("Invalid DLLName")));
  2274. DC_QUIT;
  2275. }
  2276. TRC_NRM((TB, _T("VirtualChannelEntry at %p"), pChannelEntry));
  2277. TRC_NRM((TB, _T("VirtualChannelEntryEx at %p"), pChannelEntryEx));
  2278. /************************************************************************/
  2279. /* Allocate and initialize a handle */
  2280. /************************************************************************/
  2281. _newInitHandle = (PCHANNEL_INIT_HANDLE)UT_Malloc( _pUt,sizeof(CHANNEL_INIT_HANDLE));
  2282. if (_newInitHandle == NULL)
  2283. {
  2284. TRC_ERR((TB, _T("Failed to allocate handle")));
  2285. DC_QUIT;
  2286. }
  2287. _newInitHandle->signature = CHANNEL_INIT_SIGNATURE;
  2288. _newInitHandle->hMod = hMod;
  2289. _newInitHandle->pInst = this;
  2290. //
  2291. //ChannelCount for this addin is marked as 0 now
  2292. //it will be updated by the plugin's calls to VirtualChannelInit
  2293. //if VirtualChannelEntry returns false, this count will be used
  2294. //to rollback any created channels.
  2295. //
  2296. _newInitHandle->channelCount = 0;
  2297. //
  2298. // Internal addin's can get params passed back down
  2299. // today this is used so the control can pass it's internal
  2300. // an interface pointer to the virtual channel scripting addin
  2301. //
  2302. _newInitHandle->lpInternalAddinParam = pPassParamToEx;
  2303. /************************************************************************/
  2304. /* Allocate and fill a temporary structure in which to pass the entry */
  2305. /* points. This keeps our global entry points structure safe from */
  2306. /* badly-behaved addins that could overwrite it and stop other addins */
  2307. /* from working correctly. Note that addins must copy this structure */
  2308. /* -- it is only valid during this call to VirtualChannelEntry. */
  2309. /************************************************************************/
  2310. if(pChannelEntryEx)
  2311. {
  2312. pTempEntryPointsEx = (PCHANNEL_ENTRY_POINTS_EX)UT_Malloc(
  2313. _pUt,sizeof(CHANNEL_ENTRY_POINTS_EX));
  2314. if (pTempEntryPointsEx == NULL)
  2315. {
  2316. TRC_ERR((TB, _T("Failed to allocate temporary entry points (Ex) structure")));
  2317. DC_QUIT;
  2318. }
  2319. DC_MEMCPY(pTempEntryPointsEx,
  2320. &_channelEntryPointsEx,
  2321. sizeof(CHANNEL_ENTRY_POINTS_EX));
  2322. }
  2323. else
  2324. {
  2325. pTempEntryPoints = (PCHANNEL_ENTRY_POINTS)UT_Malloc( _pUt,sizeof(CHANNEL_ENTRY_POINTS));
  2326. if (pTempEntryPoints == NULL)
  2327. {
  2328. TRC_ERR((TB, _T("Failed to allocate temporary entry points structure")));
  2329. DC_QUIT;
  2330. }
  2331. DC_MEMCPY(pTempEntryPoints,
  2332. &_channelEntryPoints,
  2333. sizeof(CHANNEL_ENTRY_POINTS));
  2334. }
  2335. /************************************************************************/
  2336. /* Call VirtualChannelEntry */
  2337. /************************************************************************/
  2338. _ChannelInitCalled = FALSE;
  2339. _inChannelEntry = TRUE;
  2340. if(pChannelEntryEx)
  2341. {
  2342. //
  2343. // Pass the adddin a pointer to the new init handle
  2344. //
  2345. rc = pChannelEntryEx(pTempEntryPointsEx, _newInitHandle);
  2346. }
  2347. else
  2348. {
  2349. rc = pChannelEntry(pTempEntryPoints);
  2350. }
  2351. _inChannelEntry = FALSE;
  2352. if (!rc)
  2353. {
  2354. TRC_NRM((TB, _T("ChannelEntry aborted")));
  2355. DC_QUIT;
  2356. }
  2357. /************************************************************************/
  2358. /* Make sure that the Addin called VirtualChannelInit from */
  2359. /* VirtualChannelEntry */
  2360. /************************************************************************/
  2361. if (!_ChannelInitCalled)
  2362. {
  2363. TRC_ERR((TB, _T("Addin %s didn't call VirtualChannelInit"), DLLName));
  2364. rc = FALSE;
  2365. DC_QUIT;
  2366. }
  2367. /************************************************************************/
  2368. /* Everything OK - insert this handle into chain of Init Handles */
  2369. /************************************************************************/
  2370. _newInitHandle->pPrev = NULL;
  2371. _newInitHandle->pNext = _pInitHandle;
  2372. if (_pInitHandle != NULL)
  2373. {
  2374. _pInitHandle->pPrev = _newInitHandle;
  2375. }
  2376. _pInitHandle = _newInitHandle;
  2377. rc = TRUE;
  2378. DC_EXIT_POINT:
  2379. if (!rc)
  2380. {
  2381. TRC_NRM((TB, _T("Something failed - tidy up")));
  2382. if (hMod)
  2383. {
  2384. TRC_NRM((TB, _T("Free the library")));
  2385. FreeLibrary(hMod);
  2386. }
  2387. if (_newInitHandle)
  2388. {
  2389. //
  2390. // Remove any channel entries that were created
  2391. // for this plugin. These should be consecutive channels at the tail
  2392. // of the channels array.
  2393. //
  2394. if(_newInitHandle->channelCount)
  2395. {
  2396. UINT startRemoveIdx = _channelCount - _newInitHandle->channelCount;
  2397. TRC_ASSERT((startRemoveIdx < _channelCount),
  2398. (TB,_T("startRemoveIdx for channel cleanup is invalid")));
  2399. if(startRemoveIdx < _channelCount)
  2400. {
  2401. //
  2402. // Rollback creation of virtual channels
  2403. //
  2404. for( i=startRemoveIdx; i<_channelCount; i++)
  2405. {
  2406. TRC_ASSERT((_channelData[i].pInitHandle == _newInitHandle),
  2407. (TB,_T("_channelData[i].pInitHandle != _newInitHandle on rollback")));
  2408. if(_channelData[i].pInitHandle == _newInitHandle)
  2409. {
  2410. _channel[i].options = ~CHANNEL_OPTION_INITIALIZED;
  2411. DC_MEMSET(_channel[i].name, 0, CHANNEL_NAME_LEN+1);
  2412. _channelData[i].pOpenEventExFn = NULL;
  2413. _channelData[i].pOpenEventFn = NULL;
  2414. _channelData[i].status = CHANNEL_STATUS_CLOSED;
  2415. }
  2416. else
  2417. {
  2418. break;
  2419. }
  2420. }
  2421. _channelCount -= _newInitHandle->channelCount;
  2422. }
  2423. }
  2424. TRC_NRM((TB, _T("Free unused handle")));
  2425. UT_Free( _pUt,_newInitHandle);
  2426. }
  2427. }
  2428. if (pTempEntryPoints)
  2429. {
  2430. UT_Free( _pUt,pTempEntryPoints);
  2431. }
  2432. if (pTempEntryPointsEx)
  2433. {
  2434. UT_Free( _pUt, pTempEntryPointsEx);
  2435. }
  2436. DC_END_FN();
  2437. return rc;
  2438. } /* IntChannelInitAddin */
  2439. /**PROC+*********************************************************************/
  2440. /* Name: IntChannelCancelSend */
  2441. /* */
  2442. /* Purpose: Cancel outstanding send requests */
  2443. /* */
  2444. /* Returns: none */
  2445. /* */
  2446. /* Params: value - message passed from caller */
  2447. /* */
  2448. /* Operation: Called on SND thread */
  2449. /* */
  2450. /* */
  2451. /**PROC-*********************************************************************/
  2452. DCVOID DCINTERNAL CChan::IntChannelCancelSend(ULONG_PTR value)
  2453. {
  2454. PCHANNEL_WRITE_DECOUPLE pDecouple;
  2455. PCHANNEL_WRITE_DECOUPLE pFree;
  2456. DWORD chanIndex = 0xFDFDFDFD;
  2457. DC_BEGIN_FN("IntChannelCancelSend");
  2458. //UNREFERENCED_PARAMETER( value );
  2459. pDecouple = _pFirstWrite;
  2460. while (pDecouple != NULL)
  2461. {
  2462. TRC_ASSERT((pDecouple->signature == CHANNEL_DECOUPLE_SIGNATURE),
  2463. (TB,_T("Invalid decouple signature %#lx"), pDecouple->signature));
  2464. chanIndex = pDecouple->openHandle;
  2465. if ((value == CHANNEL_MSG_SUSPEND) &&
  2466. (_channelData[chanIndex].VCFlags & CHANNEL_FLAG_SHADOW_PERSISTENT)) {
  2467. // skip this one as it should not be closed
  2468. pDecouple = pDecouple->pNext;
  2469. continue;
  2470. }
  2471. /********************************************************************/
  2472. /* Call the callback */
  2473. /********************************************************************/
  2474. TRC_NRM((TB, _T("Write %p cancelled"), pDecouple));
  2475. if(_channelData[chanIndex].pInitHandle->fUsingExApi)
  2476. {
  2477. _channelData[chanIndex].pOpenEventExFn(
  2478. _channelData[chanIndex].pInitHandle->lpParam,
  2479. pDecouple->openHandle,
  2480. CHANNEL_EVENT_WRITE_CANCELLED,
  2481. pDecouple->pUserData,
  2482. 0, 0, 0);
  2483. }
  2484. else
  2485. {
  2486. _channelData[chanIndex].pOpenEventFn( pDecouple->openHandle,
  2487. CHANNEL_EVENT_WRITE_CANCELLED,
  2488. pDecouple->pUserData,
  2489. 0, 0, 0);
  2490. }
  2491. /********************************************************************/
  2492. /* Free the decouple structure */
  2493. /********************************************************************/
  2494. pFree = pDecouple;
  2495. pDecouple = pDecouple->pNext;
  2496. if (pDecouple) {
  2497. pDecouple->pPrev = pFree->pPrev;
  2498. } else {
  2499. _pLastWrite = pFree->pPrev;
  2500. }
  2501. if (pFree->pPrev) {
  2502. pFree->pPrev->pNext = pDecouple;
  2503. } else {
  2504. _pFirstWrite = pDecouple;
  2505. }
  2506. pFree->signature = 0;
  2507. UT_Free( _pUt,pFree);
  2508. }
  2509. if (value != CHANNEL_MSG_SUSPEND) {
  2510. _pFirstWrite = NULL;
  2511. _pLastWrite = NULL;
  2512. }
  2513. DC_END_FN();
  2514. return;
  2515. } /* IntChannelCancelSend */