Source code of Windows XP (NT5)
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.

1061 lines
35 KiB

  1. //---------------------------------------------------------------------
  2. // Copyright (C)1998 Microsoft Corporation, All Rights Reserved.
  3. //
  4. // complete.cpp
  5. //
  6. // This is the main for the IrTran-P service.
  7. //---------------------------------------------------------------------
  8. #include "precomp.h"
  9. #include "irrecv.h"
  10. #include <malloc.h>
  11. extern BOOL LaunchUi( wchar_t * cmdline ); // Defined: ..\irxfer\
  12. extern CCONNECTION_MAP *g_pConnectionMap; // Defined: irtranp.cpp
  13. extern BOOL ReceivesAllowed(); // Defined: irtranp.cpp
  14. extern BOOL CheckSaveAsUPF(); // Defined: irtranp.cpp
  15. //---------------------------------------------------------------------
  16. // Constants:
  17. //---------------------------------------------------------------------
  18. #define DEFAULT_TIMEOUT 10000
  19. //---------------------------------------------------------------------
  20. // ExplorePictures()
  21. //
  22. //---------------------------------------------------------------------
  23. DWORD ExplorePictures()
  24. {
  25. # define EXPLORER_EXE TEXT("explorer.exe")
  26. DWORD dwStatus = NO_ERROR;
  27. DWORD dwFlags;
  28. HANDLE hUserToken = ::GetUserToken();
  29. WCHAR *pwszPath;
  30. WCHAR *pwszCommandLine;
  31. STARTUPINFO StartupInfo;
  32. PROCESS_INFORMATION ProcessInfo;
  33. if (CheckExploreOnCompletion() && (hUserToken))
  34. {
  35. memset(&StartupInfo,0,sizeof(StartupInfo));
  36. memset(&ProcessInfo,0,sizeof(ProcessInfo));
  37. pwszPath = CCONNECTION::ConstructPicturesSubDirectory();
  38. if (!pwszPath)
  39. {
  40. dwStatus = ERROR_IRTRANP_OUT_OF_MEMORY;
  41. return dwStatus;
  42. }
  43. pwszCommandLine = (WCHAR*)_alloca( sizeof(WCHAR)
  44. * (wcslen(pwszPath)+wcslen(EXPLORER_EXE)+6) ); // 4 is space + 2 quotes + trailing zero + 2 extra
  45. wcscpy(pwszCommandLine,EXPLORER_EXE);
  46. wcscat(pwszCommandLine,TEXT(" \""));
  47. wcscat(pwszCommandLine,pwszPath);
  48. wcscat(pwszCommandLine,TEXT("\""));
  49. dwFlags = 0;
  50. if (!CreateProcessAsUserW(
  51. hUserToken,
  52. 0, // App name in command line.
  53. pwszCommandLine,
  54. 0, // lpProcessAttributes (security)
  55. 0, // lpThreadAttributes (security)
  56. FALSE, // bInheritHandles
  57. dwFlags,
  58. 0, // pEnvironment block
  59. pwszPath, // Current Directory
  60. &StartupInfo,
  61. &ProcessInfo ))
  62. {
  63. dwStatus = GetLastError();
  64. #ifdef DBG_ERROR
  65. DbgPrint("IrTranP: CreateProcessAsUser() failed: %d\n",dwStatus);
  66. #endif
  67. }
  68. FreeMemory(pwszPath);
  69. }
  70. return dwStatus;
  71. }
  72. //---------------------------------------------------------------------
  73. // ReceiveComplete()
  74. //
  75. //---------------------------------------------------------------------
  76. void ReceiveComplete( IN CCONNECTION *pConnection,
  77. IN DWORD dwStatusCode )
  78. {
  79. DWORD dwStatus = NO_ERROR;
  80. handle_t hBinding = ::GetRpcBinding();
  81. if (!pConnection)
  82. {
  83. return;
  84. }
  85. // Hide the progress dialog:
  86. if (hBinding)
  87. {
  88. #ifdef DBG_RETURN_STATUS
  89. DbgPrint("ReceiveComplete(): StatusCode: 0x%x (%d)\n",
  90. dwStatusCode, dwStatusCode );
  91. #endif
  92. ReceiveFinished( hBinding, pConnection->GetUiCookie(), dwStatusCode );
  93. }
  94. if ( (dwStatusCode == NO_ERROR)
  95. || (dwStatusCode == ERROR_SCEP_UNSPECIFIED_DISCONNECT)
  96. || (dwStatusCode == ERROR_SCEP_USER_DISCONNECT)
  97. || (dwStatusCode == ERROR_SCEP_PROVIDER_DISCONNECT) )
  98. {
  99. dwStatus = pConnection->Impersonate();
  100. if (dwStatus == NO_ERROR)
  101. {
  102. dwStatus = ExplorePictures();
  103. }
  104. dwStatus = pConnection->RevertToSelf();
  105. }
  106. }
  107. //---------------------------------------------------------------------
  108. // ProcessConnectRequest()
  109. //
  110. // Called by ProcessClient() when the input PDU message type is
  111. // MSG_TYPE_CONNECT_REQ.
  112. //
  113. // pConnection - The newly established Winsock connection with the
  114. // camera.
  115. //
  116. // pPdu - The SCEP PDU holding the connect request. It was
  117. // allocated in ProcessClient() by AssemblePdu() and
  118. // will always be free'd when ProcessConnectRequest()
  119. // finishes.
  120. //
  121. // dwPduSize - The size of the input PDU in bytes.
  122. //
  123. //---------------------------------------------------------------------
  124. DWORD ProcessConnectRequest( IN CCONNECTION *pConnection,
  125. IN SCEP_HEADER *pPdu,
  126. IN DWORD dwPduSize )
  127. {
  128. DWORD dwStatus;
  129. DWORD dwRespPduSize;
  130. BOOL fReceivesAllowed = ::ReceivesAllowed();
  131. SCEP_HEADER *pRespPdu;
  132. CIOPACKET *pNewIoPacket; // Posted IO packet (by SendPdu()).
  133. CSCEP_CONNECTION *pScepConnection
  134. = (CSCEP_CONNECTION*)pConnection->GetScepConnection();
  135. if (fReceivesAllowed)
  136. {
  137. // Build an connection accept acknowledgement:
  138. dwStatus = pScepConnection->BuildConnectRespPdu(&pRespPdu,
  139. &dwRespPduSize);
  140. }
  141. else
  142. {
  143. // Build a connect NACK:
  144. dwStatus = pScepConnection->BuildConnectNackPdu(&pRespPdu,
  145. &dwRespPduSize);
  146. }
  147. if (dwStatus == NO_ERROR)
  148. {
  149. pConnection->SendPdu(pRespPdu,dwRespPduSize,&pNewIoPacket);
  150. if (pNewIoPacket)
  151. {
  152. pNewIoPacket->SetWritePdu(pRespPdu);
  153. }
  154. else
  155. {
  156. DeletePdu(pRespPdu);
  157. }
  158. if (!fReceivesAllowed)
  159. {
  160. // Note: After sending a NACK, the camera should close
  161. // the connection, but at lease some don't, so I'm
  162. // forced to slam the connection...
  163. pConnection->CloseSocket(); // Was: ShutdownSocket().
  164. }
  165. }
  166. DeletePdu(pPdu);
  167. return dwStatus;
  168. }
  169. //---------------------------------------------------------------------
  170. // ProcessConnectResponse()
  171. //
  172. // Called by ProcessClient() when the input PDU message type is
  173. // MSG_TYPE_CONNECT_RESP.
  174. //
  175. // NOTE: Note implemented in the IrTran-P server, because the server
  176. // is not currently setup to connect to a camera to download
  177. // pictures back to the camera... We should never get this PDU
  178. // during normal operation.
  179. //
  180. // pConnection - The newly established Winsock connection with the
  181. // camera.
  182. //
  183. // pPdu - The SCEP PDU holding the connect request. It was
  184. // allocated in ProcessClient() by AssemblePdu() and
  185. // will always be free'd when ProcessConnectResponse()
  186. // finishes.
  187. //
  188. // dwPduSize - The size of the input PDU in bytes.
  189. //
  190. //---------------------------------------------------------------------
  191. DWORD ProcessConnectResponse( CCONNECTION *pConnection,
  192. SCEP_HEADER *pPdu,
  193. DWORD dwPduSize )
  194. {
  195. DWORD dwStatus = NO_ERROR;
  196. #ifdef DBG_ERROR
  197. DbgPrint("ProcessClient(): Unimplemented MSG_TYPE_CONNECT_RESP\n");
  198. #endif
  199. DeletePdu(pPdu);
  200. return dwStatus;
  201. }
  202. //---------------------------------------------------------------------
  203. // ProcessData()
  204. //
  205. // Called by ProcessClient() when the input PDU message type is
  206. // MSG_TYPE_DATA.
  207. //
  208. // pConnection - The newly established Winsock connection with the
  209. // camera.
  210. //
  211. // pPdu - The SCEP PDU holding the connect request. It was
  212. // allocated in ProcessClient() by AssemblePdu() and
  213. // will always be free'd when ProcessConnectResponse()
  214. // finishes.
  215. //
  216. // dwPduSize - The size of the input PDU in bytes.
  217. //
  218. //---------------------------------------------------------------------
  219. DWORD ProcessData( CCONNECTION *pConnection,
  220. SCEP_HEADER *pPdu,
  221. DWORD dwPduSize,
  222. COMMAND_HEADER *pCommandHeader,
  223. UCHAR *pUserData,
  224. DWORD dwUserDataSize )
  225. {
  226. DWORD dwStatus = NO_ERROR;
  227. DWORD dwRespPduSize;
  228. DWORD dwBftpOp = 0;
  229. UCHAR *pPutData;
  230. DWORD dwPutDataSize;
  231. DWORD dwJpegOffset;
  232. DWORD dwJpegSize;
  233. SCEP_HEADER *pRespPdu;
  234. CIOPACKET *pNewIoPacket; // Posted IO packet (by SendPdu()).
  235. CSCEP_CONNECTION *pScepConnection
  236. = (CSCEP_CONNECTION*)pConnection->GetScepConnection();
  237. // First, check to see if this is an abort PDU, send by the camera:
  238. if ( (pCommandHeader) && (pCommandHeader->PduType == PDU_TYPE_ABORT) )
  239. {
  240. DeletePdu(pPdu);
  241. return ERROR_SCEP_ABORT;
  242. }
  243. // Is one of the 2nd through Nth fragments of a fragmented PDU?
  244. if ( (pScepConnection->IsFragmented())
  245. && (pScepConnection->GetSequenceNo() > 0))
  246. {
  247. #ifdef DBG_IO
  248. DbgPrint("ProcessClient(): Put Fragment: SequenceNo: %d RestNo: %d\n",
  249. pScepConnection->GetSequenceNo(),
  250. pScepConnection->GetRestNo() );
  251. #endif
  252. pConnection->WritePictureFile( pUserData,
  253. dwUserDataSize,
  254. &pNewIoPacket );
  255. if (pNewIoPacket)
  256. {
  257. pNewIoPacket->SetWritePdu(pPdu);
  258. }
  259. else
  260. {
  261. DeletePdu(pPdu);
  262. }
  263. if (pScepConnection->GetDFlag() == DFLAG_LAST_FRAGMENT)
  264. {
  265. #ifdef DBG_IO
  266. DbgPrint("ProcessClient(): Put ACK\n");
  267. #endif
  268. pScepConnection->BuildPutRespPdu( PDU_TYPE_REPLY_ACK,
  269. ERROR_PUT_NO_ERROR,
  270. &pRespPdu,
  271. &dwRespPduSize);
  272. pConnection->SendPdu( pRespPdu,
  273. dwRespPduSize,
  274. &pNewIoPacket);
  275. if (pNewIoPacket)
  276. {
  277. pNewIoPacket->SetWritePdu(pRespPdu);
  278. }
  279. else
  280. {
  281. DeletePdu(pRespPdu);
  282. }
  283. }
  284. }
  285. else if (pCommandHeader)
  286. {
  287. // Length4 in the COMMAN_HEADER is the user data size
  288. // plus the bytes for machine ids (16), the DestPid (2),
  289. // SrcPid (2) and CommandId (2) so offset by 22.
  290. #ifdef DBG_IO
  291. DbgPrint("ProcessData(): SaveAsUPF(): %d\n",
  292. pConnection->CheckSaveAsUPF() );
  293. #endif
  294. dwStatus = pScepConnection->ParseBftp( pUserData,
  295. dwUserDataSize,
  296. pConnection->CheckSaveAsUPF(),
  297. &dwBftpOp,
  298. &pPutData,
  299. &dwPutDataSize );
  300. if ((dwStatus == NO_ERROR) && (IsBftpQuery(dwBftpOp)))
  301. {
  302. pScepConnection->BuildWht0RespPdu(dwBftpOp,
  303. &pRespPdu,
  304. &dwRespPduSize);
  305. pConnection->SendPdu( pRespPdu,
  306. dwRespPduSize,
  307. &pNewIoPacket );
  308. if (pNewIoPacket)
  309. {
  310. pNewIoPacket->SetWritePdu(pRespPdu);
  311. }
  312. else
  313. {
  314. DeletePdu(pRespPdu);
  315. }
  316. DeletePdu(pPdu);
  317. }
  318. else if ((dwStatus == NO_ERROR) && (IsBftpPut(dwBftpOp)))
  319. {
  320. //
  321. // Ok, we have a bFTP PUT command, so open a file
  322. // and get ready to start collecting image data.
  323. //
  324. dwStatus = pScepConnection->ParseUpfHeaders( pPutData,
  325. dwPutDataSize,
  326. &dwJpegOffset,
  327. &dwJpegSize );
  328. pConnection->SetJpegOffsetAndSize(dwJpegOffset,dwJpegSize);
  329. dwStatus = pConnection->Impersonate();
  330. dwStatus = pConnection->CreatePictureFile();
  331. dwStatus = pConnection->SetPictureFileTime( pScepConnection->GetCreateTime() );
  332. dwStatus = pConnection->RevertToSelf();
  333. dwStatus = pConnection->WritePictureFile( pPutData,
  334. dwPutDataSize,
  335. &pNewIoPacket );
  336. if (pNewIoPacket)
  337. {
  338. pNewIoPacket->SetWritePdu(pPdu);
  339. }
  340. else
  341. {
  342. DeletePdu(pPdu);
  343. }
  344. if (pScepConnection->IsFragmented())
  345. {
  346. #ifdef DBG_IO
  347. DbgPrint("ProcessClient(): Image File: %s Size: %d\n",
  348. pScepConnection->GetFileName(),
  349. pCommandHeader->Length4 );
  350. DbgPrint("ProcessClient(): SequenceNo: %d RestNo: %d\n",
  351. pScepConnection->GetSequenceNo(),
  352. pScepConnection->GetRestNo() );
  353. #endif
  354. }
  355. else
  356. {
  357. #ifdef DBG_IO
  358. DbgPrint("ProcessClient(): Put Command: Unfragmented\n");
  359. #endif
  360. }
  361. }
  362. else if (IsBftpError(dwBftpOp))
  363. {
  364. #ifdef DBG_ERROR
  365. DbgPrint("ProcessClient(): bFTP Error: %d\n", dwStatus );
  366. #endif
  367. DeletePdu(pPdu);
  368. dwStatus = ERROR_BFTP_INVALID_PROTOCOL;
  369. }
  370. else
  371. {
  372. #ifdef DBG_ERROR
  373. DbgPrint("ProcessClient(): Unknown bFTP Command: %d\n",dwBftpOp);
  374. #endif
  375. DeletePdu(pPdu);
  376. dwStatus = ERROR_BFTP_INVALID_PROTOCOL;
  377. }
  378. }
  379. return dwStatus;
  380. }
  381. //---------------------------------------------------------------------
  382. // ProcessDisconnect()
  383. //
  384. // Called by ProcessClient() when the input PDU message type is
  385. // MSG_TYPE_DISCONNECT.
  386. //
  387. // pConnection - The newly established Winsock connection with the
  388. // camera.
  389. //
  390. // pPdu - The SCEP PDU holding the connect request. It was
  391. // allocated in ProcessClient() by AssemblePdu() and
  392. // will always be free'd when ProcessConnectResponse()
  393. // finishes.
  394. //
  395. // dwPduSize - The size of the input PDU in bytes.
  396. //
  397. //---------------------------------------------------------------------
  398. DWORD ProcessDisconnect( CCONNECTION *pConnection,
  399. SCEP_HEADER *pPdu,
  400. DWORD dwPduSize )
  401. {
  402. DWORD dwStatus = NO_ERROR;
  403. // Don't need to do anything special here, since
  404. // ParsePdu() will set dwStatus to one of:
  405. // ERROR_SCEP_UNSPECIFIED_DISCONNECT (5002)
  406. // ERROR_SCEP_USER_DISCONNECT (5003)
  407. // or ERROR_SCEP_PROVIDER_DISCONNECT (5004)
  408. #ifdef DBG_IO
  409. DbgPrint("ProcessClient(): Disconnect: %d\n",dwStatus);
  410. #endif
  411. pConnection->SetReceiveComplete(TRUE);
  412. DeletePdu(pPdu);
  413. return dwStatus;
  414. }
  415. //---------------------------------------------------------------------
  416. // ProcessClient()
  417. //
  418. //---------------------------------------------------------------------
  419. DWORD ProcessClient( CIOSTATUS *pIoStatus,
  420. CIOPACKET *pIoPacket,
  421. DWORD dwNumBytes )
  422. {
  423. char *pBuffer;
  424. DWORD dwStatus = NO_ERROR;
  425. SOCKET Socket = pIoPacket->GetSocket();
  426. CCONNECTION *pConnection;
  427. CSCEP_CONNECTION *pScepConnection;
  428. SCEP_HEADER *pPdu;
  429. DWORD dwPduSize;
  430. COMMAND_HEADER *pCommandHeader;
  431. UCHAR *pUserData; // Location of bFTP data.
  432. DWORD dwUserDataSize;
  433. DWORD dwError = 0;
  434. handle_t hBinding;
  435. WCHAR wsCmdLine[80];
  436. pConnection = g_pConnectionMap->Lookup(Socket);
  437. if (!pConnection)
  438. {
  439. return ERROR_IRTRANP_OUT_OF_MEMORY;
  440. }
  441. pScepConnection = (CSCEP_CONNECTION*)pConnection->GetScepConnection();
  442. ASSERT(pScepConnection);
  443. pBuffer = pIoPacket->GetReadBuffer();
  444. while (dwStatus == NO_ERROR)
  445. {
  446. dwStatus = pScepConnection->AssemblePdu( pBuffer,
  447. dwNumBytes,
  448. &pPdu,
  449. &dwPduSize );
  450. if (dwStatus == NO_ERROR)
  451. {
  452. dwStatus = pScepConnection->ParsePdu( pPdu,
  453. dwPduSize,
  454. &pCommandHeader,
  455. &pUserData,
  456. &dwUserDataSize );
  457. switch (pPdu->MsgType)
  458. {
  459. case MSG_TYPE_CONNECT_REQ:
  460. // Message was an SCEP Connection Request:
  461. wcscpy(wsCmdLine,L"irftp.exe /h");
  462. if (!LaunchUi(wsCmdLine))
  463. {
  464. dwError = GetLastError();
  465. #ifdef DBG_ERROR
  466. DbgPrint("LaunchUi(): Failed: %d\n",dwError);
  467. #endif
  468. }
  469. hBinding = pIoStatus->GetRpcBinding();
  470. if (hBinding)
  471. {
  472. COOKIE cookie;
  473. dwError = ReceiveInProgress( hBinding, L"", &cookie, TRUE );
  474. pConnection->SetUiCookie( cookie );
  475. #ifdef DBG_ERROR
  476. if (dwError)
  477. {
  478. DbgPrint("ReceiveInProgress() returned: %d\n",
  479. dwError);
  480. }
  481. #endif
  482. }
  483. dwStatus = ProcessConnectRequest(pConnection,
  484. pPdu,
  485. dwPduSize );
  486. if ((dwStatus) || (!ReceivesAllowed()))
  487. {
  488. ReceiveComplete(pConnection,dwStatus);
  489. }
  490. break;
  491. case MSG_TYPE_CONNECT_RESP:
  492. // Message was a reply from a connection request:
  493. dwStatus = ProcessConnectResponse(pConnection,
  494. pPdu,
  495. dwPduSize );
  496. break;
  497. case MSG_TYPE_DATA:
  498. // Message is a SCEP command of some sort:
  499. dwStatus = ProcessData(pConnection,
  500. pPdu,
  501. dwPduSize,
  502. pCommandHeader,
  503. pUserData,
  504. dwUserDataSize );
  505. break;
  506. case MSG_TYPE_DISCONNECT:
  507. // Message from the camera was a disconnect:
  508. ProcessDisconnect(pConnection,
  509. pPdu,
  510. dwPduSize );
  511. ReceiveComplete(pConnection,dwStatus);
  512. break;
  513. default:
  514. #ifdef DBG_ERROR
  515. DbgPrint("ProcessClient(): Unknown MSG_TYPE_xxx: %d\n",
  516. pPdu->MsgType );
  517. #endif
  518. DeletePdu(pPdu);
  519. break;
  520. }
  521. }
  522. else
  523. {
  524. break;
  525. }
  526. pBuffer = 0;
  527. dwNumBytes = 0;
  528. }
  529. if (dwStatus == ERROR_CONTINUE)
  530. {
  531. dwStatus = NO_ERROR;
  532. }
  533. return dwStatus;
  534. }
  535. //---------------------------------------------------------------------
  536. // SendAbortPdu()
  537. //
  538. // Stop the camera.
  539. //
  540. // I should be able to send a Stop PDU, followed by a Disconnect, or
  541. // maybe an Abort PDU, but these don't work on all the cameras, so I
  542. // currently end up just doing a hard close on the connection to the
  543. // camera.
  544. //---------------------------------------------------------------------
  545. DWORD SendAbortPdu( IN CCONNECTION *pConnection )
  546. {
  547. DWORD dwStatus = NO_ERROR;
  548. #if TRUE
  549. if (pConnection)
  550. {
  551. pConnection->CloseSocket();
  552. }
  553. #else
  554. DWORD dwPduSize;
  555. SCEP_HEADER *pPdu;
  556. CIOPACKET *pNewIoPacket = 0;
  557. CSCEP_CONNECTION *pScepConnection
  558. = (CSCEP_CONNECTION*)pConnection->GetScepConnection();
  559. if (pScepConnection)
  560. {
  561. dwStatus = pScepConnection->BuildStopPdu(&pPdu,&dwPduSize);
  562. if (dwStatus != NO_ERROR)
  563. {
  564. pConnection->CloseSocket();
  565. return dwStatus;
  566. }
  567. dwStatus = pConnection->SendPdu(pPdu,dwPduSize,&pNewIoPacket);
  568. if (dwStatus != NO_ERROR)
  569. {
  570. DeletePdu(pPdu);
  571. pConnection->CloseSocket();
  572. return dwStatus;
  573. }
  574. pNewIoPacket->SetWritePdu(pPdu);
  575. dwStatus = pScepConnection->BuildDisconnectPdu(
  576. REASON_CODE_PROVIDER_DISCONNECT,
  577. &pPdu,
  578. &dwPduSize);
  579. if (dwStatus != NO_ERROR)
  580. {
  581. pConnection->CloseSocket();
  582. return dwStatus;
  583. }
  584. dwStatus = pConnection->SendPdu(pPdu,dwPduSize,&pNewIoPacket);
  585. if (dwStatus != NO_ERROR)
  586. {
  587. DeletePdu(pPdu);
  588. pConnection->CloseSocket();
  589. return dwStatus;
  590. }
  591. pNewIoPacket->SetWritePdu(pPdu);
  592. }
  593. #endif
  594. return dwStatus;
  595. }
  596. //---------------------------------------------------------------------
  597. // MapStatusCode()
  598. //
  599. //---------------------------------------------------------------------
  600. DWORD MapStatusCode( DWORD dwStatus,
  601. DWORD dwDefaultStatus )
  602. {
  603. // The Facility part of an error code are the first 12 bits of the
  604. // high word (16bits):
  605. #define FACILITY_MASK 0x0FFF0000
  606. // If the error code is already an IrTran-P error code, then don't
  607. // remap it:
  608. if ( ((dwStatus&FACILITY_MASK) >> 16) == FACILITY_IRTRANP)
  609. {
  610. return dwStatus;
  611. }
  612. // Map other errors:
  613. if (dwStatus != NO_ERROR)
  614. {
  615. if ( (dwStatus == ERROR_DISK_FULL)
  616. || (dwStatus == ERROR_WRITE_FAULT)
  617. || (dwStatus == ERROR_WRITE_PROTECT)
  618. || (dwStatus == ERROR_GEN_FAILURE)
  619. || (dwStatus == ERROR_NOT_DOS_DISK) )
  620. {
  621. dwStatus = ERROR_IRTRANP_DISK_FULL;
  622. }
  623. else
  624. {
  625. dwStatus = dwDefaultStatus;
  626. }
  627. }
  628. return dwStatus;
  629. }
  630. //---------------------------------------------------------------------
  631. // ProcessIoPackets()
  632. //
  633. //---------------------------------------------------------------------
  634. DWORD ProcessIoPackets( CIOSTATUS *pIoStatus )
  635. {
  636. DWORD dwStatus = NO_ERROR;
  637. DWORD dwProcessStatus = NO_ERROR; // Processing IO status.
  638. DWORD dwNumBytes;
  639. ULONG_PTR dwKey;
  640. DWORD dwTimeout = DEFAULT_TIMEOUT;
  641. LONG lPendingIos; // # of pending reads/writes on a CCONNECTION.
  642. LONG lPendingReads; // # of pending reads on a CCONNECTION.
  643. LONG lPendingWrites; // # of pending file writes on a CCONNECTION.
  644. OVERLAPPED *pOverlapped;
  645. CCONNECTION *pConnection;
  646. CCONNECTION *pNewConnection;
  647. CSCEP_CONNECTION *pScepConnection;
  648. CIOPACKET *pIoPacket = 0;
  649. CIOPACKET *pNewIoPacket = 0;
  650. HANDLE hIoCompletionPort = pIoStatus->GetIoCompletionPort();
  651. // Wait on the IO completion port for incomming connections:
  652. while (TRUE)
  653. {
  654. pIoStatus->IncrementNumPendingThreads();
  655. dwNumBytes = 0;
  656. dwKey = 0;
  657. pOverlapped = 0;
  658. if (!GetQueuedCompletionStatus( hIoCompletionPort,
  659. &dwNumBytes,
  660. &dwKey,
  661. &pOverlapped,
  662. dwTimeout ))
  663. {
  664. dwStatus = GetLastError();
  665. pIoStatus->DecrementNumPendingThreads();
  666. if (dwStatus != WAIT_TIMEOUT)
  667. {
  668. // Got an error. Two cases during an error,
  669. // data may or may not have been dequeued from
  670. // the IO completion port.
  671. if (pOverlapped)
  672. {
  673. pIoPacket = CIOPACKET::CIoPacketFromOverlapped(pOverlapped);
  674. pConnection = g_pConnectionMap->Lookup(dwKey);
  675. // ASSERT(pConnection);
  676. if (!pConnection)
  677. {
  678. delete pIoPacket;
  679. continue;
  680. }
  681. if (pIoPacket->GetIoPacketKind() == PACKET_KIND_READ)
  682. {
  683. lPendingReads = pConnection->DecrementPendingReads();
  684. ASSERT(lPendingReads >= 0);
  685. }
  686. else if (pIoPacket->GetIoPacketKind() == PACKET_KIND_WRITE_FILE)
  687. {
  688. lPendingWrites = pConnection->DecrementPendingWrites();
  689. ASSERT(lPendingWrites >= 0);
  690. SCEP_HEADER *pPdu = (SCEP_HEADER*)pIoPacket->GetWritePdu();
  691. if (pPdu)
  692. {
  693. DeletePdu(pPdu);
  694. }
  695. }
  696. else if (pIoPacket->GetIoPacketKind() == PACKET_KIND_WRITE_SOCKET)
  697. {
  698. SCEP_HEADER *pPdu = (SCEP_HEADER*)pIoPacket->GetWritePdu();
  699. if (pPdu)
  700. {
  701. DeletePdu(pPdu);
  702. }
  703. }
  704. else if (pIoPacket->GetIoPacketKind() == PACKET_KIND_LISTEN)
  705. {
  706. // One of the listen sockets was shutdown (closed):
  707. delete pIoPacket;
  708. continue;
  709. }
  710. // Check to see if there was a transmission error, or
  711. // there was an error writing the picture to disk:
  712. if (dwStatus != ERROR_NETNAME_DELETED)
  713. {
  714. DWORD dwStatusCode;
  715. SendAbortPdu(pConnection);
  716. pConnection->DeletePictureFile();
  717. dwStatusCode = MapStatusCode(
  718. dwStatus,
  719. ERROR_SCEP_PROVIDER_DISCONNECT);
  720. ReceiveComplete(pConnection,dwStatusCode);
  721. }
  722. else
  723. {
  724. // if (pConnection->IncompleteFile())
  725. dwProcessStatus = MapStatusCode(
  726. dwProcessStatus,
  727. ERROR_SCEP_INVALID_PROTOCOL );
  728. ReceiveComplete(pConnection,dwProcessStatus);
  729. }
  730. // Delete the connection if there are no more pending
  731. // IOs...
  732. lPendingIos = pConnection->NumPendingIos();
  733. if (lPendingIos == 0)
  734. {
  735. g_pConnectionMap->Remove(dwKey);
  736. delete pConnection;
  737. }
  738. #ifdef DBG_ERROR
  739. if (dwStatus != ERROR_NETNAME_DELETED)
  740. {
  741. DbgPrint("GetQueuedCompletionStatus(): Socket: %d PendingIos: %d Failed: 0x%x\n",
  742. dwKey, lPendingIos, dwStatus );
  743. }
  744. #endif
  745. delete pIoPacket;
  746. }
  747. else
  748. {
  749. #ifdef DBG_ERROR
  750. DbgPrint("GetQueuedCompletionStatus(): Socket: %d Failed: %d (no overlapped)\n",
  751. dwKey, dwStatus );
  752. #endif
  753. ReceiveComplete(pConnection,ERROR_SCEP_PROVIDER_DISCONNECT);
  754. }
  755. continue;
  756. }
  757. else
  758. {
  759. // Wait timeout, loop back and continue...
  760. }
  761. }
  762. else
  763. {
  764. // IO completed. Either we got a new connection to a client,
  765. // or more data has come in from an existing connection to
  766. // a client.
  767. // First, check to see if the shudown (uninintalize code)
  768. // wants us to shutdown:
  769. if ((dwKey == IOKEY_SHUTDOWN) && (!pOverlapped))
  770. {
  771. return dwStatus;
  772. }
  773. pConnection = g_pConnectionMap->Lookup(dwKey);
  774. if (!pConnection)
  775. {
  776. #ifdef DBG_ERROR
  777. DbgPrint("ProcessIoPackets(): Lookup(%d) Failed: Bytes: %d pOverlapped: 0x%x\n",
  778. dwKey,
  779. dwNumBytes,
  780. pOverlapped );
  781. #endif
  782. pIoPacket = CIOPACKET::CIoPacketFromOverlapped(pOverlapped);
  783. if (pIoPacket)
  784. {
  785. delete pIoPacket;
  786. }
  787. continue;
  788. }
  789. pIoStatus->DecrementNumPendingThreads();
  790. pIoPacket = CIOPACKET::CIoPacketFromOverlapped(pOverlapped);
  791. DWORD dwKind = pIoPacket->GetIoPacketKind();
  792. if (dwKind == PACKET_KIND_LISTEN)
  793. {
  794. // New connection:
  795. lPendingReads = pConnection->DecrementPendingReads();
  796. ASSERT(lPendingReads >= 0);
  797. #ifdef DBG_IO
  798. SOCKADDR_IRDA *pAddrLocal = 0;
  799. SOCKADDR_IRDA *pAddrFrom = 0;
  800. pIoPacket->GetSockAddrs(&pAddrLocal,&pAddrFrom);
  801. DbgPrint("ProcessIoPackets(): Accepted connection from 0x%2.2x%2.2x%2.2x%2.2x, service %s\n",
  802. pAddrFrom->irdaDeviceID[0],
  803. pAddrFrom->irdaDeviceID[1],
  804. pAddrFrom->irdaDeviceID[2],
  805. pAddrFrom->irdaDeviceID[3],
  806. pAddrFrom->irdaServiceName );
  807. #endif
  808. pScepConnection = new CSCEP_CONNECTION;
  809. if (!pScepConnection)
  810. {
  811. #ifdef DBG_ERROR
  812. DbgPrint("ProcessIoPackets(): Out of memeory.\n");
  813. #endif
  814. delete pIoPacket;
  815. continue;
  816. }
  817. pNewConnection = new CCONNECTION(
  818. PACKET_KIND_READ,
  819. pIoPacket->GetSocket(),
  820. pIoPacket->GetIoCompletionPort(),
  821. pScepConnection,
  822. ::CheckSaveAsUPF() );
  823. if (!pNewConnection)
  824. {
  825. #ifdef DBG_ERROR
  826. DbgPrint("ProcessIoPackets(): Out of memeory.\n");
  827. #endif
  828. delete pScepConnection;
  829. delete pIoPacket;
  830. continue;
  831. }
  832. g_pConnectionMap->Add(pNewConnection,
  833. pNewConnection->GetSocket() );
  834. delete pIoPacket;
  835. dwStatus = pNewConnection->PostMoreIos();
  836. dwStatus = pConnection->PostMoreIos();
  837. }
  838. else if (dwKind == PACKET_KIND_WRITE_SOCKET)
  839. {
  840. #ifdef DBG_IO
  841. DbgPrint("ProcessIoPackets(): Write completed: Socket: %d Bytes: %d\n",
  842. dwKey,
  843. dwNumBytes );
  844. #endif
  845. SCEP_HEADER *pPdu = (SCEP_HEADER*)pIoPacket->GetWritePdu();
  846. if (pPdu)
  847. {
  848. DeletePdu(pPdu);
  849. }
  850. delete pIoPacket;
  851. }
  852. else if (dwKind == PACKET_KIND_WRITE_FILE)
  853. {
  854. lPendingWrites = pConnection->DecrementPendingWrites();
  855. ASSERT(lPendingWrites >= 0);
  856. #ifdef DBG_IO
  857. DbgPrint("ProcessIoPackets(): Write File: Handle: %d Bytes: %d NumPendingIos: %d\n",
  858. dwKey, dwNumBytes, pConnection->NumPendingIos() );
  859. #endif
  860. SCEP_HEADER *pPdu = (SCEP_HEADER*)pIoPacket->GetWritePdu();
  861. if (pPdu)
  862. {
  863. DeletePdu(pPdu);
  864. }
  865. delete pIoPacket;
  866. }
  867. else
  868. {
  869. // Incomming data from connection client:
  870. ASSERT(dwKind == PACKET_KIND_READ);
  871. lPendingReads = pConnection->DecrementPendingReads();
  872. ASSERT(lPendingReads >= 0);
  873. #ifdef DBG_IO
  874. DbgPrint("ProcessIoPackets(): Read completed: Socket: %d Bytes: %d\n",
  875. dwKey,
  876. dwNumBytes );
  877. #endif
  878. if (dwNumBytes)
  879. {
  880. dwProcessStatus
  881. = ProcessClient(pIoStatus,pIoPacket,dwNumBytes);
  882. if (dwProcessStatus == NO_ERROR)
  883. {
  884. dwStatus = pConnection->PostMoreIos();
  885. }
  886. else
  887. {
  888. #ifdef DBG_ERROR
  889. if ( (dwProcessStatus != ERROR_SCEP_UNSPECIFIED_DISCONNECT)
  890. && (dwProcessStatus != ERROR_SCEP_USER_DISCONNECT)
  891. && (dwProcessStatus != ERROR_SCEP_PROVIDER_DISCONNECT) )
  892. {
  893. DbgPrint("ProcessIoPackets(): ProcessClient(): Failed: 0x%x\n",dwProcessStatus);
  894. }
  895. #endif
  896. pConnection->CloseSocket();
  897. }
  898. delete pIoPacket;
  899. }
  900. else
  901. {
  902. if (pConnection->NumPendingIos() == 0)
  903. {
  904. g_pConnectionMap->RemoveConnection(pConnection);
  905. delete pConnection;
  906. pConnection = 0;
  907. }
  908. delete pIoPacket;
  909. }
  910. }
  911. }
  912. }
  913. return 0;
  914. }