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.

741 lines
27 KiB

  1. //
  2. // discodlg.cpp: disconnected dialog
  3. //
  4. //
  5. #include "stdafx.h"
  6. #define TRC_GROUP TRC_GROUP_UI
  7. #define TRC_FILE "disconnecteddlg"
  8. #include <atrcapi.h>
  9. #include "discodlg.h"
  10. #include "sh.h"
  11. #include "contwnd.h"
  12. //For error code decoding
  13. #define DC_DEFINE_GLOBAL_ERROR_STRINGS 1
  14. #include "tscerrs.h"
  15. //
  16. // Protocol errors
  17. //
  18. #include "rdperr.h"
  19. CDisconnectedDlg::CDisconnectedDlg( HWND hwndOwner, HINSTANCE hInst,
  20. CContainerWnd* pContWnd) :
  21. _pContWnd(pContWnd),
  22. _hInstance(hInst),
  23. _hwndOwner(hwndOwner)
  24. {
  25. DC_BEGIN_FN("CDisconnectedDlg");
  26. TRC_ASSERT(_pContWnd, (TB,_T("_pContWnd not set\n")));
  27. _disconnectReason = 0;
  28. _extendedDiscReason = exDiscReasonNoInfo;
  29. DC_END_FN();
  30. }
  31. CDisconnectedDlg::~CDisconnectedDlg()
  32. {
  33. }
  34. #define MAX_DISCOMSG_LEN SH_DISCONNECT_RESOURCE_MAX_LENGTH*3
  35. DCINT CDisconnectedDlg::DoModal()
  36. {
  37. DCINT retVal = 0;
  38. LPTSTR szOverallMsgString = NULL;
  39. INT_PTR rc = FALSE;
  40. DCUINT intRC;
  41. DC_BEGIN_FN("DoModal");
  42. szOverallMsgString = (LPTSTR) LocalAlloc(LPTR,
  43. MAX_DISCOMSG_LEN*sizeof(TCHAR));
  44. if (!szOverallMsgString)
  45. {
  46. return -1;
  47. }
  48. if (MapErrorToString(_hInstance, _disconnectReason,
  49. _extendedDiscReason,
  50. szOverallMsgString,
  51. MAX_DISCOMSG_LEN))
  52. {
  53. TCHAR szDialogCaption[64];
  54. intRC = LoadString(_hInstance,
  55. UI_IDS_DISCONNECTED_CAPTION,
  56. szDialogCaption,
  57. SIZECHAR(szDialogCaption));
  58. if(0 == intRC)
  59. {
  60. TRC_SYSTEM_ERROR("LoadString");
  61. TRC_ERR((TB, _T("Failed to load string ID:%u"),
  62. UI_IDS_DISCONNECTED_CAPTION));
  63. szDialogCaption[0] = 0;
  64. }
  65. MessageBox( _hwndOwner,
  66. szOverallMsgString,
  67. szDialogCaption,
  68. #ifndef OS_WINCE
  69. MB_OK | MB_HELP | MB_ICONSTOP);
  70. #else
  71. MB_OK | MB_ICONSTOP);
  72. #endif
  73. // Do the cleanup. This is hackerific but has to happen
  74. // from here because the disconnect dialog could be initiated
  75. // in the context of the main dialog via a PostMessage
  76. // see comment in contwnd.cpp
  77. TRC_ASSERT(_pContWnd, (TB,_T("_pContWnd not set\n")));
  78. if(_pContWnd)
  79. {
  80. _pContWnd->FinishDisconnect();
  81. }
  82. }
  83. DC_END_FN();
  84. if (szOverallMsgString)
  85. {
  86. LocalFree(szOverallMsgString);
  87. }
  88. return retVal;
  89. }
  90. //Returns error string for this message in szErrorMsg
  91. //szErrorMsg must be large enough to hold error string
  92. INT
  93. CDisconnectedDlg::MapErrorToString(
  94. HINSTANCE hInstance,
  95. INT disconnectReason,
  96. ExtendedDisconnectReasonCode extendedDisconnectReason,
  97. LPTSTR szErrorMsg,
  98. INT cchErrorMsgLen
  99. )
  100. {
  101. UINT stringID = 0;
  102. UINT errorCode;
  103. int rc;
  104. TCHAR szDisconnectedString[SH_DISCONNECT_RESOURCE_MAX_LENGTH];
  105. LPTSTR pszDebugErrorCodeText = _T("");
  106. DC_BEGIN_FN("MapErrorToString");
  107. TRC_NRM((TB, _T("Main disconnect reason code is:%u"),
  108. NL_GET_MAIN_REASON_CODE(disconnectReason)));
  109. TRC_ASSERT(szErrorMsg, (TB, _T("szErrorMsg is null")));
  110. //
  111. // If extended disconnect reason is set we may
  112. // just be able to figure out the error right away
  113. //
  114. if(extendedDisconnectReason != exDiscReasonNoInfo)
  115. {
  116. switch(extendedDisconnectReason)
  117. {
  118. case exDiscReasonAPIInitiatedDisconnect:
  119. {
  120. //An RPC call on the server initiated the disconnect
  121. //most likely is that it was an admin tool that kicked
  122. //off the disconnect
  123. stringID = UI_IDS_DISCONNECT_REMOTE_BY_SERVER_TOOL;
  124. }
  125. break;
  126. case exDiscReasonAPIInitiatedLogoff:
  127. {
  128. //An RPC call on the server initiated the disconnect
  129. //most likely is that it was an admin tool that kicked
  130. //off the disconnect
  131. stringID = UI_IDS_LOGOFF_REMOTE_BY_SERVER;
  132. }
  133. break;
  134. case exDiscReasonServerIdleTimeout:
  135. {
  136. // Idle timeout expired on server
  137. stringID = UI_IDS_DISCONNECT_IDLE_TIMEOUT;
  138. }
  139. break;
  140. case exDiscReasonServerLogonTimeout:
  141. {
  142. // Total logon timeout expired on server
  143. stringID = UI_IDS_DISCONNECT_LOGON_TIMEOUT;
  144. }
  145. break;
  146. case exDiscReasonReplacedByOtherConnection:
  147. {
  148. TRC_NRM((TB, _T("Disconnected by other connection")));
  149. stringID = UI_IDS_DISCONNECT_BYOTHERCONNECTION;
  150. }
  151. break;
  152. case exDiscReasonOutOfMemory:
  153. {
  154. // Server is out of memory
  155. stringID = UI_IDS_SERVER_OUT_OF_MEMORY;
  156. }
  157. break;
  158. case exDiscReasonServerDeniedConnection:
  159. {
  160. stringID = UI_IDS_SERVER_DENIED_CONNECTION;
  161. }
  162. break;
  163. case exDiscReasonServerDeniedConnectionFips:
  164. {
  165. stringID = UI_IDS_SERVER_DENIED_CONNECTION_FIPS;
  166. }
  167. break;
  168. case exDiscReasonLicenseInternal:
  169. {
  170. // Internal error in licensing protocol
  171. stringID = UI_IDS_LICENSE_INTERNAL;
  172. }
  173. break;
  174. case exDiscReasonLicenseNoLicenseServer:
  175. {
  176. // No license server available
  177. stringID = UI_IDS_LICENSE_NO_LICENSE_SERVER;
  178. }
  179. break;
  180. case exDiscReasonLicenseNoLicense:
  181. {
  182. // No license available for this client
  183. stringID = UI_IDS_LICENSE_NO_LICENSE;
  184. }
  185. break;
  186. case exDiscReasonLicenseErrClientMsg:
  187. {
  188. // Server got bad message from client
  189. stringID = UI_IDS_LICENSE_BAD_CLIENT_MSG;
  190. }
  191. break;
  192. case exDiscReasonLicenseHwidDoesntMatchLicense:
  193. {
  194. // HWID in license doesn't match the one sent
  195. stringID = UI_IDS_LICENSE_HWID_DOESNT_MATCH_LICENSE;
  196. }
  197. break;
  198. case exDiscReasonLicenseErrClientLicense:
  199. {
  200. // Server couldn't decode client license
  201. stringID = UI_IDS_LICENSE_BAD_CLIENT_LICENSE;
  202. }
  203. break;
  204. case exDiscReasonLicenseCantFinishProtocol:
  205. {
  206. // Server couldn't send final licensing packets
  207. stringID = UI_IDS_LICENSE_CANT_FINISH_PROTOCOL;
  208. }
  209. break;
  210. case exDiscReasonLicenseClientEndedProtocol:
  211. {
  212. // Client sent licensing error to server
  213. stringID = UI_IDS_LICENSE_CLIENT_ENDED_PROTOCOL;
  214. }
  215. break;
  216. case exDiscReasonLicenseErrClientEncryption:
  217. {
  218. // Server couldn't decrypt client message
  219. stringID = UI_IDS_LICENSE_BAD_CLIENT_ENCRYPTION;
  220. }
  221. break;
  222. case exDiscReasonLicenseCantUpgradeLicense:
  223. {
  224. // Client's license couldn't be upgraded
  225. stringID = UI_IDS_LICENSE_CANT_UPGRADE_LICENSE;
  226. }
  227. break;
  228. case exDiscReasonLicenseNoRemoteConnections:
  229. {
  230. // Server is in null mode - expired or not enough Per-CPU CALs
  231. stringID = UI_IDS_LICENSE_NO_REMOTE_CONNECTIONS;
  232. }
  233. break;
  234. default:
  235. {
  236. if(extendedDisconnectReason >= exDiscReasonProtocolRangeStart &&
  237. extendedDisconnectReason <= exDiscReasonProtocolRangeEnd)
  238. {
  239. //
  240. // It's a protocol error detected (E.g rdpwd broke the link
  241. // because it detected an error).
  242. //
  243. //
  244. // For most of these we just return status codes, more common
  245. // ones get their own message
  246. //
  247. if (Log_RDP_ENC_DecryptFailed ==
  248. (ULONG)(extendedDisconnectReason -
  249. exDiscReasonProtocolRangeStart))
  250. {
  251. stringID = UI_IDS_SERVER_DECRYPTION_ERROR;
  252. }
  253. else
  254. {
  255. stringID = UI_IDS_PROTOCOL_ERROR_WITH_CODE;
  256. }
  257. }
  258. }
  259. break;
  260. }
  261. }
  262. //
  263. // If we still haven't got the string to load then
  264. // crack the error code to figure out which stringID to load
  265. //
  266. if(0 == stringID)
  267. {
  268. switch (NL_GET_MAIN_REASON_CODE(disconnectReason))
  269. {
  270. case UI_DISCONNECT_ERROR: // ??08
  271. {
  272. errorCode = NL_GET_ERR_CODE(disconnectReason);
  273. #ifdef DC_DEBUG
  274. //
  275. // Extra debugging info for this error
  276. //
  277. pszDebugErrorCodeText = (PDCTCHAR) uiUIErrorText[errorCode-1];
  278. TRC_ALT((TB, _T("UI error occurred - cause:%#x '%s'"),
  279. errorCode,
  280. pszDebugErrorCodeText));
  281. #endif /* DC_DEBUG */
  282. switch (errorCode)
  283. {
  284. case UI_ERR_DISCONNECT_TIMEOUT:
  285. {
  286. TRC_NRM((TB, _T("Connection timed out")));
  287. stringID = UI_IDS_CONNECTION_TIMEOUT;
  288. }
  289. break;
  290. case UI_ERR_GHBNFAILED:
  291. case UI_ERR_BADIPADDRESS:
  292. case UI_ERR_DNSLOOKUPFAILED:
  293. {
  294. TRC_NRM((TB, _T("Bad IP address")));
  295. stringID = UI_IDS_BAD_SERVER_NAME;
  296. }
  297. break;
  298. case UI_ERR_ANSICONVERT:
  299. {
  300. TRC_NRM((TB, _T("An internal error has occurred.")));
  301. stringID = UI_IDS_ILLEGAL_SERVER_NAME;
  302. }
  303. break;
  304. case UI_ERR_NOTIMER:
  305. {
  306. /************************************************/
  307. /* Failed to create a timer. */
  308. /************************************************/
  309. TRC_NRM((TB, _T("Failed to create a timer")));
  310. stringID = UI_IDS_LOW_MEMORY;
  311. }
  312. break;
  313. case UI_ERR_LOOPBACK_CONSOLE_CONNECT:
  314. {
  315. TRC_NRM((TB, _T("Console loopback connect!!!")));
  316. stringID = UI_IDS_CANNOT_LOOPBACK_CONNECT;
  317. }
  318. break;
  319. case UI_ERR_LICENSING_TIMEOUT:
  320. {
  321. TRC_NRM((TB, _T("Licensing timed out")));
  322. stringID = UI_IDS_LICENSING_TIMEDOUT;
  323. }
  324. break;
  325. case UI_ERR_LICENSING_NEGOTIATION_FAIL:
  326. {
  327. TRC_NRM((TB, _T("Licensing negotiation failed")));
  328. stringID = UI_IDS_LICENSING_NEGOT_FAILED;
  329. }
  330. break;
  331. case UI_ERR_DECOMPRESSION_FAILURE:
  332. {
  333. TRC_NRM((TB,_T("Client decompression failure")));
  334. stringID = UI_IDS_CLIENT_DECOMPRESSION_FAILED;
  335. }
  336. break;
  337. case UI_ERR_UNEXPECTED_DISCONNECT:
  338. {
  339. TRC_NRM((TB,_T("Received 'UnexpectedDisconnect' code")));
  340. stringID = UI_IDS_INTERNAL_ERROR;
  341. }
  342. break;
  343. default:
  344. {
  345. TRC_ABORT((TB, _T("Unrecognized UI error %#x"),
  346. errorCode));
  347. stringID = UI_IDS_INTERNAL_ERROR;
  348. }
  349. break;
  350. }
  351. }
  352. break;
  353. case NL_DISCONNECT_REMOTE_BY_SERVER: // 0003
  354. {
  355. //The server has remotely disconnected us
  356. TRC_NRM((TB, _T("Remote disconnection by server")));
  357. //Unable to get more information
  358. stringID = UI_IDS_DISCONNECT_REMOTE_BY_SERVER;
  359. }
  360. break;
  361. case SL_DISCONNECT_ERROR: // ??06
  362. {
  363. errorCode = NL_GET_ERR_CODE(disconnectReason);
  364. #ifdef DC_DEBUG
  365. /********************************************************/
  366. /* Set up the error code text. */
  367. /********************************************************/
  368. pszDebugErrorCodeText = (PDCTCHAR) uiSLErrorText[errorCode-1];
  369. TRC_ALT((TB, _T("SL error occurred - cause:%#x '%s'"),
  370. errorCode,
  371. pszDebugErrorCodeText));
  372. #endif /* DC_DEBUG */
  373. /********************************************************/
  374. /* An SL error has occurred. Work out what the actual */
  375. /* code is. */
  376. /********************************************************/
  377. switch (errorCode)
  378. {
  379. /****************************************************/
  380. /* The following codes all map onto an "out of */
  381. /* memory" string. */
  382. /****************************************************/
  383. case SL_ERR_NOMEMFORSENDUD: // 0106
  384. case SL_ERR_NOMEMFORRECVUD: // 0206
  385. case SL_ERR_NOMEMFORSECPACKET: // 0306
  386. {
  387. TRC_NRM((TB, _T("Out of memory")));
  388. stringID = UI_IDS_LOW_MEMORY;
  389. }
  390. break;
  391. /****************************************************/
  392. /* The following codes all map onto a "security */
  393. /* error" string. */
  394. /****************************************************/
  395. case SL_ERR_NOSECURITYUSERDATA: // 0406
  396. case SL_ERR_INVALIDENCMETHOD: // 0506
  397. case SL_ERR_INVALIDSRVRAND: // 0606
  398. case SL_ERR_INVALIDSRVCERT: // 0706
  399. case SL_ERR_GENSRVRANDFAILED: // 0806
  400. case SL_ERR_MKSESSKEYFAILED: // 0906
  401. case SL_ERR_ENCCLNTRANDFAILED: // 0A06
  402. {
  403. TRC_NRM((TB, _T("Security error")));
  404. stringID = UI_IDS_SECURITY_ERROR;
  405. }
  406. break;
  407. case SL_ERR_ENCRYPTFAILED: // 0B06
  408. case SL_ERR_DECRYPTFAILED: // 0C06
  409. {
  410. TRC_NRM((TB, _T("Encryption error")));
  411. stringID = UI_IDS_ENCRYPTION_ERROR;
  412. }
  413. break;
  414. case SL_ERR_INVALIDPACKETFORMAT: // 0D06
  415. {
  416. TRC_NRM((TB, _T("Invalid packet format")));
  417. stringID = UI_IDS_PROTOCOL_ERROR;
  418. }
  419. break;
  420. case SL_ERR_INITFIPSFAILED:
  421. {
  422. TRC_NRM((TB, _T("Init FIPS encryption failed")));
  423. stringID = UI_IDS_FIPS_ERROR;
  424. }
  425. break;
  426. default:
  427. {
  428. /************************************************/
  429. /* Whoops - shouldn't get here. We should be */
  430. /* capable of correctly decoding every error */
  431. /* value. */
  432. /************************************************/
  433. TRC_ABORT((TB, _T("Unrecognized SL error code:%#x"),
  434. disconnectReason));
  435. stringID = UI_IDS_INTERNAL_ERROR;
  436. }
  437. break;
  438. }
  439. }
  440. break;
  441. case NL_DISCONNECT_ERROR: // ??04
  442. {
  443. #ifdef DC_DEBUG
  444. DCUINT lowByte;
  445. DCUINT highByte;
  446. #endif /* DC_DEBUG */
  447. errorCode = NL_GET_ERR_CODE(disconnectReason);
  448. #ifdef DC_DEBUG
  449. /********************************************************/
  450. /* Set up the error code text. */
  451. /********************************************************/
  452. highByte = errorCode >> 4;
  453. lowByte = (errorCode & 0xF) - 1;
  454. pszDebugErrorCodeText =
  455. (PDCTCHAR) uiNLErrorText[highByte][lowByte];
  456. TRC_ALT((TB, _T("NL error occurred - cause:%u '%s'"),
  457. errorCode,
  458. pszDebugErrorCodeText));
  459. #endif /* DC_DEBUG */
  460. /********************************************************/
  461. /* An NL error has occurred. Work out what the actual */
  462. /* code is. */
  463. /********************************************************/
  464. switch (NL_GET_ERR_CODE(disconnectReason))
  465. {
  466. /****************************************************/
  467. /* The following codes all map onto a "bad IP */
  468. /* address" string. */
  469. /****************************************************/
  470. case NL_ERR_TDDNSLOOKUPFAILED: // 0104
  471. case NL_ERR_TDGHBNFAILED: // 0604
  472. case NL_ERR_TDBADIPADDRESS: // 0804
  473. {
  474. TRC_NRM((TB, _T("Bad IP address")));
  475. stringID = UI_IDS_BAD_SERVER_NAME;
  476. }
  477. break;
  478. /****************************************************/
  479. /* The following code maps onto a "connect failed" */
  480. /* string. */
  481. /****************************************************/
  482. case NL_ERR_TDSKTCONNECTFAILED: // 0204
  483. case NL_ERR_TDTIMEOUT: // 0704
  484. case NL_ERR_NCATTACHUSERFAILED: // 3604
  485. case NL_ERR_NCCHANNELJOINFAILED: // 3704
  486. {
  487. TRC_NRM((TB, _T("Failed to establish a connection")));
  488. stringID = UI_IDS_NOT_RESPONDING;
  489. }
  490. break;
  491. case NL_ERR_MCSNOUSERIDINAUC: // 2704
  492. case NL_ERR_MCSNOCHANNELIDINCJC: // 2804
  493. case NL_ERR_NCBADMCSRESULT: // 3104
  494. case NL_ERR_NCNOUSERDATA: // 3304
  495. case NL_ERR_NCINVALIDH221KEY: // 3404
  496. case NL_ERR_NCNONETDATA: // 3504
  497. case NL_ERR_NCJOINBADCHANNEL: // 3804
  498. case NL_ERR_NCNOCOREDATA: // 3904
  499. {
  500. TRC_NRM((TB, _T("Protocol Error")));
  501. stringID = UI_IDS_CONNECT_FAILED_PROTOCOL;
  502. }
  503. break;
  504. /****************************************************/
  505. /* The following codes all map onto a "network */
  506. /* error has occurred" string. */
  507. /****************************************************/
  508. case NL_ERR_TDONCALLTOSEND: // 0304
  509. case NL_ERR_TDONCALLTORECV: // 0404
  510. {
  511. TRC_NRM((TB, _T("A network error has occurred")));
  512. stringID = UI_IDS_NETWORK_ERROR;
  513. }
  514. break;
  515. case NL_ERR_XTBADTPKTVERSION: // 1104
  516. case NL_ERR_XTBADHEADER: // 1204
  517. case NL_ERR_XTUNEXPECTEDDATA: // 1304
  518. case NL_ERR_MCSUNEXPECTEDPDU: // 2104
  519. case NL_ERR_MCSNOTCRPDU: // 2204
  520. case NL_ERR_MCSBADCRLENGTH: // 2304
  521. case NL_ERR_MCSBADCRFIELDS: // 2404
  522. case NL_ERR_MCSINVALIDPACKETFORMAT: // 2904
  523. {
  524. TRC_NRM((TB, _T("A protocol error has occurred")));
  525. stringID = UI_IDS_CLIENTSIDE_PROTOCOL_ERROR;
  526. }
  527. break;
  528. /****************************************************/
  529. /* This code relates to an incompatible server */
  530. /* version. */
  531. /****************************************************/
  532. case NL_ERR_MCSBADMCSREASON: // 2604
  533. case NL_ERR_NCVERSIONMISMATCH: // 3A04
  534. {
  535. TRC_NRM((TB, _T("Client/Server version mismatch")));
  536. stringID = UI_IDS_VERSION_MISMATCH;
  537. }
  538. break;
  539. /****************************************************/
  540. /* The following codes map onto an "illegal server */
  541. /* name" string. */
  542. /****************************************************/
  543. case NL_ERR_TDANSICONVERT: // 0A04
  544. {
  545. TRC_NRM((TB, _T("Couldn't convert name to ANSI")));
  546. stringID = UI_IDS_ILLEGAL_SERVER_NAME;
  547. }
  548. break;
  549. case NL_ERR_TDFDCLOSE: // 0904
  550. {
  551. TRC_NRM((TB, _T("Socket closed")));
  552. stringID = UI_IDS_CONNECTION_BROKEN;
  553. }
  554. break;
  555. default:
  556. {
  557. /************************************************/
  558. /* Woops - shouldn't get here. We should be */
  559. /* capable of correctly decoding every error */
  560. /* value. */
  561. /************************************************/
  562. TRC_ABORT((TB, _T("Unrecognized NL error code:%#x"),
  563. disconnectReason));
  564. stringID = UI_IDS_INTERNAL_ERROR;
  565. }
  566. break;
  567. }
  568. }
  569. break;
  570. default:
  571. {
  572. /********************************************************/
  573. /* Woops - shouldn't get here. We should be capable */
  574. /* of correctly decoding every disconnection reason */
  575. /* code. */
  576. /********************************************************/
  577. TRC_ABORT((TB, _T("Unexpected disconnect ID:%#x"),
  578. disconnectReason));
  579. stringID = UI_IDS_INTERNAL_ERROR;
  580. }
  581. break;
  582. }
  583. }
  584. //
  585. // First of all get the textual version of the string - we have
  586. // just worked out which string we need to load.
  587. //
  588. rc = LoadString(hInstance,
  589. stringID,
  590. szDisconnectedString,
  591. SIZECHAR(szDisconnectedString));
  592. if (0 == rc)
  593. {
  594. //Oops! Some problem with the resources.
  595. TRC_SYSTEM_ERROR("LoadString");
  596. TRC_ERR((TB, _T("Failed to load string ID:%u"), stringID));
  597. return FALSE;
  598. }
  599. if(UI_IDS_PROTOCOL_ERROR_WITH_CODE == stringID)
  600. {
  601. //
  602. // Need to add the specific protocol error
  603. // code to the string
  604. //
  605. DC_TSPRINTF(szErrorMsg, szDisconnectedString,
  606. extendedDisconnectReason);
  607. }
  608. else if (UI_IDS_CLIENTSIDE_PROTOCOL_ERROR == stringID)
  609. {
  610. //
  611. // Client side protocol error, add the appropriate
  612. // code to the string
  613. //
  614. DC_TSPRINTF(szErrorMsg, szDisconnectedString,
  615. disconnectReason);
  616. }
  617. else
  618. {
  619. //
  620. // Static error string (doesn't need codes appended)
  621. //
  622. _tcscpy(szErrorMsg, szDisconnectedString);
  623. }
  624. #ifdef DC_DEBUG
  625. //
  626. // In Check builds display the disconnect
  627. // codes as well as the debug disconnect reason string
  628. //
  629. TCHAR szDebugDisconnectInfo[128];
  630. // Add the numerical reason code.
  631. _stprintf(szDebugDisconnectInfo,
  632. _T("DEBUG ONLY: Disconnect code: 0x%x - ") \
  633. _T("Extended Disconnect code: 0x%x\n"),
  634. disconnectReason,
  635. extendedDisconnectReason);
  636. //
  637. // Add the error code text to the end of the string.
  638. //
  639. _tcscat(szErrorMsg, _T("\n\n"));
  640. _tcscat(szErrorMsg, szDebugDisconnectInfo);
  641. if (pszDebugErrorCodeText)
  642. {
  643. _tcscat(szErrorMsg, pszDebugErrorCodeText);
  644. }
  645. #endif
  646. DC_END_FN();
  647. return TRUE;
  648. }