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.

476 lines
16 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: xputil.cpp
  5. //
  6. // PURPOSE: Utility functions that can be shared by all the transports.
  7. //
  8. #include "pch.hxx"
  9. #include "imnxport.h"
  10. #include "resource.h"
  11. #include "xputil.h"
  12. #include "strconst.h"
  13. #include "xpcomm.h"
  14. #include "demand.h"
  15. //
  16. // FUNCTION: XPUtil_DupResult()
  17. //
  18. // PURPOSE: Takes an IXPRESULT structure and duplicates the information
  19. // in that structure.
  20. //
  21. // PARAMETERS:
  22. // <in> pIxpResult - IXPRESULT structure to dupe
  23. // <out> *ppDupe - Returned duplicate.
  24. //
  25. // RETURN VALUE:
  26. // HRESULT
  27. //
  28. HRESULT XPUtil_DupResult(LPIXPRESULT pIxpResult, LPIXPRESULT *ppDupe)
  29. {
  30. if (!MemAlloc((LPVOID*) ppDupe, sizeof(IXPRESULT)))
  31. return (E_OUTOFMEMORY);
  32. (*ppDupe)->hrResult = pIxpResult->hrResult;
  33. (*ppDupe)->pszResponse = PszDup(pIxpResult->pszResponse);
  34. (*ppDupe)->uiServerError = pIxpResult->uiServerError;
  35. (*ppDupe)->hrServerError = pIxpResult->hrServerError;
  36. (*ppDupe)->dwSocketError = pIxpResult->dwSocketError;
  37. (*ppDupe)->pszProblem = PszDup(pIxpResult->pszProblem);
  38. return (S_OK);
  39. }
  40. //
  41. // FUNCTION: XPUtil_FreeResult()
  42. //
  43. // PURPOSE: Takes an IXPRESULT structure and frees all the memory used
  44. // by that structure.
  45. //
  46. // PARAMETERS:
  47. // <in> pIxpResult - structure to free.
  48. //
  49. void XPUtil_FreeResult(LPIXPRESULT pIxpResult)
  50. {
  51. SafeMemFree(pIxpResult->pszResponse);
  52. SafeMemFree(pIxpResult->pszProblem);
  53. SafeMemFree(pIxpResult);
  54. }
  55. //
  56. // FUNCTION: XPUtil_StatusToString()
  57. //
  58. // PURPOSE: Converts the IXPSTATUS enumeration into a string resource id.
  59. //
  60. // PARAMETERS:
  61. // <in> ixpStatus - status value to look up
  62. //
  63. // RETURN VALUE:
  64. // Returns the string resource ID which matches the status value
  65. //
  66. int XPUtil_StatusToString(IXPSTATUS ixpStatus)
  67. {
  68. const int rgStatusStrings[9][2] = {
  69. { IXP_FINDINGHOST, idsFindingHost },
  70. { IXP_CONNECTING, idsConnecting },
  71. { IXP_SECURING, idsSecuring },
  72. { IXP_CONNECTED, idsConnected },
  73. { IXP_AUTHORIZING, idsAuthorizing },
  74. { IXP_AUTHRETRY, idsAuthorizing },
  75. { IXP_AUTHORIZED, idsConnected },
  76. { IXP_DISCONNECTING, idsDisconnecting },
  77. { IXP_DISCONNECTED, idsNotConnected }
  78. };
  79. int iString = idsUnknown;
  80. for (UINT i = 0; i < 9; i++)
  81. {
  82. if (ixpStatus == rgStatusStrings[i][0])
  83. {
  84. iString = rgStatusStrings[i][1];
  85. break;
  86. }
  87. }
  88. // If this assert fires, it means someone added a status and didn't update
  89. // the table.
  90. Assert(iString != idsUnknown);
  91. return (iString);
  92. }
  93. LPTSTR XPUtil_NNTPErrorToString(HRESULT hr, LPTSTR pszAccount, LPTSTR pszGroup)
  94. {
  95. #ifndef WIN16
  96. const int rgErrorStrings[][2] = {
  97. #else
  98. const LONG rgErrorStrings[][2] = {
  99. #endif
  100. { IXP_E_NNTP_RESPONSE_ERROR, idsNNTPErrUnknownResponse },
  101. { IXP_E_NNTP_NEWGROUPS_FAILED, idsNNTPErrNewgroupsFailed },
  102. { IXP_E_NNTP_LIST_FAILED, idsNNTPErrListFailed },
  103. { IXP_E_NNTP_LISTGROUP_FAILED, idsNNTPErrListGroupFailed },
  104. { IXP_E_NNTP_GROUP_FAILED, idsNNTPErrGroupFailed },
  105. { IXP_E_NNTP_GROUP_NOTFOUND, idsNNTPErrGroupNotFound },
  106. { IXP_E_NNTP_ARTICLE_FAILED, idsNNTPErrArticleFailed },
  107. { IXP_E_NNTP_HEAD_FAILED, idsNNTPErrHeadFailed },
  108. { IXP_E_NNTP_BODY_FAILED, idsNNTPErrBodyFailed },
  109. { IXP_E_NNTP_POST_FAILED, idsNNTPErrPostFailed },
  110. { IXP_E_NNTP_NEXT_FAILED, idsNNTPErrNextFailed },
  111. { IXP_E_NNTP_DATE_FAILED, idsNNTPErrDateFailed },
  112. { IXP_E_NNTP_HEADERS_FAILED, idsNNTPErrHeadersFailed },
  113. { IXP_E_NNTP_XHDR_FAILED, idsNNTPErrXhdrFailed },
  114. { IXP_E_CONNECTION_DROPPED, idsErrPeerClosed },
  115. { E_OUTOFMEMORY, idsMemory },
  116. { IXP_E_SICILY_LOGON_FAILED, IDS_IXP_E_SICILY_LOGON_FAILED },
  117. { IXP_E_LOAD_SICILY_FAILED, idsErrSicilyFailedToLoad },
  118. { IXP_E_CANT_FIND_HOST, idsErrCantFindHost },
  119. { IXP_E_NNTP_INVALID_USERPASS, idsNNTPErrPasswordFailed },
  120. { IXP_E_TIMEOUT, idsNNTPErrServerTimeout }
  121. };
  122. int iString = idsNNTPErrUnknownResponse;
  123. int bCreatedEscaped;
  124. LPSTR pszEscapedAcct;
  125. // 2* in case every char is an ampersand, +1 for the terminator
  126. if (bCreatedEscaped = MemAlloc((LPVOID*)&pszEscapedAcct, 2*lstrlen(pszAccount)+1))
  127. PszEscapeMenuStringA(pszAccount, pszEscapedAcct, 2*lstrlen(pszAccount)+1);
  128. else
  129. pszEscapedAcct = pszAccount;
  130. // Look up the string in the string resource
  131. for (UINT i = 0; i < ARRAYSIZE(rgErrorStrings); i++)
  132. {
  133. if (hr == rgErrorStrings[i][0])
  134. {
  135. iString = rgErrorStrings[i][1];
  136. break;
  137. }
  138. }
  139. // Allocate a buffer for the string we're going to return
  140. LPTSTR psz;
  141. DWORD cchSize = (CCHMAX_STRINGRES + lstrlen(pszEscapedAcct) + lstrlen(pszGroup));
  142. if (!MemAlloc((LPVOID*) &psz, sizeof(TCHAR) * cchSize))
  143. {
  144. if (bCreatedEscaped)
  145. MemFree(pszEscapedAcct);
  146. return NULL;
  147. }
  148. // Load the string resource
  149. TCHAR szRes[CCHMAX_STRINGRES];
  150. AthLoadString(iString, szRes, ARRAYSIZE(szRes));
  151. // Add any extra information to the error string that might be necessary
  152. switch (iString)
  153. {
  154. // Requires account name
  155. case idsNNTPErrUnknownResponse:
  156. case idsNNTPErrNewgroupsFailed:
  157. case idsNNTPErrListFailed:
  158. case idsNNTPErrPostFailed:
  159. case idsNNTPErrDateFailed:
  160. case idsErrCantFindHost:
  161. case idsNNTPErrPasswordFailed:
  162. case idsNNTPErrServerTimeout:
  163. wnsprintf(psz, cchSize, szRes, pszEscapedAcct);
  164. break;
  165. // Group name, then account name
  166. case idsNNTPErrListGroupFailed:
  167. case idsNNTPErrGroupFailed:
  168. case idsNNTPErrGroupNotFound:
  169. wnsprintf(psz, cchSize, szRes, pszGroup, pszEscapedAcct);
  170. break;
  171. // Group name only
  172. case idsNNTPErrHeadersFailed:
  173. case idsNNTPErrXhdrFailed:
  174. wnsprintf(psz, cchSize, szRes, pszGroup);
  175. break;
  176. default:
  177. StrCpyN(psz, szRes, cchSize);
  178. }
  179. if (bCreatedEscaped)
  180. MemFree(pszEscapedAcct);
  181. return (psz);
  182. }
  183. //
  184. // FUNCTION: XPUtil_DisplayIXPError()
  185. //
  186. // PURPOSE: Displays a dialog box with the information from an IXPRESULT
  187. // structure.
  188. //
  189. // PARAMETERS:
  190. // <in> pIxpResult - Pointer to the IXPRESULT structure to display.
  191. //
  192. int XPUtil_DisplayIXPError(HWND hwndParent, LPIXPRESULT pIxpResult,
  193. IInternetTransport *pTransport)
  194. {
  195. CTransportErrorDlg *pDlg = 0;
  196. int iReturn = 0;
  197. pDlg = new CTransportErrorDlg(pIxpResult, pTransport);
  198. if (pDlg)
  199. iReturn = pDlg->Create(hwndParent);
  200. delete pDlg;
  201. return (iReturn);
  202. }
  203. //
  204. // FUNCTION: CTransportErrorDlg::CTransportErrorDlg()
  205. //
  206. // PURPOSE: Initializes the CTransportErrorDlg class.
  207. //
  208. CTransportErrorDlg::CTransportErrorDlg(LPIXPRESULT pIxpResult, IInternetTransport *pTransport)
  209. {
  210. m_hwnd = 0;
  211. m_fExpanded = TRUE;
  212. ZeroMemory(&m_rcDlg, sizeof(RECT));
  213. m_pIxpResult = pIxpResult;
  214. m_pTransport = pTransport;
  215. m_pTransport->AddRef();
  216. }
  217. CTransportErrorDlg::~CTransportErrorDlg()
  218. {
  219. m_pTransport->Release();
  220. }
  221. BOOL CTransportErrorDlg::Create(HWND hwndParent)
  222. {
  223. return ((0 != DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddTransportErrorDlg),
  224. hwndParent, ErrorDlgProc, (LPARAM) this)));
  225. }
  226. //
  227. // FUNCTION: CTransportError::ErrorDlgProc()
  228. //
  229. // PURPOSE: Dialog callback for the IXPError dialog.
  230. //
  231. INT_PTR CALLBACK CTransportErrorDlg::ErrorDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam,
  232. LPARAM lParam)
  233. {
  234. CTransportErrorDlg *pThis = (CTransportErrorDlg *) GetWindowLongPtr(hwnd, DWLP_USER);
  235. switch (uMsg)
  236. {
  237. case WM_INITDIALOG:
  238. // Stash the this pointer so we can use it later
  239. Assert(lParam);
  240. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  241. pThis = (CTransportErrorDlg *) lParam;
  242. return (BOOL) HANDLE_WM_INITDIALOG(hwnd, wParam, lParam,
  243. pThis->OnInitDialog);
  244. case WM_COMMAND:
  245. if (pThis)
  246. HANDLE_WM_COMMAND(hwnd, wParam, lParam, pThis->OnCommand);
  247. return (TRUE);
  248. case WM_CLOSE:
  249. Assert(pThis);
  250. if (pThis)
  251. HANDLE_WM_CLOSE(hwnd, wParam, lParam, pThis->OnClose);
  252. break;
  253. }
  254. return (FALSE);
  255. }
  256. //
  257. // FUNCTION: CTransportErrorDlg::OnInitDialog()
  258. //
  259. // PURPOSE: Initializes the dialog by setting the error strings and the
  260. // detail strings.
  261. //
  262. // PARAMETERS:
  263. // <in> hwnd - Handle of the dialog window.
  264. // <in> hwndFocus - Handle of the control that will start with the focus.
  265. // <in> lParam - Extra data being passed to the dialog.
  266. //
  267. // RETURN VALUE:
  268. // Return TRUE to set the focus to hwndFocus
  269. //
  270. BOOL CTransportErrorDlg::OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam)
  271. {
  272. RECT rcSep;
  273. HWND hwndDetails = GetDlgItem(hwnd, idcXPErrDetailText);
  274. // Save our window handle
  275. m_hwnd = hwnd;
  276. // Initialize the rectangles that we'll need for sizing later
  277. GetWindowRect(GetDlgItem(hwnd, idcXPErrSep), &rcSep);
  278. GetWindowRect(hwnd, &m_rcDlg);
  279. m_cyCollapsed = rcSep.top - m_rcDlg.top;
  280. ExpandCollapse(FALSE);
  281. // Center the error dialog over the desktop
  282. CenterDialog(hwnd);
  283. // Set the information into the dialog
  284. Assert(m_pIxpResult->pszProblem);
  285. SetDlgItemText(hwnd, idcXPErrError, m_pIxpResult->pszProblem);
  286. // Set up the details information
  287. TCHAR szRes[CCHMAX_STRINGRES];
  288. TCHAR szBuf[CCHMAX_STRINGRES + CCHMAX_ACCOUNT_NAME];
  289. INETSERVER rInetServer;
  290. // Server Response:
  291. if (AthLoadString(idsDetail_ServerResponse, szRes, ARRAYSIZE(szRes)))
  292. {
  293. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  294. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szRes);
  295. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  296. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)g_szCRLF);
  297. }
  298. if (m_pIxpResult->pszResponse)
  299. {
  300. SendMessage(hwndDetails, EM_SETSEL, (WPARAM) -1, (LPARAM) -1);
  301. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM) m_pIxpResult->pszResponse);
  302. SendMessage(hwndDetails, EM_SETSEL, (WPARAM) -1, (LPARAM )-1);
  303. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM) g_szCRLF);
  304. SendMessage(hwndDetails, EM_SETSEL, (WPARAM) -1, (LPARAM) -1);
  305. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM) g_szCRLF);
  306. }
  307. // Get the account information from the server
  308. m_pTransport->GetServerInfo(&rInetServer);
  309. if (AthLoadString(idsDetails_Config, szRes, ARRAYSIZE(szRes)))
  310. {
  311. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  312. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szRes);
  313. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  314. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)g_szCRLF);
  315. }
  316. // Account:
  317. if (!FIsStringEmpty(rInetServer.szAccount))
  318. {
  319. if (AthLoadString(idsDetail_Account, szRes, sizeof(szRes)/sizeof(TCHAR)))
  320. {
  321. wnsprintf(szBuf, ARRAYSIZE(szBuf), " %s %s\r\n", szRes, rInetServer.szAccount);
  322. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  323. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szBuf);
  324. }
  325. }
  326. // Server:
  327. if (!FIsStringEmpty(rInetServer.szServerName))
  328. {
  329. TCHAR szServer[255 + CCHMAX_SERVER_NAME];
  330. if (AthLoadString(idsDetail_Server, szRes, sizeof(szRes)/sizeof(TCHAR)))
  331. {
  332. wnsprintf(szServer, ARRAYSIZE(szServer), " %s %s\r\n", szRes, rInetServer.szServerName);
  333. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  334. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szServer);
  335. }
  336. }
  337. // Port:
  338. if (AthLoadString(idsDetail_Port, szRes, sizeof(szRes)/sizeof(TCHAR)))
  339. {
  340. wnsprintf(szBuf, ARRAYSIZE(szBuf), " %s %d\r\n", szRes, rInetServer.dwPort);
  341. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  342. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szBuf);
  343. }
  344. // Secure:
  345. if (AthLoadString(idsDetail_Secure, szRes, sizeof(szRes)/sizeof(TCHAR)))
  346. {
  347. wnsprintf(szBuf, ARRAYSIZE(szBuf), " %s %d\r\n", szRes, rInetServer.fSSL);
  348. SendMessage(hwndDetails, EM_SETSEL, (WPARAM)-1, (LPARAM)-1);
  349. SendMessage(hwndDetails, EM_REPLACESEL, FALSE, (LPARAM)szBuf);
  350. }
  351. return (TRUE);
  352. }
  353. //
  354. // FUNCTION: CTransportErrorDlg::OnCommand()
  355. //
  356. // PURPOSE: Handle the various command messages dispatched from the dialog
  357. //
  358. void CTransportErrorDlg::OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify)
  359. {
  360. switch (id)
  361. {
  362. case IDOK:
  363. EndDialog(hwnd, 0);
  364. break;
  365. case idcXPErrDetails:
  366. ExpandCollapse(!m_fExpanded);
  367. break;
  368. }
  369. }
  370. //
  371. // FUNCTION: CTransportErrorDlg::OnClose()
  372. //
  373. // PURPOSE: Handles the WM_CLOSE notification by sending an IDOK to
  374. // the dialog.
  375. //
  376. void CTransportErrorDlg::OnClose(HWND hwnd)
  377. {
  378. SendMessage(hwnd, WM_COMMAND, IDOK, 0);
  379. }
  380. //
  381. // FUNCTION: CTransportErrorDlg::ExpandCollapse()
  382. //
  383. // PURPOSE: Takes care of showing and hiding the "details" part of the
  384. // error dialog.
  385. //
  386. // PARAMETERS:
  387. // <in> fExpand - TRUE if we should be expanding the dialog.
  388. //
  389. void CTransportErrorDlg::ExpandCollapse(BOOL fExpand)
  390. {
  391. RECT rcSep;
  392. TCHAR szBuf[64];
  393. // Nothing to do
  394. if (m_fExpanded == fExpand)
  395. return;
  396. m_fExpanded = fExpand;
  397. GetWindowRect(GetDlgItem(m_hwnd, idcXPErrSep), &rcSep);
  398. if (!m_fExpanded)
  399. SetWindowPos(m_hwnd, 0, 0, 0, m_rcDlg.right - m_rcDlg.left,
  400. m_cyCollapsed, SWP_NOMOVE | SWP_NOZORDER);
  401. else
  402. SetWindowPos(m_hwnd, 0, 0, 0, m_rcDlg.right - m_rcDlg.left,
  403. m_rcDlg.bottom - m_rcDlg.top, SWP_NOMOVE | SWP_NOZORDER);
  404. AthLoadString(m_fExpanded ? idsHideDetails : idsShowDetails, szBuf,
  405. ARRAYSIZE(szBuf));
  406. SetDlgItemText(m_hwnd, idcXPErrDetails, szBuf);
  407. EnableWindow(GetDlgItem(m_hwnd, idcXPErrDetailText), m_fExpanded);
  408. }