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.

773 lines
22 KiB

  1. /**MOD+**********************************************************************/
  2. /* Module: vchannel.cpp */
  3. /* */
  4. /* Purpose: internal handling of the exposed virtual channel interfaces */
  5. /* */
  6. /* Copyright(C) Microsoft Corporation 1999 */
  7. /* */
  8. /****************************************************************************/
  9. #include "stdafx.h"
  10. #include "atlwarn.h"
  11. //IDL generated header
  12. #include "mstsax.h"
  13. #include "mstscax.h"
  14. #include "vchannel.h"
  15. #include "cleanup.h"
  16. #define TRC_GROUP TRC_GROUP_UI
  17. #define TRC_FILE "vchannel"
  18. #include <atrcapi.h>
  19. CVChannels::CVChannels()
  20. {
  21. DC_BEGIN_FN("~CVChannels");
  22. _pChanInfo = NULL;
  23. _pEntryPoints = NULL;
  24. _dwConnectState = NOTHING;
  25. _phInitHandle = NULL;
  26. _ChanCount = NULL;
  27. _hwndControl = NULL;
  28. DC_END_FN();
  29. }
  30. CVChannels::~CVChannels()
  31. {
  32. UINT i;
  33. DC_BEGIN_FN("~CVChannels");
  34. if (_pChanInfo) {
  35. //
  36. // Free any incomplete channel receive buffers
  37. //
  38. for (i=0; i<_ChanCount; i++) {
  39. if (_pChanInfo[i].CurrentlyReceivingData.pData) {
  40. SysFreeString((BSTR)_pChanInfo[i].CurrentlyReceivingData.pData);
  41. _pChanInfo[i].CurrentlyReceivingData.pData = NULL;
  42. }
  43. }
  44. LocalFree(_pChanInfo);
  45. _pChanInfo = NULL;
  46. }
  47. DC_END_FN();
  48. }
  49. /*****************************************************************************
  50. *
  51. * Routine Description:
  52. * Return the channel index for a given open channel handle
  53. *
  54. * Arguments:
  55. * dwHandle - handle to the channel
  56. *
  57. * Return Value:
  58. * index to the channel in the _pChanInfo array or -1 if not found
  59. *
  60. *****************************************************************************/
  61. DCINT CVChannels::ChannelIndexFromOpenHandle(DWORD dwHandle)
  62. {
  63. DCUINT i;
  64. DC_BEGIN_FN("ChannelIndexFromOpenHandle");
  65. TRC_ASSERT((_pChanInfo), (TB,_T("_pChanInfo is NULL")));
  66. if (!_pChanInfo)
  67. {
  68. DC_QUIT;
  69. }
  70. for (i=0;i<_ChanCount;i++)
  71. {
  72. if (_pChanInfo[i].dwOpenHandle == dwHandle)
  73. {
  74. return i;
  75. }
  76. }
  77. DC_END_FN();
  78. DC_EXIT_POINT:
  79. return -1;
  80. }
  81. /*****************************************************************************
  82. *
  83. * Routine Description:
  84. * Return the channel index for a given channel name
  85. *
  86. * Arguments:
  87. * szChanName - name of channel
  88. *
  89. * Return Value:
  90. * index to the channel in the _pChanInfo array or -1 if not found
  91. *
  92. *****************************************************************************/
  93. DCINT CVChannels::ChannelIndexFromName(PDCACHAR szChanName)
  94. {
  95. DCUINT i;
  96. DC_BEGIN_FN("ChannelIndexFromName");
  97. TRC_ASSERT((_pChanInfo), (TB,_T("_pChanInfo is NULL")));
  98. TRC_ASSERT((szChanName), (TB,_T("szChanName is NULL")));
  99. if (!_pChanInfo || !szChanName)
  100. {
  101. DC_QUIT;
  102. }
  103. for (i=0;i<_ChanCount;i++)
  104. {
  105. if (!DC_ASTRNCMP(_pChanInfo[i].chanName,szChanName,
  106. sizeof(_pChanInfo[i].chanName)))
  107. {
  108. return i;
  109. }
  110. }
  111. DC_END_FN();
  112. DC_EXIT_POINT:
  113. return -1;
  114. }
  115. /*****************************************************************************
  116. *
  117. * Routine Description:
  118. * Sends data on a given virtual channel
  119. *
  120. * Arguments:
  121. * chanIndex : index of the channel to send on
  122. * pdata : pointer to the data
  123. * datalength : length of data
  124. *
  125. * Return Value:
  126. * nothing. write is asynchronous so no notification at this point
  127. *
  128. *****************************************************************************/
  129. DCBOOL CVChannels::SendDataOnChannel(DCUINT chanIndex, LPVOID pdata, DWORD datalength)
  130. {
  131. DC_BEGIN_FN("SendDataOnNamedChannel");
  132. DCBOOL bRetVal = TRUE;
  133. if (_dwConnectState != NON_V1_CONNECT)
  134. {
  135. TRC_DBG((TB,_T("MsTscAx Vchannel: Error: SendDataOnNamedChannel when not connected\n")));
  136. return FALSE;
  137. }
  138. TRC_ASSERT((_pEntryPoints), (TB,_T("_pEntryPoints is NULL")));
  139. if (!_pEntryPoints)
  140. {
  141. bRetVal = FALSE;
  142. DC_QUIT;
  143. }
  144. TRC_ASSERT((chanIndex < _ChanCount),
  145. (TB,_T("chanIndex out of range!!!")));
  146. if (chanIndex >= _ChanCount)
  147. {
  148. TRC_DBG((TB,_T("MsTscAx Vchannel: chanIndex out of range\n")));
  149. bRetVal = FALSE;
  150. DC_QUIT;
  151. }
  152. if (!_pChanInfo[chanIndex].fIsOpen || !_pChanInfo[chanIndex].fIsValidChannel)
  153. {
  154. TRC_DBG((TB,_T("MsTscAx Vchannel: channel not open or invalid channel\n")));
  155. bRetVal = FALSE;
  156. DC_QUIT;
  157. }
  158. if (CHANNEL_RC_OK !=
  159. _pEntryPoints->pVirtualChannelWriteEx(_phInitHandle,
  160. _pChanInfo[chanIndex].dwOpenHandle,
  161. pdata,
  162. datalength,
  163. pdata))
  164. {
  165. bRetVal = FALSE;
  166. DC_QUIT;
  167. }
  168. //
  169. // pdata will be freed when a write complete notification is received
  170. //
  171. DC_EXIT_POINT:
  172. DC_END_FN();
  173. return bRetVal;
  174. }
  175. /*****************************************************************************
  176. *
  177. * Routine Description:
  178. * Handle a data received notification
  179. *
  180. * Arguments:
  181. * chanIndex : index to the channel
  182. * pdata : if the event was data received, then this is the pointer
  183. * to data
  184. * datalength : length of data available
  185. * totalLength : totallength sent by server at a time.
  186. * dataFlags : Not Used
  187. *
  188. * Return Value:
  189. * TRUE if data was successfully received
  190. *
  191. *****************************************************************************/
  192. DCBOOL CVChannels::HandleReceiveData(IN DCUINT chanIndex,
  193. IN LPVOID pdata,
  194. IN UINT32 dataLength,
  195. IN UINT32 totalLength,
  196. IN UINT32 dataFlags)
  197. {
  198. DCBOOL bRetVal = TRUE;
  199. DC_BEGIN_FN("HandleReceiveData");
  200. TRC_ASSERT((chanIndex < _ChanCount),
  201. (TB,_T("chanIndex out of range!!!")));
  202. if (chanIndex >= _ChanCount)
  203. {
  204. TRC_DBG((TB,_T("MsTscAx Vchannel: chanIndex out of range\n")));
  205. DC_QUIT;
  206. }
  207. //
  208. // Server request has been received by DLL. Read it and store it
  209. // for later use.
  210. //
  211. if (dataFlags & CHANNEL_FLAG_FIRST)
  212. {
  213. TRC_DBG((TB,_T("MsTscAx Vchannel: Data Received first chunk\n")));
  214. PCHANDATA pReceivedData = &_pChanInfo[chanIndex].CurrentlyReceivingData;
  215. pReceivedData->chanDataState = dataIncompleteAssemblingChunks;
  216. pReceivedData->dwDataLen = totalLength;
  217. //
  218. // The data buffer is stored in a BSTR
  219. // because it eventually gets handed out to the caller
  220. // in an out parameter (the caller frees)
  221. //
  222. TRC_ASSERT((NULL == _pChanInfo[chanIndex].CurrentlyReceivingData.pData),
  223. (TB,_T("_pChanInfo[chanIndex].CurrentlyReceivingData.pData is NOT NULL.") \
  224. _T("Are we losing received data?")));
  225. pReceivedData->pData = (LPVOID) SysAllocStringByteLen(NULL, totalLength);
  226. if(!pReceivedData->pData)
  227. {
  228. LocalFree(pReceivedData);
  229. TRC_ERR((TB,_T("Failed to allocate BSTR for received data in HandleReceiveData\n")));
  230. DC_QUIT;
  231. }
  232. DC_MEMCPY( pReceivedData->pData, pdata, dataLength);
  233. pReceivedData->pCurWritePointer = (LPBYTE)pReceivedData->pData + dataLength;
  234. if (dataFlags & CHANNEL_FLAG_LAST)
  235. {
  236. //
  237. // chunk is both first and last, we're done
  238. //
  239. pReceivedData->chanDataState = dataReceivedComplete;
  240. }
  241. }
  242. else // middle or last block
  243. {
  244. TRC_ASSERT((_pChanInfo[chanIndex].CurrentlyReceivingData.pData),
  245. (TB,_T("_pChanInfo[chanIndex].CurrentlyReceivingData.pData is NULL.") \
  246. _T("While receiving CHANNEL_FLAG_MIDDLE data!!!!")));
  247. PCHANDATA pReceivedData = &_pChanInfo[chanIndex].CurrentlyReceivingData;
  248. TRC_ASSERT((pReceivedData->pData && pReceivedData->pCurWritePointer),
  249. (TB,_T("_pChanInfo[chanIndex].pCurrentlyReceivingData write pointer(s) are NULL.")));
  250. if (!pReceivedData->pData || !pReceivedData->pCurWritePointer)
  251. {
  252. bRetVal = FALSE;
  253. DC_QUIT;
  254. }
  255. //
  256. // Sanity check that the write pointer is within the data buffer
  257. //
  258. LPBYTE pEnd = (LPBYTE)pReceivedData->pData + pReceivedData->dwDataLen;
  259. if (pReceivedData->pCurWritePointer < (LPBYTE)pReceivedData->pData ||
  260. pReceivedData->pCurWritePointer + dataLength > pEnd) {
  261. TRC_ASSERT(0,(TB,_T("pCurWritePointer is outside valid range")));
  262. bRetVal = FALSE;
  263. DC_QUIT;
  264. }
  265. DC_MEMCPY( pReceivedData->pCurWritePointer, pdata, dataLength);
  266. pReceivedData->pCurWritePointer += dataLength;
  267. if (dataFlags & CHANNEL_FLAG_LAST)
  268. {
  269. //
  270. // chunk is both first and last, we're done
  271. //
  272. pReceivedData->chanDataState = dataReceivedComplete;
  273. }
  274. }
  275. //
  276. // If a complete chunk was received add it to the receive list
  277. //
  278. if (dataReceivedComplete == _pChanInfo[chanIndex].CurrentlyReceivingData.chanDataState )
  279. {
  280. //Non blocking read, notify the window so it can
  281. //fire an event to the container
  282. if (_hwndControl)
  283. {
  284. PostMessage( _hwndControl,
  285. WM_VCHANNEL_DATARECEIVED, (WPARAM)chanIndex,
  286. (LPARAM)_pChanInfo[chanIndex].CurrentlyReceivingData.pData);
  287. }
  288. _pChanInfo[chanIndex].CurrentlyReceivingData.chanDataState = dataIncompleteAssemblingChunks;
  289. _pChanInfo[chanIndex].CurrentlyReceivingData.dwDataLen = 0;
  290. _pChanInfo[chanIndex].CurrentlyReceivingData.pData = NULL;
  291. }
  292. DC_EXIT_POINT:
  293. DC_END_FN();
  294. return bRetVal;
  295. }
  296. VOID WINAPI CVChannels::IntVirtualChannelOpenEventEx(
  297. IN DWORD openHandle,
  298. IN UINT event,
  299. IN LPVOID pdata,
  300. IN UINT32 dataLength,
  301. IN UINT32 totalLength,
  302. IN UINT32 dataFlags)
  303. {
  304. DC_BEGIN_FN("IntVirtualChannelOpenEventEx");
  305. DCUINT chanIndex = -1;
  306. TRC_ASSERT((_pChanInfo), (TB,_T("_pChanInfo is NULL")));
  307. if (!_pChanInfo)
  308. {
  309. DC_QUIT;
  310. }
  311. chanIndex = ChannelIndexFromOpenHandle(openHandle);
  312. if (-1 == chanIndex)
  313. {
  314. TRC_DBG((TB,_T("MsTscAx Vchannel: openHandle does not map to any known channel structure\n")));
  315. DC_QUIT;
  316. }
  317. TRC_ASSERT((chanIndex < _ChanCount), (TB,_T("chanIndex out of range!!!")));
  318. if (chanIndex >= _ChanCount)
  319. {
  320. TRC_DBG((TB,_T("MsTscAx Vchannel: chanIndex out of range\n")));
  321. DC_QUIT;
  322. }
  323. switch (event)
  324. {
  325. case CHANNEL_EVENT_DATA_RECEIVED:
  326. //
  327. // Receive and re-assemble data if necessary
  328. //
  329. HandleReceiveData(chanIndex, pdata, dataLength, totalLength, dataFlags);
  330. break;
  331. case CHANNEL_EVENT_WRITE_CANCELLED:
  332. TRC_DBG((TB,_T("MsTscAx Vchannel: Write cancelled\n")));
  333. // No BREAK HERE.
  334. case CHANNEL_EVENT_WRITE_COMPLETE:
  335. //
  336. // A write has completed.
  337. // All we have to do is free the data buffer
  338. // pdata is the send buffer
  339. //
  340. TRC_ASSERT((pdata), (TB,_T("pdata is NULL on WRITE_COMPLETE/CANCELED")));
  341. if (pdata)
  342. {
  343. LocalFree((HLOCAL) pdata);
  344. }
  345. break;
  346. default:
  347. TRC_DBG((TB,_T("MsTscAx Vchannel: unrecognized open event\n")));
  348. break;
  349. }
  350. DC_EXIT_POINT:
  351. DC_END_FN();
  352. }
  353. VOID
  354. VCAPITYPE CVChannels::IntVirtualChannelInitEventProcEx(
  355. IN LPVOID pInitHandle,
  356. IN UINT event,
  357. IN LPVOID pData,
  358. IN UINT dataLength)
  359. {
  360. UINT ui;
  361. UINT i;
  362. UNREFERENCED_PARAMETER(pInitHandle);
  363. UNREFERENCED_PARAMETER(pData);
  364. UNREFERENCED_PARAMETER(dataLength);
  365. DC_BEGIN_FN("IntVirtualChannelInitEventProc");
  366. TRC_ASSERT((_pChanInfo), (TB,_T("_pChanInfo is NULL")));
  367. if (!_pChanInfo)
  368. {
  369. DC_QUIT;
  370. }
  371. TRC_ASSERT((_pEntryPoints), (TB,_T("_pEntryPoints is NULL")));
  372. if (!_pEntryPoints)
  373. {
  374. DC_QUIT;
  375. }
  376. switch (event)
  377. {
  378. case CHANNEL_EVENT_INITIALIZED:
  379. TRC_DBG((TB,_T("MsTscAx Vchannel: channel initialized\n")));
  380. break;
  381. case CHANNEL_EVENT_CONNECTED:
  382. //
  383. // We have been connected to a server
  384. //
  385. _dwConnectState=NON_V1_CONNECT;
  386. TRC_DBG((TB,_T("MsTscAx Vchannel: channel connected\n")));
  387. for (i=0; i< _ChanCount; i++)
  388. {
  389. //
  390. // open channel
  391. //
  392. if(_pChanInfo[i].fIsValidChannel)
  393. {
  394. ui = _pEntryPoints->pVirtualChannelOpenEx(_phInitHandle,
  395. &_pChanInfo[i].dwOpenHandle,
  396. _pChanInfo[i].chanName,
  397. (PCHANNEL_OPEN_EVENT_EX_FN)
  398. VirtualChannelOpenEventEx);
  399. if (ui != CHANNEL_RC_OK)
  400. {
  401. TRC_DBG((TB,_T("MsTscAx Vchannel: virtual channel open failed\n")));
  402. continue;
  403. }
  404. _pChanInfo[i].fIsOpen = TRUE;
  405. }
  406. }
  407. break;
  408. case CHANNEL_EVENT_V1_CONNECTED:
  409. //
  410. // So nothing can be done in this case.
  411. //
  412. _dwConnectState=V1_CONNECT;
  413. TRC_DBG((TB,_T("MsTscAx Vchannel: v1 connected\n")));
  414. break;
  415. case CHANNEL_EVENT_DISCONNECTED:
  416. //
  417. // Disconnected from the Server so cleanup
  418. //
  419. TRC_DBG((TB,_T("MsTscAx Vchannel: disconnected\n")));
  420. if (_dwConnectState==NON_V1_CONNECT)
  421. {
  422. for (i=0; i< _ChanCount; i++)
  423. {
  424. //
  425. // Close the channel
  426. //
  427. if(_pChanInfo[i].fIsValidChannel)
  428. {
  429. _pEntryPoints->pVirtualChannelCloseEx(_phInitHandle,
  430. _pChanInfo[i].dwOpenHandle);
  431. _pChanInfo[i].fIsOpen = FALSE;
  432. }
  433. }
  434. }
  435. _dwConnectState=NOTHING;
  436. break;
  437. case CHANNEL_EVENT_TERMINATED:
  438. //
  439. // This means that process is exiting. So cleanup the memory
  440. //
  441. TRC_DBG((TB,_T("MsTscAx Vchannel: Terminated\n")));
  442. if (_pEntryPoints!=NULL)
  443. {
  444. LocalFree((HLOCAL)_pEntryPoints);
  445. _pEntryPoints=NULL;
  446. }
  447. break;
  448. default:
  449. TRC_DBG((TB,_T("MsTscAx Vchannel: unrecognized init event\n")));
  450. break;
  451. }
  452. DC_EXIT_POINT:
  453. DC_END_FN();
  454. }
  455. BEGIN_EXTERN_C
  456. /*****************************************************************************
  457. *
  458. * Routine Description:
  459. * Virtual Channel Entry function. This is the first function called to
  460. * start a virtual channel
  461. *
  462. * Arguments:
  463. * pEntryPoDCINTs : pointer to a PCHANNEL_ENTRY_POINT which contains
  464. * information about this virtual channel
  465. *
  466. * Return Value:
  467. * TRUE/FALSE : Depending on success of function.
  468. *
  469. *****************************************************************************/
  470. BOOL
  471. VCAPITYPE MSTSCAX_VirtualChannelEntryEx(IN PCHANNEL_ENTRY_POINTS_EX pEntryPoints,
  472. PVOID pInitHandle)
  473. {
  474. CHANNEL_DEF cd[CHANNEL_MAX_COUNT];
  475. UINT uRet;
  476. UINT i = 0;
  477. HRESULT hr;
  478. DC_BEGIN_FN("MSTSCAX_virtualchannelentryEx");
  479. if(!pInitHandle)
  480. {
  481. return FALSE;
  482. }
  483. PCHANNEL_INIT_HANDLE pChanInitHandle = (PCHANNEL_INIT_HANDLE)pInitHandle;
  484. CMsTscAx* pAxCtl = (CMsTscAx*)pChanInitHandle->lpInternalAddinParam;
  485. if(!pAxCtl)
  486. {
  487. return FALSE;
  488. }
  489. CVChannels* pVChans = &pAxCtl->_VChans;
  490. pVChans->_phInitHandle = pInitHandle;
  491. //
  492. // allocate memory
  493. //
  494. //
  495. // Check if the CHANINFO structures have been set up by the web control
  496. // if not then it means virtual channels are not requested
  497. //
  498. if (!pVChans->_pChanInfo || !pVChans->_ChanCount)
  499. {
  500. TRC_ALT((TB,_T("Returning FALSE. No channels requested\n")));
  501. return FALSE;
  502. }
  503. pVChans->_pEntryPoints = (PCHANNEL_ENTRY_POINTS_EX)
  504. LocalAlloc(LPTR, pEntryPoints->cbSize);
  505. if (pVChans->_pEntryPoints == NULL)
  506. {
  507. TRC_ERR((TB,_T("MsTscAx: LocalAlloc failed\n")));
  508. DC_END_FN();
  509. return FALSE;
  510. }
  511. memcpy(pVChans->_pEntryPoints, pEntryPoints, pEntryPoints->cbSize);
  512. //
  513. // initialize CHANNEL_DEF structures
  514. //
  515. ZeroMemory(&cd, sizeof(cd));
  516. //
  517. // Get comma separated channel names
  518. //
  519. for (i=0; i< pVChans->_ChanCount;i++)
  520. {
  521. hr = StringCchCopyA(cd[i].name,
  522. sizeof(cd[i].name), //ANSI buffer
  523. pVChans->_pChanInfo[i].chanName);
  524. if (SUCCEEDED(hr)) {
  525. cd[i].options = pVChans->_pChanInfo[i].channelOptions;
  526. }
  527. else {
  528. TRC_ERR((TB,_T("StringCchCopy error: 0x%x"), hr));
  529. return FALSE;
  530. }
  531. }
  532. //
  533. // register channels
  534. //
  535. uRet = pVChans->_pEntryPoints->pVirtualChannelInitEx(
  536. (LPVOID) pVChans,
  537. pVChans->_phInitHandle,
  538. (PCHANNEL_DEF)&cd,
  539. pVChans->_ChanCount,
  540. VIRTUAL_CHANNEL_VERSION_WIN2000,
  541. (PCHANNEL_INIT_EVENT_EX_FN)
  542. VirtualChannelInitEventProcEx);
  543. //
  544. // make sure channel(s) were initialized
  545. //
  546. if (CHANNEL_RC_OK == uRet)
  547. {
  548. for(i=0;i<pVChans->_ChanCount;i++)
  549. {
  550. pVChans->_pChanInfo[i].fIsValidChannel =
  551. ((cd[i].options & CHANNEL_OPTION_INITIALIZED) ? TRUE : FALSE);
  552. //Update the vc options so they can be retreived from script
  553. pVChans->_pChanInfo[i].channelOptions = cd[i].options;
  554. }
  555. }
  556. else
  557. {
  558. LocalFree((HLOCAL)pVChans->_pEntryPoints);
  559. pVChans->_pEntryPoints=NULL;
  560. DC_END_FN();
  561. return FALSE;
  562. }
  563. pVChans->_dwConnectState=NOTHING;
  564. DC_END_FN();
  565. return TRUE;
  566. }
  567. /*****************************************************************************
  568. *
  569. * Routine Description:
  570. * Virtual Channel Open callback function.
  571. *
  572. * Arguments:
  573. * openHandle : specifies which of the channels was opened
  574. * event : Kind of event that has occured
  575. * pdata : if the event was data received, then this is the pointer
  576. * to data
  577. * datalength : length of data available
  578. * totalLength : totallength sent by server at a time.
  579. * dataFlags : Not Used
  580. *
  581. * Return Value:
  582. * None
  583. *
  584. *****************************************************************************/
  585. VOID WINAPI VirtualChannelOpenEventEx(IN LPVOID lpParam,
  586. IN DWORD openHandle,
  587. IN UINT event,
  588. IN LPVOID pdata,
  589. IN UINT32 dataLength,
  590. IN UINT32 totalLength,
  591. IN UINT32 dataFlags)
  592. {
  593. DC_BEGIN_FN("IntVirtualChannelOpenEvent");
  594. TRC_ASSERT((lpParam), (TB,_T("lpParam is NULL")));
  595. if(lpParam)
  596. {
  597. CVChannels* pVChan = (CVChannels*)lpParam;
  598. pVChan->IntVirtualChannelOpenEventEx( openHandle, event ,pdata,
  599. dataLength, totalLength, dataFlags);
  600. }
  601. DC_END_FN();
  602. }
  603. /*****************************************************************************
  604. *
  605. * Routine Description:
  606. * Virtual Channel Init callback function.
  607. *
  608. * Arguments:
  609. * pInitHandle : Not Used
  610. * event : Kind of event that has occured
  611. * pdata : Not Used
  612. * datalength : Not Used
  613. *
  614. * Return Value:
  615. * None
  616. *
  617. *****************************************************************************/
  618. VOID
  619. VCAPITYPE VirtualChannelInitEventProcEx(
  620. IN LPVOID lpParam,
  621. IN LPVOID pInitHandle,
  622. IN UINT event,
  623. IN LPVOID pData,
  624. IN UINT dataLength)
  625. {
  626. UNREFERENCED_PARAMETER(pInitHandle);
  627. UNREFERENCED_PARAMETER(pData);
  628. UNREFERENCED_PARAMETER(dataLength);
  629. DC_BEGIN_FN("VirtualChannelInitEventProc");
  630. TRC_ASSERT((lpParam), (TB,_T("lpParam is NULL")));
  631. if(!lpParam)
  632. {
  633. return;
  634. }
  635. CVChannels* pVChan = (CVChannels*)lpParam;
  636. pVChan->IntVirtualChannelInitEventProcEx( pInitHandle, event, pData, dataLength);
  637. DC_END_FN();
  638. }
  639. END_EXTERN_C