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.

922 lines
28 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name :
  4. igateway.cxx
  5. Abstract:
  6. This module defines the functions for Internet Services related
  7. gateway processing ( spawning process and thread for i/o).
  8. Author:
  9. Murali R. Krishnan ( MuraliK ) 25-Jan-1995
  10. Environment:
  11. User Mode - Win32
  12. Project:
  13. Internet Services Common DLL
  14. Functions Exported:
  15. BOOL TsProcessGatewayRequest(
  16. IN LPVOID pClientContext,
  17. IN PIGATEWAY_REQUEST pigRequest,
  18. IN PFN_GATEWAY_READ_CALLBACK pfnReadCallBack);
  19. Revision History:
  20. --*/
  21. /*++
  22. A service may require gateway call to process special
  23. requests received from the clients.
  24. Such requests are processed by spawning a special process and communicating
  25. with the special process. The process takes the client supplied data as
  26. input and sends its output to be sent to the client.
  27. Since the service module is aware of the details of input and output,
  28. a special thread is created in the service process to deal with the
  29. input and output. A two-way pipe is established b/w the spawned process
  30. and the service thread.
  31. Once the "special gateway process" completes processing the input and
  32. terminates, the thread doing I/O proceeds to munging.
  33. During munging state, the thread calls upon a callback function for
  34. munging and data transfer. The call-back function is responsible
  35. for altering the data if need be and sending the data to client.
  36. After this the service thread terminates its work.
  37. --*/
  38. /************************************************************
  39. * Include Headers
  40. ************************************************************/
  41. # include <tcpdllp.hxx>
  42. # include "igateway.hxx"
  43. # define MAX_CB_DATA_FROM_GATEWAY ( 4096)
  44. /************************************************************
  45. * Type Definitions
  46. ************************************************************/
  47. class IGATEWAY_PROCESSOR {
  48. public:
  49. inline
  50. IGATEWAY_PROCESSOR(
  51. IN LPVOID pClientContext,
  52. IN PFN_IGATEWAY_READ_CALLBACK pfnReadCallBack,
  53. IN LPBYTE pbDataToGateway = NULL,
  54. IN DWORD cbDataToGateway = 0
  55. )
  56. : m_pClientContext ( pClientContext),
  57. m_pfnReadCallBack ( pfnReadCallBack),
  58. m_pbDataToGateway ( pbDataToGateway),
  59. m_cbDataToGateway ( cbDataToGateway),
  60. m_hStdIn ( INVALID_HANDLE_VALUE),
  61. m_hStdOut ( INVALID_HANDLE_VALUE)
  62. {
  63. m_fCompleted = 0;
  64. m_fValid = ( m_pfnReadCallBack != NULL);
  65. }
  66. inline virtual ~IGATEWAY_PROCESSOR( VOID);
  67. BOOL IsValid( VOID) const
  68. { return ( m_fValid); }
  69. VOID
  70. SetProcessingCompleted( IN BOOL fValue = TRUE)
  71. { m_fCompleted = ( fValue) ? 1 : 0; }
  72. BOOL
  73. IsProcessingCompleted( VOID) const
  74. { return ( m_fCompleted == 1); }
  75. HANDLE
  76. QueryStdInHandle( VOID) const
  77. { return ( m_hStdIn); }
  78. HANDLE
  79. QueryStdOutHandle( VOID) const
  80. { return ( m_hStdOut); }
  81. BOOL
  82. StartGatewayProcess(
  83. IN LPCTSTR pszCmdLine,
  84. IN LPCTSTR pszWorkingDir,
  85. IN LPVOID lpvEnvironment,
  86. IN HANDLE hUserToken);
  87. //
  88. // the worker thread for gateway request processing
  89. //
  90. DWORD
  91. GatewayIOWorker( VOID);
  92. # if DBG
  93. VOID Print( VOID) const;
  94. # endif // DBG
  95. private:
  96. DWORD m_fValid : 1;
  97. DWORD m_fCompleted : 1;
  98. PVOID m_pClientContext; // client context information
  99. PFN_IGATEWAY_READ_CALLBACK m_pfnReadCallBack;
  100. HANDLE m_hStdIn;
  101. HANDLE m_hStdOut;
  102. LPBYTE m_pbDataToGateway;
  103. DWORD m_cbDataToGateway;
  104. BOOL
  105. SetupChildPipes( IN STARTUPINFO * pStartupInfo);
  106. }; // class IGATEWAY_PROCESSOR
  107. typedef IGATEWAY_PROCESSOR * PIGATEWAY_PROCESSOR;
  108. inline IGATEWAY_PROCESSOR::~IGATEWAY_PROCESSOR( VOID)
  109. {
  110. DBG_ASSERT( IsProcessingCompleted());
  111. if ( m_hStdIn != INVALID_HANDLE_VALUE &&
  112. !CloseHandle( m_hStdIn)) {
  113. IF_DEBUG( GATEWAY) {
  114. DBGPRINTF( ( DBG_CONTEXT,
  115. "IGATEWAY_PROCESSOR:CloseHandle( StdIn %08x) failed."
  116. " Error = %d.\n",
  117. m_hStdIn, GetLastError()));
  118. }
  119. }
  120. if ( m_hStdOut != INVALID_HANDLE_VALUE &&
  121. !CloseHandle( m_hStdOut)) {
  122. IF_DEBUG( GATEWAY) {
  123. DBGPRINTF( ( DBG_CONTEXT,
  124. "IGATEWAY_PROCESSOR:CloseHandle( StdOut %08x) failed."
  125. " Error = %d.\n",
  126. m_hStdOut, GetLastError()));
  127. }
  128. }
  129. } // IGATEWAY_PROCESSOR::~IGATEWAY_PROCESSOR()
  130. # if DBG
  131. static inline VOID
  132. PrintStartupInfo( IN const STARTUPINFO * pStartInfo)
  133. {
  134. IF_DEBUG( GATEWAY) {
  135. DBGPRINTF( ( DBG_CONTEXT,
  136. " Startup Info = %08x. cb = %d."
  137. " hStdInput = %08x. hStdOutput = %08x."
  138. " hStdError = %08x.\n",
  139. pStartInfo, pStartInfo->cb,
  140. pStartInfo->hStdInput,
  141. pStartInfo->hStdOutput,
  142. pStartInfo->hStdError));
  143. }
  144. } // PrintStartupInfo()
  145. static inline VOID
  146. PrintProcessInfo( IN const PROCESS_INFORMATION * pProcInfo)
  147. {
  148. IF_DEBUG( GATEWAY) {
  149. DBGPRINTF( ( DBG_CONTEXT,
  150. " ProcessInfo = %08x."
  151. " hProcess = %08x. hThread = %08x."
  152. " dwProcessId = %08x. dwThreadId = %08x",
  153. pProcInfo, pProcInfo->hProcess,
  154. pProcInfo->hThread,
  155. pProcInfo->dwProcessId,
  156. pProcInfo->dwThreadId));
  157. }
  158. } // PrintProcessInfo()
  159. # endif // DBG
  160. /************************************************************
  161. * Functions
  162. ************************************************************/
  163. static
  164. DWORD
  165. WINAPI
  166. GatewayRequestIOThreadFunction(
  167. IN LPVOID pThreadParam)
  168. /*++
  169. The function is called when the thread for Gateway request I/O is created.
  170. This function calls the GatewayIOWorker member function to process I/O
  171. from the gateway process.
  172. In addition this function also deletes the IGATEWAY_PROCESSOR object, at
  173. the end. Memory deallocation is done here, since this thread will die
  174. at the end of this procedure and no other thread has knowledge about this
  175. object to perform cleanup.
  176. Arguments:
  177. pThreadParam pointer to thread parameter. This function is called
  178. with the parameter as the pointer to
  179. IGATEWAY_PROCESSOR object.
  180. Returns:
  181. Win32 error code resulting from gateway I/O processing.
  182. --*/
  183. {
  184. PIGATEWAY_PROCESSOR pigProcessor = (PIGATEWAY_PROCESSOR ) pThreadParam;
  185. DWORD dwError;
  186. DBG_ASSERT( pigProcessor != NULL);
  187. dwError = pigProcessor->GatewayIOWorker();
  188. IF_DEBUG( GATEWAY) {
  189. DBGPRINTF( ( DBG_CONTEXT,
  190. "Freeing the IGATEWAY_PROCESSOR object ( %08x)\n",
  191. pigProcessor));
  192. }
  193. delete pigProcessor;
  194. return ( dwError);
  195. } // GatewayRequestIOThreadFunction()
  196. dllexp BOOL
  197. TsProcessGatewayRequest(
  198. IN LPVOID pClientContext,
  199. IN PIGATEWAY_REQUEST pigRequest,
  200. IN PFN_IGATEWAY_READ_CALLBACK pfnReadCallBack)
  201. /*++
  202. Description:
  203. This function creates a gateway processor object responsible for processing
  204. gateway requests. It extracts the parameters required from input request
  205. package ( IGATEWAY_REQUEST structure). It creates a separate process for
  206. gateway request and a separate thread for handling I/O for the
  207. gateway request. The thread uses buffers supplied for i/o in pigRequest.
  208. On a completion of read, the thread calls the callback function for
  209. processing the data retrieved. If the call back function returns any error
  210. further procecssing in the thread is halted and the thread dies.
  211. The process also will eventually die, since the pipes are broken.
  212. Arguments:
  213. pClientContext context information supplied by client
  214. pigRequest pointer to IGATEWAY_REQUEST object.
  215. pfnReadCallBack pointer to callback function for read completions.
  216. Returns:
  217. TRUE on success and FALSE if there is any failure.
  218. Use GetLastError() to retrieve Win32 error code.
  219. --*/
  220. {
  221. BOOL fReturn = FALSE;
  222. PIGATEWAY_PROCESSOR pigProcessor = NULL;
  223. DBG_ASSERT( pigRequest != NULL && pfnReadCallBack != NULL);
  224. IF_DEBUG( GATEWAY) {
  225. DBGPRINTF( ( DBG_CONTEXT,
  226. "TsProcessGatewayRequest() called. pigRequest = %08x.\n",
  227. pigRequest));
  228. }
  229. //
  230. // create a new gateway processor object for handling the gateway request.
  231. //
  232. pigProcessor = new IGATEWAY_PROCESSOR( pClientContext,
  233. pfnReadCallBack,
  234. pigRequest->pbDataToGateway,
  235. pigRequest->cbDataToGateway);
  236. fReturn = ( pigProcessor != NULL) && pigProcessor->IsValid();
  237. if ( fReturn) {
  238. IF_DEBUG( GATEWAY) {
  239. DBGPRINTF( ( DBG_CONTEXT,
  240. " Created a new IGATEWAY_PROCESSOR object.\n"));
  241. DBG_CODE( pigProcessor->Print());
  242. DBGPRINTF( ( DBG_CONTEXT,
  243. " Starting a process for the gateway command\n"));
  244. }
  245. fReturn = pigProcessor->StartGatewayProcess( pigRequest->pszCmdLine,
  246. pigRequest->pszWorkingDir,
  247. pigRequest->lpvEnvironment,
  248. pigRequest->hUserToken);
  249. if ( fReturn) {
  250. HANDLE hThread;
  251. DWORD dwThreadId;
  252. IF_DEBUG( GATEWAY) {
  253. DBGPRINTF( ( DBG_CONTEXT,
  254. " Creating a new thread to handle gateway I/O\n"));
  255. }
  256. //
  257. // Create a new thread to handle I/O with the process spawned.
  258. //
  259. hThread = CreateThread( NULL, // lpSecurityAttributes,
  260. 0, // stack size in Bytes,
  261. GatewayRequestIOThreadFunction,
  262. (LPVOID )pigProcessor, // params
  263. 0, // Creation flags
  264. &dwThreadId);
  265. if ( ( fReturn = ( hThread != NULL))) {
  266. IF_DEBUG( GATEWAY) {
  267. DBGPRINTF( ( DBG_CONTEXT,
  268. " Created Gateway I/O thread. Hdl=%d. Id=%d\n",
  269. hThread, dwThreadId));
  270. }
  271. //
  272. // Close thread handle, since we are not bothered about its
  273. // termination and there is no special cleanup required.
  274. //
  275. DBG_REQUIRE( CloseHandle( hThread));
  276. } else {
  277. IF_DEBUG( GATEWAY) {
  278. DBGPRINTF( ( DBG_CONTEXT,
  279. "Creation of gateway I/O thread failed."
  280. " Error = %d\n",
  281. GetLastError()));
  282. }
  283. } // creation of IO thread
  284. } // successful start of process for gateway.
  285. } // creation of pigProcessor
  286. if ( !fReturn) {
  287. IF_DEBUG( GATEWAY) {
  288. DBGPRINTF( ( DBG_CONTEXT,
  289. " Failure to set up gateway request processiong."
  290. " Deleting the IGATEWAY_PROCESSOR object( %08x)."
  291. " Error = %d.\n",
  292. pigProcessor,
  293. GetLastError()));
  294. }
  295. if ( pigProcessor != NULL) {
  296. DBG_ASSERT( !pigProcessor->IsValid());
  297. delete pigProcessor;
  298. }
  299. }
  300. return ( fReturn);
  301. } // TsProcessGatewayRequest()
  302. /************************************************************
  303. * IGATEWAY_PROCESSOR member functions
  304. ************************************************************/
  305. BOOL
  306. IGATEWAY_PROCESSOR::StartGatewayProcess(
  307. IN LPCTSTR pszCmdLine,
  308. IN LPCTSTR pszWorkingDir,
  309. IN LPVOID lpvEnvironment, // optional
  310. IN HANDLE hUserToken)
  311. /*++
  312. Description:
  313. This function sets up pipes for communication with gateway
  314. and starts a process for gateway application.
  315. Arguments:
  316. pszCmdLine pointer to null-terminated string containing the
  317. command line for the gateway call.
  318. The first word ( seq of chars) in pszCmdLine, specifies
  319. the gateway application to be used.
  320. pszWorkingDir pointer to working directory for the gateway call.
  321. hUserToken handle for the user accessing gateway for secure access.
  322. lpvEnvironment pointer to Environment Block for CreateProcess to pass
  323. environment information to the gateway application.
  324. Returns:
  325. TRUE on success; and FALSE if there is any failure.
  326. Use GetLastError() for Win32 error code.
  327. --*/
  328. {
  329. BOOL fReturn;
  330. STARTUPINFO startInfo;
  331. PROCESS_INFORMATION procInfo;
  332. DBG_ASSERT( pszCmdLine != NULL && pszWorkingDir != NULL);
  333. DBG_ASSERT( hUserToken != INVALID_HANDLE_VALUE);
  334. memset( (PVOID ) &procInfo, 0, sizeof( procInfo));
  335. memset( (PVOID ) &startInfo, 0, sizeof( startInfo));
  336. startInfo.cb = sizeof( startInfo);
  337. if ( ( fReturn = SetupChildPipes( &startInfo))) {
  338. //
  339. // Successfully setup the child pipes. Proceed to create the process.
  340. //
  341. fReturn = CreateProcessAsUser( hUserToken,
  342. NULL, // pszImageName
  343. (TCHAR *) pszCmdLine, // pszCommandLine
  344. NULL, // process security
  345. NULL, // thread security
  346. TRUE, // inherit handles,
  347. DETACHED_PROCESS,
  348. lpvEnvironment,
  349. pszWorkingDir,
  350. &startInfo,
  351. &procInfo);
  352. DBG_CODE( PrintStartupInfo( &startInfo));
  353. DBG_CODE( PrintProcessInfo( &procInfo));
  354. //
  355. // Had already set up the stderror to be same as stdoutput
  356. // in SetupChildPipes(). Verify the same.
  357. //
  358. if ( fReturn) {
  359. DBG_REQUIRE( startInfo.hStdError == startInfo.hStdOutput);
  360. DBG_REQUIRE( CloseHandle( startInfo.hStdOutput));
  361. DBG_REQUIRE( CloseHandle( startInfo.hStdInput));
  362. DBG_REQUIRE( CloseHandle( procInfo.hProcess));
  363. DBG_REQUIRE( CloseHandle( procInfo.hThread));
  364. }
  365. IF_DEBUG( GATEWAY) {
  366. DBGPRINTF( ( DBG_CONTEXT,
  367. "StartGatewayProcess: CreateProcessAsUser( %s)"
  368. " returns %d. Error = %d.\n",
  369. pszCmdLine, fReturn, GetLastError()));
  370. }
  371. } else {
  372. IF_DEBUG( GATEWAY) {
  373. DBGPRINTF( ( DBG_CONTEXT,
  374. "StartGatewayProcess(). Unable to setup child Pipes."
  375. " Error = %d\n",
  376. GetLastError()));
  377. }
  378. }
  379. return ( fReturn);
  380. } // IGATEWAY_PROCESSOR::StartGatewayProcess()
  381. BOOL
  382. IGATEWAY_PROCESSOR::SetupChildPipes( IN LPSTARTUPINFO lpStartupInfo)
  383. /*++
  384. Description:
  385. Creates pipe and duplicates handles for redirecting stdin and stdout
  386. to child process.
  387. Arguments:
  388. pStartupInfo pointer to startup information structure used by
  389. CreateProcess().
  390. This receives the child stdin and stdout.
  391. Returns:
  392. TRUE on success and FALSE if there is any error.
  393. --*/
  394. {
  395. BOOL fReturn;
  396. SECURITY_ATTRIBUTES securityAttributes;
  397. DBG_ASSERT( lpStartupInfo != NULL);
  398. securityAttributes.nLength = sizeof( securityAttributes);
  399. securityAttributes.bInheritHandle = TRUE;
  400. securityAttributes.lpSecurityDescriptor = NULL;
  401. m_hStdIn = m_hStdOut = NULL;
  402. lpStartupInfo->dwFlags = STARTF_USESTDHANDLES;
  403. //
  404. // create pipes for communication and duplicate handles.
  405. // mark the duplicates handles as non-inherited to avoid handle leaks
  406. //
  407. fReturn = ( CreatePipe( &m_hStdIn, // parent read pipe
  408. &lpStartupInfo->hStdOutput,// child write pipe
  409. &securityAttributes,
  410. 0) && // nSize
  411. DuplicateHandle( GetCurrentProcess(), // hSourceProcess
  412. m_hStdIn, // hSourceHandle
  413. GetCurrentProcess(), // hTargetProcess
  414. &m_hStdIn, // lphTargetHandle
  415. 0, // desired access
  416. FALSE, // bInheritHandle
  417. DUPLICATE_SAME_ACCESS |
  418. DUPLICATE_CLOSE_SOURCE) &&
  419. CreatePipe( &lpStartupInfo->hStdInput, // parent read pipe
  420. &m_hStdOut, // child write pipe
  421. &securityAttributes,
  422. 0) && // nSize
  423. DuplicateHandle( GetCurrentProcess(), // hSourceProcess
  424. m_hStdOut, // hSourceHandle
  425. GetCurrentProcess(), // hTargetProcess
  426. &m_hStdOut, // lphTargetHandle
  427. 0, // desired access
  428. FALSE, // bInheritHandle
  429. DUPLICATE_SAME_ACCESS |
  430. DUPLICATE_CLOSE_SOURCE)
  431. );
  432. //
  433. // stdout and stderr share the same handle. In the worst case
  434. // clients close stderr before closing stdout, then we need to duplicate
  435. // stderr too. For now dont duplicate stdout.
  436. //
  437. lpStartupInfo->hStdError = lpStartupInfo->hStdOutput;
  438. IF_DEBUG( GATEWAY) {
  439. DBGPRINTF( ( DBG_CONTEXT,
  440. "Handles. ChildProcess. In= %08x. Out= %08x. Err= %08x.\n",
  441. lpStartupInfo->hStdInput,
  442. lpStartupInfo->hStdOutput,
  443. lpStartupInfo->hStdError));
  444. DBGPRINTF( ( DBG_CONTEXT,
  445. " IO Thread. In= %08x. Out= %08x.\n",
  446. m_hStdIn,
  447. m_hStdOut));
  448. }
  449. if ( !fReturn) {
  450. IF_DEBUG( GATEWAY) {
  451. DBGPRINTF( ( DBG_CONTEXT,
  452. " SetupChildPipes failed. Error = %d.\n",
  453. GetLastError()));
  454. }
  455. //
  456. // Free up the handles if any allocated.
  457. //
  458. if ( m_hStdIn != NULL) {
  459. DBG_REQUIRE( CloseHandle( m_hStdIn));
  460. m_hStdIn = INVALID_HANDLE_VALUE;
  461. }
  462. if ( m_hStdOut != NULL) {
  463. DBG_REQUIRE( CloseHandle( m_hStdOut));
  464. m_hStdOut = INVALID_HANDLE_VALUE;
  465. }
  466. }
  467. return ( fReturn);
  468. } // IGATEWAY_PROCESSOR::SetupChildPipes()
  469. DWORD
  470. IGATEWAY_PROCESSOR::GatewayIOWorker( VOID)
  471. /*++
  472. Description:
  473. This is the core function that performs the I/O with the gateway process.
  474. I/O is performed using the pipes created by cross-linking
  475. the stdout and stdin of gateway process to duplicated handles in the I/O
  476. thread.
  477. First, this function writes any data to be sent to the gateway process
  478. on the read pipe of the process
  479. ( to m_hStdOut of the IGATEWAY_PROCESSOR object).
  480. Subsequently it loops receiving data from the gateway process and passing
  481. it onto the client ( meaning service that requested gateway processing).
  482. It uses the read callback function to make the client perform necessary
  483. work.
  484. At the least the client should copy the data returned during in callback.
  485. ( Otherwise, there is a danger of the data getting lost in subsequent
  486. read from the gateway process.)
  487. Arguments:
  488. None
  489. Returns:
  490. Win32 error code.
  491. --*/
  492. {
  493. DWORD dwError = NO_ERROR;
  494. BOOL fDoneWaitingForGateway;
  495. BYTE pbDataFromGateway[ MAX_CB_DATA_FROM_GATEWAY];
  496. DWORD cbRead = 0;
  497. IF_DEBUG( GATEWAY) {
  498. DBGPRINTF( ( DBG_CONTEXT,
  499. " Entering IGATEWAY_PROCESSOR( %08x)::GatewayIOWorker()\n",
  500. this));
  501. }
  502. //
  503. // 1. Write any data to the gateway process's stdin
  504. //
  505. if ( m_cbDataToGateway != 0) {
  506. DWORD cbWritten;
  507. BOOL fWritten;
  508. DBG_ASSERT( m_pbDataToGateway != NULL);
  509. IF_DEBUG( GATEWAY) {
  510. DBGPRINTF( ( DBG_CONTEXT,
  511. "GatewayIOWorker( %08x)."
  512. " Writing %u bytes to gateway ( child) process's"
  513. " stdin ( %08x)\n",
  514. this, m_cbDataToGateway, m_hStdOut));
  515. }
  516. fWritten = WriteFile( m_hStdOut,
  517. m_pbDataToGateway,
  518. m_cbDataToGateway,
  519. &cbWritten,
  520. NULL);
  521. IF_DEBUG( GATEWAY) {
  522. DBGPRINTF( ( DBG_CONTEXT,
  523. "GatewayIOWorker( %08x). WriteFile() returns %d."
  524. " written %u bytes of %u bytes. Error = %d.\n",
  525. this, fWritten, cbWritten, m_cbDataToGateway,
  526. GetLastError()));
  527. }
  528. //
  529. // The error if any during WriteFile() is ignored.
  530. //
  531. } // data written to gateway process
  532. //
  533. // 2. Loop for data from gateway.
  534. //
  535. DBG_ASSERT( m_pfnReadCallBack != NULL);
  536. for( fDoneWaitingForGateway = FALSE; !fDoneWaitingForGateway; ) {
  537. BOOL fCallBack;
  538. //
  539. // 3. Wait for data from gateway process.
  540. //
  541. dwError = WaitForSingleObject( m_hStdIn, INFINITE);
  542. //
  543. // 4. Depending on return code, either read data or get error code
  544. //
  545. switch( dwError) {
  546. case WAIT_OBJECT_0:
  547. {
  548. BOOL fRead;
  549. //
  550. // 4.a Got something to read. Read the data into buffer.
  551. //
  552. fRead = ReadFile( m_hStdIn,
  553. pbDataFromGateway,
  554. MAX_CB_DATA_FROM_GATEWAY,
  555. &cbRead,
  556. NULL);
  557. dwError = ( fRead) ? NO_ERROR: GetLastError();
  558. IF_DEBUG( GATEWAY) {
  559. DBGPRINTF( ( DBG_CONTEXT,
  560. " GatewayIOWorker( %08x). ReadDataFromGateway"
  561. " returns %d. Read %d bytes. Error = %d.\n",
  562. this, fRead, cbRead, dwError));
  563. }
  564. if ( dwError == ERROR_BROKEN_PIPE) {
  565. fDoneWaitingForGateway = TRUE;
  566. }
  567. break;
  568. } // case WAIT_OBJECT_0
  569. case WAIT_FAILED:
  570. default: {
  571. //
  572. // Unknown error.
  573. //
  574. IF_DEBUG( GATEWAY) {
  575. DBGPRINTF( ( DBG_CONTEXT,
  576. " GatewayIOWorker(). WaitForReading Gateway"
  577. " data failed. Error = %d\n",
  578. dwError));
  579. }
  580. fDoneWaitingForGateway = TRUE;
  581. break;
  582. }
  583. } // switch
  584. //
  585. // 5. send data or error code back to the callback function.
  586. //
  587. fCallBack = ( *m_pfnReadCallBack)( m_pClientContext,
  588. dwError,
  589. pbDataFromGateway,
  590. cbRead);
  591. if ( !fCallBack) {
  592. dwError = GetLastError();
  593. IF_DEBUG( GATEWAY) {
  594. DBGPRINTF( ( DBG_CONTEXT,
  595. " GatewayIOWorker( %08x). ReadCallback failed."
  596. " Exiting the gateway processing. Error = %d\n",
  597. dwError));
  598. }
  599. fDoneWaitingForGateway = TRUE;
  600. }
  601. } // for
  602. IF_DEBUG( GATEWAY) {
  603. DBGPRINTF( ( DBG_CONTEXT,
  604. " GatewayIOWorker( %08x). Exiting the IO thread."
  605. " Error = %d.\n",
  606. this, dwError));
  607. }
  608. SetProcessingCompleted( TRUE);
  609. return ( dwError);
  610. } // IGATEWAY_PROCESSOR::GatewayIOWorker()
  611. # if DBG
  612. VOID
  613. IGATEWAY_PROCESSOR::Print( VOID) const
  614. {
  615. DBGPRINTF( ( DBG_CONTEXT,
  616. " Printing IGATEWAY_PROCESSOR object ( %08x)\n",
  617. this));
  618. DBGPRINTF( ( DBG_CONTEXT,
  619. "IsValid = %d. IsIOCompleted = %d.\n",
  620. m_fValid, m_fCompleted));
  621. DBGPRINTF( ( DBG_CONTEXT,
  622. " Client Context = %08x\tIO call back function = %08x\n",
  623. m_pClientContext, m_pfnReadCallBack));
  624. DBGPRINTF( ( DBG_CONTEXT,
  625. " Child StdIn handle = %08x\t Child StdOut handle = %08x\n",
  626. m_hStdIn, m_hStdOut));
  627. DBGPRINTF( ( DBG_CONTEXT,
  628. " Buffer for Data to Gateway = %08x, %u bytes\n",
  629. m_pbDataToGateway, m_cbDataToGateway));
  630. return;
  631. } // IGATEWAY_PROCESSOR::Print()
  632. dllexp VOID
  633. PrintIGatewayRequest( IN const IGATEWAY_REQUEST * pigRequest)
  634. {
  635. DBGPRINTF( ( DBG_CONTEXT,
  636. " Printing IGATEWAY_REQUEST object ( %08x)\n",
  637. pigRequest));
  638. if ( pigRequest != NULL) {
  639. DBGPRINTF( ( DBG_CONTEXT,
  640. " CommandLine = %s.\n WorkingDir = %s\n",
  641. pigRequest->pszCmdLine, pigRequest->pszWorkingDir));
  642. DBGPRINTF( ( DBG_CONTEXT,
  643. " UserHandle = %08x. lpvEnvironment = %08x\n",
  644. pigRequest->hUserToken, pigRequest->lpvEnvironment));
  645. DBGPRINTF( ( DBG_CONTEXT,
  646. " pbDataToGateway = %08x. cbDataToGateway = %u.\n",
  647. pigRequest->pbDataToGateway, pigRequest->cbDataToGateway));
  648. }
  649. return;
  650. } // PrintIGatewayRequest()
  651. # endif // DBG
  652. /************************ End of File ***********************/