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.

6569 lines
206 KiB

  1. // --------------------------------------------------------------------------------
  2. // Ixphttpm.cpp
  3. // Copyright (c)1998 Microsoft Corporation, All Rights Reserved
  4. // Greg Friedman
  5. // --------------------------------------------------------------------------------
  6. #include "pch.hxx"
  7. #include "dllmain.h"
  8. #include "ixphttpm.h"
  9. #include "wininet.h"
  10. #include "ocidl.h"
  11. #include "Vstream.h"
  12. #include "shlwapi.h"
  13. #include "htmlstr.h"
  14. #include "strconst.h"
  15. #include "propfind.h"
  16. #include "davparse.h"
  17. #include "davstrs.h"
  18. #include <ntverp.h>
  19. #include <process.h>
  20. #include "oleutil.h"
  21. #include "ixputil.h"
  22. #include <demand.h>
  23. extern HRESULT HrGetLastError(void);
  24. typedef struct tagHTTPERROR
  25. {
  26. DWORD dwHttpError;
  27. HRESULT ixpResult;
  28. } HTTPERROR, *LPHTTPERROR;
  29. static const HTTPERROR c_rgHttpErrorMap[] =
  30. {
  31. { HTTP_STATUS_USE_PROXY, IXP_E_HTTP_USE_PROXY },
  32. { HTTP_STATUS_BAD_REQUEST, IXP_E_HTTP_BAD_REQUEST },
  33. { HTTP_STATUS_DENIED, IXP_E_HTTP_UNAUTHORIZED },
  34. { HTTP_STATUS_FORBIDDEN, IXP_E_HTTP_FORBIDDEN },
  35. { HTTP_STATUS_NOT_FOUND, IXP_E_HTTP_NOT_FOUND },
  36. { HTTP_STATUS_BAD_METHOD, IXP_E_HTTP_METHOD_NOT_ALLOW },
  37. { HTTP_STATUS_NONE_ACCEPTABLE, IXP_E_HTTP_NOT_ACCEPTABLE },
  38. { HTTP_STATUS_PROXY_AUTH_REQ, IXP_E_HTTP_PROXY_AUTH_REQ },
  39. { HTTP_STATUS_REQUEST_TIMEOUT, IXP_E_HTTP_REQUEST_TIMEOUT },
  40. { HTTP_STATUS_CONFLICT, IXP_E_HTTP_CONFLICT },
  41. { HTTP_STATUS_GONE, IXP_E_HTTP_GONE },
  42. { HTTP_STATUS_LENGTH_REQUIRED, IXP_E_HTTP_LENGTH_REQUIRED },
  43. { HTTP_STATUS_PRECOND_FAILED, IXP_E_HTTP_PRECOND_FAILED },
  44. { HTTP_STATUS_SERVER_ERROR, IXP_E_HTTP_INTERNAL_ERROR },
  45. { HTTP_STATUS_NOT_SUPPORTED, IXP_E_HTTP_NOT_IMPLEMENTED },
  46. { HTTP_STATUS_BAD_GATEWAY, IXP_E_HTTP_BAD_GATEWAY },
  47. { HTTP_STATUS_SERVICE_UNAVAIL, IXP_E_HTTP_SERVICE_UNAVAIL },
  48. { HTTP_STATUS_GATEWAY_TIMEOUT, IXP_E_HTTP_GATEWAY_TIMEOUT },
  49. { HTTP_STATUS_VERSION_NOT_SUP, IXP_E_HTTP_VERS_NOT_SUP },
  50. { 425, IXP_E_HTTP_INSUFFICIENT_STORAGE }, // obsolete out of storage error
  51. { 507, IXP_E_HTTP_INSUFFICIENT_STORAGE }, // preferred out of storage error
  52. { ERROR_INTERNET_OUT_OF_HANDLES, E_OUTOFMEMORY },
  53. { ERROR_INTERNET_TIMEOUT, IXP_E_TIMEOUT },
  54. { ERROR_INTERNET_NAME_NOT_RESOLVED, IXP_E_CANT_FIND_HOST },
  55. { ERROR_INTERNET_CANNOT_CONNECT, IXP_E_FAILED_TO_CONNECT },
  56. { HTTP_STATUS_NOT_MODIFIED, IXP_E_HTTP_NOT_MODIFIED},
  57. };
  58. #define FAIL_ABORT \
  59. if (WasAborted()) \
  60. { \
  61. hr = TrapError(IXP_E_USER_CANCEL); \
  62. goto exit; \
  63. } \
  64. else
  65. #define FAIL_EXIT_STREAM_WRITE(stream, psz) \
  66. if (FAILED(hr = stream.Write(psz, lstrlen(psz), NULL))) \
  67. goto exit; \
  68. else
  69. #define FAIL_EXIT(hr) \
  70. if (FAILED(hr)) \
  71. goto exit; \
  72. else
  73. #define FAIL_CREATEWND \
  74. if (!m_hwnd && !CreateWnd()) \
  75. { \
  76. hr = TrapError(E_OUTOFMEMORY); \
  77. goto exit; \
  78. } \
  79. else
  80. // these arrays describe element stack states, and are used to asses
  81. // the current state of the element stack
  82. static const HMELE c_rgPropFindPropStatStack[] =
  83. {
  84. HMELE_DAV_MULTISTATUS,
  85. HMELE_DAV_RESPONSE,
  86. HMELE_DAV_PROPSTAT
  87. };
  88. static const HMELE c_rgPropFindPropValueStack[] =
  89. {
  90. HMELE_DAV_MULTISTATUS,
  91. HMELE_DAV_RESPONSE,
  92. HMELE_DAV_PROPSTAT,
  93. HMELE_DAV_PROP,
  94. HMELE_UNKNOWN // wildcard
  95. };
  96. static const HMELE c_rgPropFindResponseStack[] =
  97. {
  98. HMELE_DAV_MULTISTATUS,
  99. HMELE_DAV_RESPONSE
  100. };
  101. static const HMELE c_rgMultiStatusResponseChildStack[] =
  102. {
  103. HMELE_DAV_MULTISTATUS,
  104. HMELE_DAV_RESPONSE,
  105. HMELE_UNKNOWN
  106. };
  107. static const HMELE c_rgPropFindStatusStack[] =
  108. {
  109. HMELE_DAV_MULTISTATUS,
  110. HMELE_DAV_RESPONSE,
  111. HMELE_DAV_PROPSTAT,
  112. HMELE_DAV_STATUS
  113. };
  114. // GET command
  115. static const PFNHTTPMAILOPFUNC c_rgpfGet[] =
  116. {
  117. &CHTTPMailTransport::OpenRequest,
  118. &CHTTPMailTransport::AddCommonHeaders,
  119. &CHTTPMailTransport::SendRequest,
  120. &CHTTPMailTransport::ProcessGetResponse,
  121. &CHTTPMailTransport::FinalizeRequest
  122. };
  123. // DELETE command
  124. static const PFNHTTPMAILOPFUNC c_rgpfDelete[] =
  125. {
  126. &CHTTPMailTransport::OpenRequest,
  127. &CHTTPMailTransport::AddCommonHeaders,
  128. &CHTTPMailTransport::SendRequest,
  129. &CHTTPMailTransport::FinalizeRequest
  130. };
  131. // PROPPATCH command
  132. static const PFNHTTPMAILOPFUNC c_rgpfnPropPatch[] =
  133. {
  134. &CHTTPMailTransport::GeneratePropPatchXML,
  135. &CHTTPMailTransport::OpenRequest,
  136. &CHTTPMailTransport::AddCommonHeaders,
  137. &CHTTPMailTransport::SendRequest,
  138. &CHTTPMailTransport::FinalizeRequest
  139. };
  140. // MKCOL command
  141. static const PFNHTTPMAILOPFUNC c_rgpfnMkCol[] =
  142. {
  143. &CHTTPMailTransport::OpenRequest,
  144. &CHTTPMailTransport::AddCharsetLine,
  145. &CHTTPMailTransport::SendRequest,
  146. &CHTTPMailTransport::ProcessCreatedResponse,
  147. &CHTTPMailTransport::ProcessLocationResponse,
  148. &CHTTPMailTransport::FinalizeRequest
  149. };
  150. // COPY command
  151. static const PFNHTTPMAILOPFUNC c_rgpfnCopy[] =
  152. {
  153. &CHTTPMailTransport::OpenRequest,
  154. &CHTTPMailTransport::AddDestinationHeader,
  155. &CHTTPMailTransport::AddCommonHeaders,
  156. &CHTTPMailTransport::SendRequest,
  157. &CHTTPMailTransport::ProcessCreatedResponse,
  158. &CHTTPMailTransport::ProcessLocationResponse,
  159. &CHTTPMailTransport::FinalizeRequest
  160. };
  161. // MOVE command
  162. static const PFNHTTPMAILOPFUNC c_rgpfnMove[] =
  163. {
  164. &CHTTPMailTransport::OpenRequest,
  165. &CHTTPMailTransport::AddDestinationHeader,
  166. &CHTTPMailTransport::AddCommonHeaders,
  167. &CHTTPMailTransport::SendRequest,
  168. &CHTTPMailTransport::ProcessCreatedResponse,
  169. &CHTTPMailTransport::ProcessLocationResponse,
  170. &CHTTPMailTransport::FinalizeRequest
  171. };
  172. // BMOVE command (data applies to bcopy and bmove)
  173. #define BCOPYMOVE_MAXRESPONSES 10
  174. XP_BEGIN_SCHEMA(HTTPMAILBCOPYMOVE)
  175. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_MSVALIDMSRESPONSECHILD, XPCDT_STRA, HTTPMAILBCOPYMOVE, pszHref)
  176. XP_SCHEMA_COL(HMELE_DAV_LOCATION, XPCF_MSVALIDMSRESPONSECHILD, XPCDT_STRA, HTTPMAILBCOPYMOVE, pszLocation)
  177. XP_SCHEMA_COL(HMELE_DAV_STATUS, XPCF_MSVALIDMSRESPONSECHILD, XPCDT_IXPHRESULT, HTTPMAILBCOPYMOVE, hrResult)
  178. XP_END_SCHEMA
  179. static const PFNHTTPMAILOPFUNC c_rgpfnBMove[] =
  180. {
  181. &CHTTPMailTransport::InitBCopyMove,
  182. &CHTTPMailTransport::OpenRequest,
  183. &CHTTPMailTransport::AddDestinationHeader,
  184. &CHTTPMailTransport::AddCommonHeaders,
  185. &CHTTPMailTransport::SendRequest,
  186. &CHTTPMailTransport::ProcessXMLResponse,
  187. &CHTTPMailTransport::FinalizeRequest
  188. };
  189. static const XMLPARSEFUNCS c_rgpfnBCopyMoveParse[] =
  190. {
  191. &CHTTPMailTransport::CreateElement,
  192. &CHTTPMailTransport::BCopyMove_HandleText,
  193. &CHTTPMailTransport::BCopyMove_EndChildren
  194. };
  195. // MemberInfo Data. There are four schemas associated with this command.
  196. // The first three are used to build up the propfind request, and are
  197. // not used to parse responses. The fourth is the combined schema that
  198. // is used for parsing.
  199. //
  200. // THE FOURTH SCHEMA MUST BE KEPT IN SYNC WITH THE FIRST THREE TO
  201. // GUARANTEE THAT RESPONSES WILL BE PARSED CORRECTLY.
  202. #define MEMBERINFO_MAXRESPONSES 10
  203. // common property schema - used only for building the request
  204. XP_BEGIN_SCHEMA(HTTPMEMBERINFO_COMMON)
  205. // common properties
  206. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_PROPFINDHREF, XPCDT_STRA, HTTPMEMBERINFO, pszHref)
  207. XP_SCHEMA_COL(HMELE_DAV_ISFOLDER, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fIsFolder)
  208. XP_END_SCHEMA
  209. // folder property schema - used only for building the request
  210. XP_BEGIN_SCHEMA(HTTPMEMBERINFO_FOLDER)
  211. XP_SCHEMA_COL(HMELE_DAV_DISPLAYNAME, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszDisplayName)
  212. XP_SCHEMA_COL(HMELE_HTTPMAIL_SPECIAL, XPFC_PROPFINDPROP, XPCDT_HTTPSPECIALFOLDER, HTTPMEMBERINFO, tySpecial)
  213. XP_SCHEMA_COL(HMELE_DAV_HASSUBS, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fHasSubs)
  214. XP_SCHEMA_COL(HMELE_DAV_NOSUBS, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fNoSubs)
  215. XP_SCHEMA_COL(HMELE_HTTPMAIL_UNREADCOUNT, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwUnreadCount)
  216. XP_SCHEMA_COL(HMELE_DAV_VISIBLECOUNT, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwVisibleCount)
  217. XP_SCHEMA_COL(HMELE_HTTPMAIL_SPECIAL, XPFC_PROPFINDPROP, XPCDT_HTTPSPECIALFOLDER, HTTPMEMBERINFO, tySpecial)
  218. XP_END_SCHEMA
  219. // message property schema - used only for building the request
  220. XP_BEGIN_SCHEMA(HTTPMEMBERINFO_MESSAGE)
  221. XP_SCHEMA_COL(HMELE_HTTPMAIL_READ, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fRead)
  222. XP_SCHEMA_COL(HMELE_MAIL_HASATTACHMENT, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fHasAttachment)
  223. XP_SCHEMA_COL(HMELE_MAIL_TO, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszTo)
  224. XP_SCHEMA_COL(HMELE_MAIL_FROM, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszFrom)
  225. XP_SCHEMA_COL(HMELE_MAIL_SUBJECT, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszSubject)
  226. XP_SCHEMA_COL(HMELE_MAIL_DATE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszDate)
  227. XP_SCHEMA_COL(HMELE_DAV_GETCONTENTLENGTH, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwContentLength)
  228. XP_END_SCHEMA
  229. // combined schema - used for parsing responses
  230. XP_BEGIN_SCHEMA(HTTPMEMBERINFO)
  231. // common properties
  232. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_PROPFINDHREF, XPCDT_STRA, HTTPMEMBERINFO, pszHref)
  233. XP_SCHEMA_COL(HMELE_DAV_ISFOLDER, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fIsFolder)
  234. // folder properties
  235. XP_SCHEMA_COL(HMELE_DAV_DISPLAYNAME, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszDisplayName)
  236. XP_SCHEMA_COL(HMELE_HTTPMAIL_SPECIAL, XPFC_PROPFINDPROP, XPCDT_HTTPSPECIALFOLDER, HTTPMEMBERINFO, tySpecial)
  237. XP_SCHEMA_COL(HMELE_DAV_HASSUBS, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fHasSubs)
  238. XP_SCHEMA_COL(HMELE_DAV_NOSUBS, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fNoSubs)
  239. XP_SCHEMA_COL(HMELE_HTTPMAIL_UNREADCOUNT, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwUnreadCount)
  240. XP_SCHEMA_COL(HMELE_DAV_VISIBLECOUNT, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwVisibleCount)
  241. XP_SCHEMA_COL(HMELE_HTTPMAIL_SPECIAL, XPFC_PROPFINDPROP, XPCDT_HTTPSPECIALFOLDER, HTTPMEMBERINFO, tySpecial)
  242. // message properties
  243. XP_SCHEMA_COL(HMELE_HTTPMAIL_READ, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fRead)
  244. XP_SCHEMA_COL(HMELE_MAIL_HASATTACHMENT, XPFC_PROPFINDPROP, XPCDT_BOOL, HTTPMEMBERINFO, fHasAttachment)
  245. XP_SCHEMA_COL(HMELE_MAIL_TO, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszTo)
  246. XP_SCHEMA_COL(HMELE_MAIL_FROM, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszFrom)
  247. XP_SCHEMA_COL(HMELE_MAIL_SUBJECT, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszSubject)
  248. XP_SCHEMA_COL(HMELE_MAIL_DATE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPMEMBERINFO, pszDate)
  249. XP_SCHEMA_COL(HMELE_DAV_GETCONTENTLENGTH, XPFC_PROPFINDPROP, XPCDT_DWORD, HTTPMEMBERINFO, dwContentLength)
  250. XP_END_SCHEMA
  251. static const XMLPARSEFUNCS c_rgpfnMemberInfoParse[] =
  252. {
  253. &CHTTPMailTransport::CreateElement,
  254. &CHTTPMailTransport::MemberInfo_HandleText,
  255. &CHTTPMailTransport::MemberInfo_EndChildren
  256. };
  257. static const PFNHTTPMAILOPFUNC c_rgpfnMemberInfo[] =
  258. {
  259. &CHTTPMailTransport::InitMemberInfo,
  260. &CHTTPMailTransport::GeneratePropFindXML,
  261. &CHTTPMailTransport::OpenRequest,
  262. &CHTTPMailTransport::AddDepthHeader,
  263. &CHTTPMailTransport::AddCommonHeaders,
  264. &CHTTPMailTransport::SendRequest,
  265. &CHTTPMailTransport::ProcessXMLResponse,
  266. &CHTTPMailTransport::RequireMultiStatus,
  267. &CHTTPMailTransport::FinalizeRequest
  268. };
  269. // Operations which share MemberError-based responses (MarkRead, BDELETE)
  270. #define MEMBERERROR_MAXRESPONSES 10
  271. XP_BEGIN_SCHEMA(HTTPMEMBERERROR)
  272. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_PROPFINDHREF, XPCDT_STRA, HTTPMEMBERERROR, pszHref)
  273. XP_SCHEMA_COL(HMELE_DAV_STATUS, XPCF_MSVALIDMSRESPONSECHILD, XPCDT_IXPHRESULT, HTTPMEMBERERROR, hrResult)
  274. XP_END_SCHEMA
  275. static const XMLPARSEFUNCS c_rgpfnMemberErrorParse[] =
  276. {
  277. &CHTTPMailTransport::CreateElement,
  278. &CHTTPMailTransport::MemberError_HandleText,
  279. &CHTTPMailTransport::MemberError_EndChildren
  280. };
  281. static const PFNHTTPMAILOPFUNC c_rgpfnMarkRead[] =
  282. {
  283. &CHTTPMailTransport::InitMemberError,
  284. &CHTTPMailTransport::OpenRequest,
  285. &CHTTPMailTransport::AddCommonHeaders,
  286. &CHTTPMailTransport::SendRequest,
  287. &CHTTPMailTransport::ProcessXMLResponse,
  288. &CHTTPMailTransport::FinalizeRequest
  289. };
  290. // SendMessage
  291. static const PFNHTTPMAILOPFUNC c_rgpfnSendMessage[] =
  292. {
  293. &CHTTPMailTransport::OpenRequest,
  294. &CHTTPMailTransport::AddContentTypeHeader,
  295. &CHTTPMailTransport::AddCommonHeaders,
  296. &CHTTPMailTransport::SendPostRequest,
  297. &CHTTPMailTransport::ProcessPostResponse,
  298. &CHTTPMailTransport::FinalizeRequest
  299. };
  300. // RootProps
  301. XP_BEGIN_SCHEMA(ROOTPROPS)
  302. XP_SCHEMA_COL(HMELE_HOTMAIL_ADBAR, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszAdbar)
  303. XP_SCHEMA_COL(HMELE_HTTPMAIL_CONTACTS, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszContacts)
  304. XP_SCHEMA_COL(HMELE_HTTPMAIL_INBOX, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszInbox)
  305. XP_SCHEMA_COL(HMELE_HTTPMAIL_OUTBOX, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszOutbox)
  306. XP_SCHEMA_COL(HMELE_HTTPMAIL_SENDMSG, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszSendMsg)
  307. XP_SCHEMA_COL(HMELE_HTTPMAIL_SENTITEMS, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszSentItems)
  308. XP_SCHEMA_COL(HMELE_HTTPMAIL_DELETEDITEMS, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszDeletedItems)
  309. XP_SCHEMA_COL(HMELE_HTTPMAIL_DRAFTS, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszDrafts)
  310. XP_SCHEMA_COL(HMELE_HTTPMAIL_MSGFOLDERROOT, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszMsgFolderRoot)
  311. XP_SCHEMA_COL(HMELE_HOTMAIL_MAXPOLLINGINTERVAL, XPFC_PROPFINDPROP, XPCDT_DWORD, ROOTPROPS, dwMaxPollingInterval)
  312. XP_SCHEMA_COL(HMELE_HOTMAIL_SIG, XPFC_PROPFINDPROP, XPCDT_STRA, ROOTPROPS, pszSig)
  313. XP_END_SCHEMA
  314. static const XMLPARSEFUNCS c_rgpfnRootPropsParse[] =
  315. {
  316. &CHTTPMailTransport::CreateElement,
  317. &CHTTPMailTransport::RootProps_HandleText,
  318. &CHTTPMailTransport::RootProps_EndChildren
  319. };
  320. static const PFNHTTPMAILOPFUNC c_rgpfnRootProps[] =
  321. {
  322. &CHTTPMailTransport::InitRootProps,
  323. &CHTTPMailTransport::GeneratePropFindXML,
  324. &CHTTPMailTransport::OpenRequest,
  325. &CHTTPMailTransport::AddDepthHeader,
  326. &CHTTPMailTransport::AddCommonHeaders,
  327. &CHTTPMailTransport::SendRequest,
  328. &CHTTPMailTransport::ProcessXMLResponse,
  329. &CHTTPMailTransport::FinalizeRootProps
  330. };
  331. static const PFNHTTPMAILOPFUNC c_rgpfnPost[] =
  332. {
  333. &CHTTPMailTransport::OpenRequest,
  334. &CHTTPMailTransport::AddContentTypeHeader,
  335. &CHTTPMailTransport::AddCharsetLine,
  336. &CHTTPMailTransport::SendPostRequest,
  337. //&CHTTPMailTransport::SendRequest,
  338. &CHTTPMailTransport::ProcessPostResponse,
  339. &CHTTPMailTransport::FinalizeRequest
  340. };
  341. static const PFNHTTPMAILOPFUNC c_rgpfnPut[] =
  342. {
  343. &CHTTPMailTransport::OpenRequest,
  344. &CHTTPMailTransport::AddCharsetLine,
  345. &CHTTPMailTransport::SendRequest,
  346. &CHTTPMailTransport::ProcessPostResponse,
  347. &CHTTPMailTransport::FinalizeRequest
  348. };
  349. // ListContacts Data
  350. #define LISTCONTACTS_MAXRESPONSES 10
  351. XP_BEGIN_SCHEMA(HTTPCONTACTID)
  352. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_PROPFINDHREF, XPCDT_STRA, HTTPCONTACTID, pszHref)
  353. XP_SCHEMA_COL(HMELE_DAV_ID, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTID, pszId)
  354. XP_SCHEMA_COL(HMELE_CONTACTS_GROUP, XPFC_PROPFINDPROP, XPCDT_HTTPCONTACTTYPE, HTTPCONTACTID, tyContact)
  355. XP_SCHEMA_COL(HMELE_HOTMAIL_MODIFIED, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTID, pszModified)
  356. XP_END_SCHEMA
  357. static const PFNHTTPMAILOPFUNC c_rgpfnListContacts[] =
  358. {
  359. &CHTTPMailTransport::InitListContacts,
  360. &CHTTPMailTransport::GeneratePropFindXML,
  361. &CHTTPMailTransport::OpenRequest,
  362. &CHTTPMailTransport::AddDepthHeader,
  363. &CHTTPMailTransport::AddCommonHeaders,
  364. &CHTTPMailTransport::SendRequest,
  365. &CHTTPMailTransport::ProcessXMLResponse,
  366. &CHTTPMailTransport::RequireMultiStatus,
  367. &CHTTPMailTransport::FinalizeRequest
  368. };
  369. static const XMLPARSEFUNCS c_rgpfnListContactsParse[] =
  370. {
  371. &CHTTPMailTransport::CreateElement,
  372. &CHTTPMailTransport::ListContacts_HandleText,
  373. &CHTTPMailTransport::ListContacts_EndChildren
  374. };
  375. // ContactInfo Data
  376. #define CONTACTINFO_MAXRESPONSES 10
  377. XP_BEGIN_SCHEMA(HTTPCONTACTINFO)
  378. XP_SCHEMA_COL(HMELE_DAV_HREF, XPCF_PROPFINDHREF, XPCDT_STRA, HTTPCONTACTINFO, pszHref)
  379. XP_SCHEMA_COL(HMELE_DAV_ID, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszId)
  380. XP_SCHEMA_COL(HMELE_CONTACTS_GROUP, XPFC_PROPFINDPROP, XPCDT_HTTPCONTACTTYPE, HTTPCONTACTINFO, tyContact)
  381. XP_SCHEMA_COL(HMELE_HOTMAIL_MODIFIED, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszModified)
  382. XP_SCHEMA_COL(HMELE_CONTACTS_CN, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszDisplayName)
  383. XP_SCHEMA_COL(HMELE_CONTACTS_GIVENNAME, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszGivenName)
  384. XP_SCHEMA_COL(HMELE_CONTACTS_SN, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszSurname)
  385. XP_SCHEMA_COL(HMELE_CONTACTS_NICKNAME, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszNickname)
  386. XP_SCHEMA_COL(HMELE_CONTACTS_MAIL, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszEmail)
  387. XP_SCHEMA_COL(HMELE_CONTACTS_HOMESTREET, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomeStreet)
  388. XP_SCHEMA_COL(HMELE_CONTACTS_HOMECITY, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomeCity)
  389. XP_SCHEMA_COL(HMELE_CONTACTS_HOMESTATE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomeState)
  390. XP_SCHEMA_COL(HMELE_CONTACTS_HOMEPOSTALCODE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomePostalCode)
  391. XP_SCHEMA_COL(HMELE_CONTACTS_HOMECOUNTRY, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomeCountry)
  392. XP_SCHEMA_COL(HMELE_CONTACTS_O, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszCompany)
  393. XP_SCHEMA_COL(HMELE_CONTACTS_STREET, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkStreet)
  394. XP_SCHEMA_COL(HMELE_CONTACTS_L, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkCity)
  395. XP_SCHEMA_COL(HMELE_CONTACTS_ST, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkState)
  396. XP_SCHEMA_COL(HMELE_CONTACTS_POSTALCODE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkPostalCode)
  397. XP_SCHEMA_COL(HMELE_CONTACTS_FRIENDLYCOUNTRYNAME, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkCountry)
  398. XP_SCHEMA_COL(HMELE_CONTACTS_HOMEPHONE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomePhone)
  399. XP_SCHEMA_COL(HMELE_CONTACTS_HOMEFAX, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszHomeFax)
  400. XP_SCHEMA_COL(HMELE_CONTACTS_TELEPHONENUMBER, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkPhone)
  401. XP_SCHEMA_COL(HMELE_CONTACTS_FACSIMILETELEPHONENUMBER, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszWorkFax)
  402. XP_SCHEMA_COL(HMELE_CONTACTS_MOBILE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszMobilePhone)
  403. XP_SCHEMA_COL(HMELE_CONTACTS_OTHERTELEPHONE, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszOtherPhone)
  404. XP_SCHEMA_COL(HMELE_CONTACTS_BDAY, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszBday)
  405. XP_SCHEMA_COL(HMELE_CONTACTS_PAGER, XPFC_PROPFINDPROP, XPCDT_STRA, HTTPCONTACTINFO, pszPager)
  406. XP_END_SCHEMA
  407. static const XMLPARSEFUNCS c_rgpfnContactInfoParse[] =
  408. {
  409. &CHTTPMailTransport::CreateElement,
  410. &CHTTPMailTransport::ContactInfo_HandleText,
  411. &CHTTPMailTransport::ContactInfo_EndChildren
  412. };
  413. static const PFNHTTPMAILOPFUNC c_rgpfnContactInfo[] =
  414. {
  415. &CHTTPMailTransport::InitContactInfo,
  416. &CHTTPMailTransport::GeneratePropFindXML,
  417. &CHTTPMailTransport::OpenRequest,
  418. &CHTTPMailTransport::AddDepthHeader,
  419. &CHTTPMailTransport::AddCommonHeaders,
  420. &CHTTPMailTransport::SendRequest,
  421. &CHTTPMailTransport::ProcessXMLResponse,
  422. &CHTTPMailTransport::FinalizeRequest
  423. };
  424. // PostContact Data
  425. static const PFNHTTPMAILOPFUNC c_rgpfnPostContact[] =
  426. {
  427. &CHTTPMailTransport::OpenRequest,
  428. &CHTTPMailTransport::AddCommonHeaders,
  429. &CHTTPMailTransport::SendRequest,
  430. &CHTTPMailTransport::ProcessPostContactResponse,
  431. &CHTTPMailTransport::InitListContacts,
  432. &CHTTPMailTransport::GeneratePropFindXML,
  433. &CHTTPMailTransport::OpenRequest,
  434. &CHTTPMailTransport::AddDepthHeader,
  435. &CHTTPMailTransport::AddCommonHeaders,
  436. &CHTTPMailTransport::SendRequest,
  437. &CHTTPMailTransport::ProcessXMLResponse,
  438. &CHTTPMailTransport::FinalizeRequest
  439. };
  440. static const XMLPARSEFUNCS c_rgpfnPostOrPatchContactParse[] =
  441. {
  442. &CHTTPMailTransport::CreateElement,
  443. &CHTTPMailTransport::PostOrPatchContact_HandleText,
  444. &CHTTPMailTransport::PostOrPatchContact_EndChildren
  445. };
  446. // PatchContact data
  447. static const PFNHTTPMAILOPFUNC c_rgpfnPatchContact[] =
  448. {
  449. &CHTTPMailTransport::GeneratePropPatchXML,
  450. &CHTTPMailTransport::OpenRequest,
  451. &CHTTPMailTransport::AddCommonHeaders,
  452. &CHTTPMailTransport::SendRequest,
  453. &CHTTPMailTransport::ProcessPatchContactResponse,
  454. &CHTTPMailTransport::InitListContacts,
  455. &CHTTPMailTransport::GeneratePropFindXML,
  456. &CHTTPMailTransport::OpenRequest,
  457. &CHTTPMailTransport::AddDepthHeader,
  458. &CHTTPMailTransport::AddCommonHeaders,
  459. &CHTTPMailTransport::SendRequest,
  460. &CHTTPMailTransport::ProcessXMLResponse,
  461. &CHTTPMailTransport::FinalizeRequest
  462. };
  463. // special folders
  464. typedef struct tagHTTPSPECIALFOLDER
  465. {
  466. const WCHAR *pwcName;
  467. ULONG ulLen;
  468. HTTPMAILSPECIALFOLDER tyFolder;
  469. } HTTPSPECIALFOLDER, *LPHTTPSPECIALFOLDER;
  470. static const HTTPSPECIALFOLDER c_rgpfnSpecialFolder[] =
  471. {
  472. { DAV_STR_LEN(InboxSpecialFolder), HTTPMAIL_SF_INBOX },
  473. { DAV_STR_LEN(DeletedItemsSpecialFolder), HTTPMAIL_SF_DELETEDITEMS },
  474. { DAV_STR_LEN(DraftsSpecialFolder), HTTPMAIL_SF_DRAFTS },
  475. { DAV_STR_LEN(OutboxSpecialFolder), HTTPMAIL_SF_OUTBOX },
  476. { DAV_STR_LEN(SentItemsSpecialFolder), HTTPMAIL_SF_SENTITEMS },
  477. { DAV_STR_LEN(ContactsSpecialFolder), HTTPMAIL_SF_CONTACTS },
  478. { DAV_STR_LEN(CalendarSpecialFolder), HTTPMAIL_SF_CALENDAR },
  479. { DAV_STR_LEN(MsnPromoSpecialFolder), HTTPMAIL_SF_MSNPROMO },
  480. { DAV_STR_LEN(BulkMailSpecialFolder), HTTPMAIL_SF_BULKMAIL },
  481. };
  482. #define VALIDSTACK(rg) ValidStack(rg, ARRAYSIZE(rg))
  483. static const char s_szHTTPMailWndClass[] = "HTTPMailWndClass";
  484. // Notification messages used to communicate between the async thread
  485. // and the window proc
  486. #define SPM_HTTPMAIL_STATECHANGED (WM_USER + 1)
  487. #define SPM_HTTPMAIL_SENDRESPONSE (WM_USER + 2)
  488. #define SPM_HTTPMAIL_LOGONPROMPT (WM_USER + 3)
  489. #define SPM_HTTPMAIL_GETPARENTWINDOW (WM_USER + 4)
  490. // --------------------------------------------------------------------------------
  491. // static functions
  492. // --------------------------------------------------------------------------------
  493. // --------------------------------------------------------------------------------
  494. // CHTTPMailTransport::_HrCrackUrl
  495. // --------------------------------------------------------------------------------
  496. HRESULT HrCrackUrl(
  497. LPSTR pszUrl,
  498. LPSTR *ppszHost,
  499. LPSTR *ppszPath,
  500. INTERNET_PORT *pPort)
  501. {
  502. URL_COMPONENTS uc;
  503. char szHost[INTERNET_MAX_HOST_NAME_LENGTH];
  504. char szPath[INTERNET_MAX_PATH_LENGTH];
  505. if (NULL == pszUrl)
  506. return E_INVALIDARG;
  507. if (ppszHost)
  508. *ppszHost = NULL;
  509. if (ppszPath)
  510. *ppszPath = NULL;
  511. if (pPort)
  512. *pPort = INTERNET_INVALID_PORT_NUMBER;
  513. ZeroMemory(&uc, sizeof(URL_COMPONENTS));
  514. uc.dwStructSize = sizeof(URL_COMPONENTS);
  515. uc.lpszHostName = szHost;
  516. uc.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
  517. uc.lpszUrlPath = szPath;
  518. uc.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
  519. if (!InternetCrackUrl(pszUrl, NULL, 0, &uc))
  520. return E_INVALIDARG;
  521. // validate the protocol
  522. if (INTERNET_SCHEME_HTTP != uc.nScheme && INTERNET_SCHEME_HTTPS != uc.nScheme)
  523. return E_INVALIDARG;
  524. // copy the response data
  525. if (ppszHost)
  526. {
  527. *ppszHost = PszDupA(uc.lpszHostName);
  528. if (!*ppszHost)
  529. return E_OUTOFMEMORY;
  530. }
  531. if (ppszPath)
  532. {
  533. *ppszPath = PszDupA(uc.lpszUrlPath);
  534. if (!*ppszPath)
  535. {
  536. SafeMemFree(*ppszHost);
  537. return E_OUTOFMEMORY;
  538. }
  539. }
  540. if (pPort)
  541. *pPort = uc.nPort;
  542. return S_OK;
  543. }
  544. // --------------------------------------------------------------------------------
  545. // Utility functions
  546. // --------------------------------------------------------------------------------
  547. // --------------------------------------------------------------------------------
  548. // HttpErrorToIxpResult
  549. // --------------------------------------------------------------------------------
  550. HRESULT HttpErrorToIxpResult(DWORD dwHttpError)
  551. {
  552. for (DWORD dw = 0; dw < ARRAYSIZE(c_rgHttpErrorMap); dw++)
  553. {
  554. if (c_rgHttpErrorMap[dw].dwHttpError == dwHttpError)
  555. return c_rgHttpErrorMap[dw].ixpResult;
  556. }
  557. return E_FAIL;
  558. }
  559. // --------------------------------------------------------------------------------
  560. // HrParseHTTPStatus
  561. // --------------------------------------------------------------------------------
  562. HRESULT HrParseHTTPStatus(LPSTR pszStatusStr, DWORD *pdwStatus)
  563. {
  564. LPSTR psz;
  565. LPSTR pszEnd;
  566. char chSaved;
  567. if (!pszStatusStr || !pdwStatus)
  568. return E_INVALIDARG;
  569. *pdwStatus = 0;
  570. // status is of the form "HTTP/1.1 200 OK"
  571. psz = PszSkipWhiteA(pszStatusStr);
  572. if ('\0' == *psz)
  573. return E_INVALIDARG;
  574. psz = PszScanToWhiteA(psz);
  575. if ('\0' == *psz)
  576. return E_INVALIDARG;
  577. psz = PszSkipWhiteA(psz);
  578. if ('\0' == *psz)
  579. return E_INVALIDARG;
  580. // psz now points at the numeric component
  581. pszEnd = PszScanToWhiteA(psz);
  582. if ('\0' == *psz)
  583. return E_INVALIDARG;
  584. // temporarily modify the string in place
  585. chSaved = *pszEnd;
  586. *pszEnd = '\0';
  587. *pdwStatus = StrToInt(psz);
  588. *pszEnd = chSaved;
  589. return S_OK;
  590. }
  591. // --------------------------------------------------------------------------------
  592. // HrGetStreamSize
  593. // --------------------------------------------------------------------------------
  594. static HRESULT HrGetStreamSize(LPSTREAM pstm, ULONG *pcb)
  595. {
  596. // Locals
  597. HRESULT hr=S_OK;
  598. ULARGE_INTEGER uliPos = {0,0};
  599. LARGE_INTEGER liOrigin = {0,0};
  600. // Seek
  601. hr = pstm->Seek(liOrigin, STREAM_SEEK_END, &uliPos);
  602. if (FAILED(hr))
  603. goto error;
  604. // set size
  605. *pcb = uliPos.LowPart;
  606. error:
  607. // Done
  608. return hr;
  609. }
  610. // --------------------------------------------------------------------------------
  611. // HrAddPropFindProps
  612. // --------------------------------------------------------------------------------
  613. HRESULT HrAddPropFindProps(IPropFindRequest *pRequest, const HMELE *rgEle, DWORD cEle)
  614. {
  615. HRESULT hr;
  616. HMELE ele;
  617. for (DWORD i = 0; i < cEle; ++i)
  618. {
  619. ele = rgEle[i];
  620. hr = pRequest->AddProperty(
  621. rgHTTPMailDictionary[ele].dwNamespaceID,
  622. const_cast<char *>(rgHTTPMailDictionary[ele].pszName));
  623. if (FAILED(hr))
  624. goto exit;
  625. }
  626. exit:
  627. return hr;
  628. }
  629. // --------------------------------------------------------------------------------
  630. // HrAddPropFindSchemaProps
  631. // --------------------------------------------------------------------------------
  632. HRESULT HrAddPropFindSchemaProps(
  633. IPropFindRequest *pRequest,
  634. const XPCOLUMN *prgCols,
  635. DWORD cCols)
  636. {
  637. HRESULT hr = S_OK;
  638. HMELE ele;
  639. for (DWORD i = 0; i < cCols; i++)
  640. {
  641. if (!!(prgCols[i].dwFlags & XPCF_PFREQUEST))
  642. {
  643. hr = pRequest->AddProperty(
  644. rgHTTPMailDictionary[prgCols[i].ele].dwNamespaceID,
  645. rgHTTPMailDictionary[prgCols[i].ele].pszName);
  646. if (FAILED(hr))
  647. goto exit;
  648. }
  649. }
  650. exit:
  651. return hr;
  652. }
  653. // --------------------------------------------------------------------------------
  654. // _HrGenerateRfc821Stream
  655. // --------------------------------------------------------------------------------
  656. HRESULT _HrGenerateRfc821Stream(LPCSTR pszFrom,
  657. LPHTTPTARGETLIST pTargets,
  658. IStream **ppRfc821Stream)
  659. {
  660. HRESULT hr = S_OK;
  661. IStream *pStream = NULL;
  662. DWORD dw;
  663. DWORD cbCloseTerm;
  664. DWORD cbRcptTo;
  665. IxpAssert(pszFrom);
  666. IxpAssert(pTargets);
  667. IxpAssert(ppRfc821Stream);
  668. *ppRfc821Stream = NULL;
  669. cbCloseTerm = lstrlen(c_szXMLCloseElementCRLF);
  670. cbRcptTo = lstrlen(c_szRcptTo);
  671. pStream = new CVirtualStream();
  672. if (NULL == pStream)
  673. {
  674. hr = TraceResult(E_OUTOFMEMORY);
  675. goto exit;
  676. }
  677. // write out 'mail from'
  678. FAIL_EXIT_STREAM_WRITE((*pStream), c_szMailFrom);
  679. FAIL_EXIT_STREAM_WRITE((*pStream), pszFrom);
  680. FAIL_EXIT(hr = pStream->Write(c_szXMLCloseElementCRLF, cbCloseTerm, NULL));
  681. // write out the 'rcpt to' lines
  682. for (dw = 0; dw < pTargets->cTarget; ++dw)
  683. {
  684. FAIL_EXIT(hr = pStream->Write(c_szRcptTo, cbRcptTo, NULL));
  685. FAIL_EXIT_STREAM_WRITE((*pStream), pTargets->prgTarget[dw]);
  686. FAIL_EXIT(hr = pStream->Write(c_szXMLCloseElementCRLF, cbCloseTerm, NULL));
  687. }
  688. // append an extra crlf to the end of the stream
  689. FAIL_EXIT_STREAM_WRITE((*pStream), c_szCRLF);
  690. *ppRfc821Stream = pStream;
  691. pStream = NULL;
  692. exit:
  693. SafeRelease(pStream);
  694. return hr;
  695. }
  696. // --------------------------------------------------------------------------------
  697. // _EscapeString
  698. // --------------------------------------------------------------------------------
  699. LPSTR _EscapeString(LPSTR pszIn)
  700. {
  701. CByteStream stream;
  702. DWORD dwLen;
  703. LPSTR pszLastNonEsc, pszNext, pszOut;
  704. HRESULT hr;
  705. if (NULL == pszIn)
  706. return NULL;
  707. pszLastNonEsc = pszIn;
  708. pszNext = pszIn;
  709. while (*pszNext)
  710. {
  711. switch (*pszNext)
  712. {
  713. case '<':
  714. case '>':
  715. case '&':
  716. if (FAILED(hr = stream.Write(pszLastNonEsc, (ULONG) (pszNext - pszLastNonEsc), NULL)))
  717. goto exit;
  718. if (*pszNext == '<')
  719. {
  720. if (FAILED(hr = stream.Write(c_szEscLessThan, lstrlen(c_szEscLessThan), NULL)))
  721. goto exit;
  722. }
  723. else if (*pszNext == '>')
  724. {
  725. if (FAILED(hr = stream.Write(c_szEscGreaterThan, lstrlen(c_szEscGreaterThan), NULL)))
  726. goto exit;
  727. }
  728. else
  729. {
  730. if (FAILED(hr = stream.Write(c_szEscAmp, lstrlen(c_szEscAmp), NULL)))
  731. goto exit;
  732. }
  733. pszLastNonEsc = CharNextExA(CP_ACP, pszNext, 0);
  734. break;
  735. }
  736. pszNext = CharNextExA(CP_ACP, pszNext, 0);
  737. }
  738. if (FAILED(hr = stream.Write(pszLastNonEsc, (ULONG) (pszNext - pszLastNonEsc), NULL)))
  739. goto exit;
  740. FAIL_EXIT(hr = stream.HrAcquireStringA(&dwLen, (LPSTR *)&pszOut, ACQ_DISPLACE));
  741. return pszOut;
  742. exit:
  743. return NULL;
  744. }
  745. const HMELE g_rgContactEle[] = {
  746. HMELE_UNKNOWN,
  747. HMELE_UNKNOWN,
  748. HMELE_UNKNOWN,
  749. HMELE_UNKNOWN,
  750. HMELE_UNKNOWN,
  751. HMELE_CONTACTS_GIVENNAME,
  752. HMELE_CONTACTS_SN,
  753. HMELE_CONTACTS_NICKNAME,
  754. HMELE_CONTACTS_MAIL,
  755. HMELE_CONTACTS_HOMESTREET,
  756. HMELE_CONTACTS_HOMECITY,
  757. HMELE_CONTACTS_HOMESTATE,
  758. HMELE_CONTACTS_HOMEPOSTALCODE,
  759. HMELE_CONTACTS_HOMECOUNTRY,
  760. HMELE_CONTACTS_O,
  761. HMELE_CONTACTS_STREET,
  762. HMELE_CONTACTS_L,
  763. HMELE_CONTACTS_ST,
  764. HMELE_CONTACTS_POSTALCODE,
  765. HMELE_CONTACTS_FRIENDLYCOUNTRYNAME,
  766. HMELE_CONTACTS_HOMEPHONE,
  767. HMELE_CONTACTS_HOMEFAX,
  768. HMELE_CONTACTS_TELEPHONENUMBER,
  769. HMELE_CONTACTS_FACSIMILETELEPHONENUMBER,
  770. HMELE_CONTACTS_MOBILE,
  771. HMELE_CONTACTS_OTHERTELEPHONE,
  772. HMELE_CONTACTS_BDAY,
  773. HMELE_CONTACTS_PAGER
  774. };
  775. #define CCHMAX_TAGBUFFER 128
  776. HRESULT HrGeneratePostContactXML(LPHTTPCONTACTINFO pciInfo, LPVOID *ppvXML, DWORD *pdwLen)
  777. {
  778. HRESULT hr = S_OK;
  779. CByteStream stream;
  780. CDAVNamespaceArbiterImp dna;
  781. DWORD dwIndex, dwSize = ARRAYSIZE(g_rgContactEle);
  782. DWORD iBufferSize;
  783. TCHAR szTagBuffer[CCHMAX_TAGBUFFER+1];
  784. LPSTR *prgsz = (LPSTR*)pciInfo, pszEsc;
  785. LPCSTR pszPropName;
  786. *ppvXML = NULL;
  787. *pdwLen = 0;
  788. if (NULL == ppvXML)
  789. return E_INVALIDARG;
  790. // write the DAV header. we ALWAYS post using the windows-1252 code
  791. // page for this release.
  792. if (FAILED(hr = stream.Write(c_szXML1252Head, lstrlen(c_szXML1252Head), NULL)))
  793. goto exit;
  794. dna.m_rgbNsUsed[DAVNAMESPACE_CONTACTS] = TRUE;
  795. dna.m_rgbNsUsed[DAVNAMESPACE_DAV] = TRUE;
  796. // write out the contacts header
  797. if (FAILED(hr = stream.Write(c_szContactHead, lstrlen(c_szContactHead), NULL)))
  798. goto exit;
  799. if (FAILED(hr = dna.WriteNamespaces(&stream)))
  800. goto exit;
  801. if (FAILED(hr = stream.Write(c_szXMLCloseElement, lstrlen(c_szXMLCloseElement), NULL)))
  802. goto exit;
  803. // [PaulHi] 3/11/99 Implementing WAB/HM group contact syncing
  804. // Include the xml group tag if this is a group contact item
  805. if (pciInfo->tyContact == HTTPMAIL_CT_GROUP)
  806. {
  807. if (FAILED(hr = stream.Write(c_szCRLFTab, lstrlen(c_szCRLFTab), NULL)))
  808. goto exit;
  809. if (FAILED(hr = stream.Write(c_szGroupSwitch, lstrlen(c_szGroupSwitch), NULL)))
  810. goto exit;
  811. }
  812. for (dwIndex = 0; dwIndex < dwSize; dwIndex ++)
  813. {
  814. if (prgsz[dwIndex] && g_rgContactEle[dwIndex] != HMELE_UNKNOWN)
  815. {
  816. pszPropName = rgHTTPMailDictionary[g_rgContactEle[dwIndex]].pszName;
  817. if (FAILED(hr = stream.Write(c_szOpenContactNamespace, lstrlen(c_szOpenContactNamespace), NULL)))
  818. goto exit;
  819. if (FAILED(hr = stream.Write(pszPropName, lstrlen(pszPropName), NULL)))
  820. goto exit;
  821. if (FAILED(hr = stream.Write(c_szXMLCloseElement, lstrlen(c_szXMLCloseElement), NULL)))
  822. goto exit;
  823. pszEsc = _EscapeString(prgsz[dwIndex]);
  824. if (!pszEsc)
  825. goto exit;
  826. hr = stream.Write(pszEsc, lstrlen(pszEsc), NULL);
  827. SafeMemFree(pszEsc);
  828. if (FAILED(hr))
  829. goto exit;
  830. if (FAILED(hr = stream.Write(c_szCloseContactNamespace, lstrlen(c_szCloseContactNamespace), NULL)))
  831. goto exit;
  832. if (FAILED(hr = stream.Write(pszPropName, lstrlen(pszPropName), NULL)))
  833. goto exit;
  834. if (FAILED(hr = stream.Write(c_szXMLCloseElement, lstrlen(c_szXMLCloseElement), NULL)))
  835. goto exit;
  836. }
  837. }
  838. if (FAILED(hr = stream.Write(c_szContactTail, lstrlen(c_szContactTail), NULL)))
  839. goto exit;
  840. FAIL_EXIT(hr = stream.HrAcquireStringA(pdwLen, (LPSTR *)ppvXML, ACQ_DISPLACE));
  841. exit:
  842. return hr;
  843. }
  844. HRESULT HrCreatePatchContactRequest(LPHTTPCONTACTINFO pciInfo, IPropPatchRequest **ppRequest)
  845. {
  846. HRESULT hr = S_OK;
  847. LPSTR *prgsz = (LPSTR*)pciInfo, pszEsc;
  848. DWORD dwIndex, dwSize = ARRAYSIZE(g_rgContactEle);
  849. CPropPatchRequest *pRequest = NULL;
  850. *ppRequest = NULL;
  851. pRequest = new CPropPatchRequest();
  852. if (NULL == pRequest)
  853. {
  854. hr = E_OUTOFMEMORY;
  855. goto exit;
  856. }
  857. // always specify windows-1252 encoding for this release
  858. pRequest->SpecifyWindows1252Encoding(TRUE);
  859. for (dwIndex = 0; dwIndex < dwSize; dwIndex ++)
  860. {
  861. if (g_rgContactEle[dwIndex] != HMELE_UNKNOWN)
  862. {
  863. if (prgsz[dwIndex])
  864. {
  865. // values with content are added. Empty strings are deleted. Null values are ignored.
  866. if (*(prgsz[dwIndex]))
  867. {
  868. pszEsc = _EscapeString(prgsz[dwIndex]);
  869. if (!pszEsc)
  870. goto exit;
  871. hr = pRequest->SetProperty(DAVNAMESPACE_CONTACTS, const_cast<char *>(rgHTTPMailDictionary[g_rgContactEle[dwIndex]].pszName), pszEsc);
  872. SafeMemFree(pszEsc);
  873. if (FAILED(hr))
  874. goto exit;
  875. }
  876. else
  877. {
  878. if (FAILED(hr = pRequest->RemoveProperty(DAVNAMESPACE_CONTACTS, const_cast<char *>(rgHTTPMailDictionary[g_rgContactEle[dwIndex]].pszName))))
  879. goto exit;
  880. }
  881. }
  882. }
  883. }
  884. exit:
  885. if (FAILED(hr))
  886. SafeRelease(pRequest);
  887. else
  888. *ppRequest = pRequest;
  889. return hr;
  890. }
  891. HRESULT HrGenerateSimpleBatchXML(
  892. LPCSTR pszRootName,
  893. LPHTTPTARGETLIST pTargets,
  894. LPVOID *ppvXML,
  895. DWORD *pdwLen)
  896. {
  897. HRESULT hr = S_OK;
  898. CByteStream stream;
  899. DWORD dwIndex;
  900. DWORD dwHrefHeadLen, dwHrefTailLen;
  901. IxpAssert(NULL != pszRootName);
  902. IxpAssert(NULL != pTargets);
  903. IxpAssert(pTargets->cTarget >= 1);
  904. IxpAssert(NULL != pTargets->prgTarget);
  905. IxpAssert(NULL != ppvXML);
  906. IxpAssert(NULL != pdwLen);
  907. dwHrefHeadLen = lstrlen(c_szHrefHead);
  908. dwHrefTailLen = lstrlen(c_szHrefTail);
  909. // write the DAV header
  910. FAIL_EXIT_STREAM_WRITE(stream, c_szXMLHead);
  911. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchHead1);
  912. FAIL_EXIT_STREAM_WRITE(stream, pszRootName);
  913. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchHead2);
  914. FAIL_EXIT_STREAM_WRITE(stream, c_szTargetHead);
  915. // write out the targets
  916. for (dwIndex = 0; dwIndex < pTargets->cTarget; dwIndex++)
  917. {
  918. if (FAILED(hr = stream.Write(c_szHrefHead, dwHrefHeadLen, NULL)))
  919. goto exit;
  920. FAIL_EXIT_STREAM_WRITE(stream, pTargets->prgTarget[dwIndex]);
  921. if (FAILED(hr = stream.Write(c_szHrefTail, dwHrefTailLen, NULL)))
  922. goto exit;
  923. }
  924. FAIL_EXIT_STREAM_WRITE(stream, c_szTargetTail);
  925. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchTail);
  926. FAIL_EXIT_STREAM_WRITE(stream, pszRootName);
  927. FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseElement);
  928. // take ownership of the bytestream
  929. FAIL_EXIT(hr = stream.HrAcquireStringA(pdwLen, (LPSTR *)ppvXML, ACQ_DISPLACE));
  930. exit:
  931. return hr;
  932. }
  933. HRESULT HrGenerateMultiDestBatchXML(
  934. LPCSTR pszRootName,
  935. LPHTTPTARGETLIST pTargets,
  936. LPHTTPTARGETLIST pDestinations,
  937. LPVOID *ppvXML,
  938. DWORD *pdwLen)
  939. {
  940. HRESULT hr = S_OK;
  941. CByteStream stream;
  942. DWORD dwIndex;
  943. IxpAssert(NULL != pszRootName);
  944. IxpAssert(NULL != pTargets);
  945. IxpAssert(NULL != pDestinations);
  946. IxpAssert(NULL != ppvXML);
  947. IxpAssert(NULL != pdwLen);
  948. // source and destination must have same count
  949. if (pTargets->cTarget != pDestinations->cTarget)
  950. return E_INVALIDARG;
  951. *ppvXML = NULL;
  952. *pdwLen = 0;
  953. // write the DAV header
  954. FAIL_EXIT_STREAM_WRITE(stream, c_szXMLHead);
  955. // write the command header
  956. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchHead1);
  957. FAIL_EXIT_STREAM_WRITE(stream, pszRootName);
  958. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchHead2);
  959. // write out the targets
  960. for (dwIndex = 0; dwIndex < pTargets->cTarget; dwIndex++)
  961. {
  962. IxpAssert(NULL != pTargets->prgTarget[dwIndex]);
  963. if (NULL != pTargets->prgTarget[dwIndex])
  964. {
  965. FAIL_EXIT_STREAM_WRITE(stream, c_szTargetHead);
  966. FAIL_EXIT_STREAM_WRITE(stream, c_szHrefHead);
  967. FAIL_EXIT_STREAM_WRITE(stream, pTargets->prgTarget[dwIndex]);
  968. FAIL_EXIT_STREAM_WRITE(stream, c_szHrefTail);
  969. if (NULL != pDestinations->prgTarget[dwIndex])
  970. {
  971. FAIL_EXIT_STREAM_WRITE(stream, c_szDestHead);
  972. FAIL_EXIT_STREAM_WRITE(stream, pDestinations->prgTarget[dwIndex]);
  973. FAIL_EXIT_STREAM_WRITE(stream, c_szDestTail);
  974. }
  975. FAIL_EXIT_STREAM_WRITE(stream, c_szTargetTail);
  976. }
  977. }
  978. FAIL_EXIT_STREAM_WRITE(stream, c_szBatchTail);
  979. FAIL_EXIT_STREAM_WRITE(stream, pszRootName);
  980. FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseElement);
  981. // take ownership of the byte stream
  982. hr = stream.HrAcquireStringA(pdwLen, (LPSTR *)ppvXML, ACQ_DISPLACE);
  983. exit:
  984. return hr;
  985. }
  986. HRESULT HrCopyStringList(LPCSTR *rgszInList, LPCSTR **prgszOutList)
  987. {
  988. DWORD cStrings = 0;
  989. HRESULT hr = S_OK;
  990. LPCSTR pszCur;
  991. DWORD i = 0;
  992. IxpAssert(NULL != rgszInList);
  993. IxpAssert(NULL != prgszOutList);
  994. *prgszOutList = NULL;
  995. // count the strings in the list
  996. while (NULL != rgszInList[i++])
  997. ++cStrings;
  998. // allocate the new list
  999. if (!MemAlloc((void **)prgszOutList, (cStrings + 1) * sizeof(LPCSTR)))
  1000. {
  1001. hr = E_OUTOFMEMORY;
  1002. goto exit;
  1003. }
  1004. // copy the strings over. if an allocation fails,
  1005. // stay in the loop and null out all of the slots
  1006. // that haven't been filled
  1007. for (i = 0; i <= cStrings; i++)
  1008. {
  1009. if (SUCCEEDED(hr) && NULL != rgszInList[i])
  1010. {
  1011. (*prgszOutList)[i] = PszDupA(rgszInList[i]);
  1012. if (NULL == (*prgszOutList)[i])
  1013. hr = E_OUTOFMEMORY;
  1014. }
  1015. else
  1016. (*prgszOutList)[i] = NULL;
  1017. }
  1018. if (FAILED(hr))
  1019. {
  1020. FreeStringList(*prgszOutList);
  1021. *prgszOutList = NULL;
  1022. }
  1023. exit:
  1024. return hr;
  1025. }
  1026. void FreeStringList(LPCSTR *rgszList)
  1027. {
  1028. DWORD i = 0;
  1029. IxpAssert(NULL != rgszList);
  1030. if (rgszList)
  1031. {
  1032. while (NULL != rgszList[i])
  1033. MemFree((void *)rgszList[i++]);
  1034. MemFree(rgszList);
  1035. }
  1036. }
  1037. // --------------------------------------------------------------------------------
  1038. // class CHTTPMailTransport
  1039. // --------------------------------------------------------------------------------
  1040. // --------------------------------------------------------------------------------
  1041. // CHTTPMailTransport::CHTTPMailTransport
  1042. // --------------------------------------------------------------------------------
  1043. CHTTPMailTransport::CHTTPMailTransport(void) :
  1044. m_cRef(1),
  1045. m_fHasServer(FALSE),
  1046. m_fHasRootProps(FALSE),
  1047. m_fTerminating(FALSE),
  1048. m_status(IXP_DISCONNECTED),
  1049. m_hInternet(NULL),
  1050. m_hConnection(NULL),
  1051. m_pszUserAgent(NULL),
  1052. m_pLogFile(NULL),
  1053. m_pCallback(NULL),
  1054. m_pParser(NULL),
  1055. m_hwnd(NULL),
  1056. m_hevPendingCommand(NULL),
  1057. m_opPendingHead(NULL),
  1058. m_opPendingTail(NULL),
  1059. m_pszCurrentHost(NULL),
  1060. m_nCurrentPort(INTERNET_INVALID_PORT_NUMBER)
  1061. {
  1062. DWORD dwTempID;
  1063. HANDLE hThread = NULL;
  1064. InitializeCriticalSection(&m_cs);
  1065. ZeroMemory(&m_rServer, sizeof(INETSERVER));
  1066. ZeroMemory(&m_op, sizeof(HTTPMAILOPERATION));
  1067. ZeroMemory(&m_rootProps, sizeof(ROOTPROPS));
  1068. m_op.rResponse.command = HTTPMAIL_NONE;
  1069. m_hevPendingCommand = CreateEvent(NULL, TRUE, FALSE, NULL);
  1070. // Create the IO thread
  1071. hThread = CreateThread(NULL, 0, IOThreadFuncProxy, (LPVOID)this, 0, &dwTempID);
  1072. // We do not need to manipulate the IO Thread through its handle, so close it
  1073. // This will NOT terminate the thread
  1074. if (NULL != hThread)
  1075. {
  1076. CloseHandle(hThread);
  1077. }
  1078. DllAddRef();
  1079. }
  1080. // --------------------------------------------------------------------------------
  1081. // CHTTPMailTransport::~CHTTPMailTransport
  1082. // --------------------------------------------------------------------------------
  1083. CHTTPMailTransport::~CHTTPMailTransport(void)
  1084. {
  1085. IxpAssert(0 == m_cRef);
  1086. // Shouldn't be pending commands
  1087. IxpAssert(HTTPMAIL_NONE == m_op.rResponse.command);
  1088. IxpAssert(!m_opPendingHead);
  1089. IxpAssert(!m_opPendingTail);
  1090. IxpAssert(m_fTerminating);
  1091. // Destroy the critical sections
  1092. DeleteCriticalSection(&m_cs);
  1093. // Close the window
  1094. if ((NULL != m_hwnd) && (FALSE != IsWindow(m_hwnd)))
  1095. ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
  1096. SafeMemFree(m_pszUserAgent);
  1097. CloseHandle(m_hevPendingCommand);
  1098. SafeMemFree(m_rootProps.pszAdbar);
  1099. SafeMemFree(m_rootProps.pszContacts);
  1100. SafeMemFree(m_rootProps.pszInbox);
  1101. SafeMemFree(m_rootProps.pszOutbox);
  1102. SafeMemFree(m_rootProps.pszSendMsg);
  1103. SafeMemFree(m_rootProps.pszSentItems);
  1104. SafeMemFree(m_rootProps.pszDeletedItems);
  1105. SafeMemFree(m_rootProps.pszDrafts);
  1106. SafeMemFree(m_rootProps.pszMsgFolderRoot);
  1107. SafeMemFree(m_rootProps.pszSig);
  1108. SafeMemFree(m_pszCurrentHost);
  1109. SafeRelease(m_pLogFile);
  1110. SafeRelease(m_pCallback);
  1111. SafeRelease(m_pParser);
  1112. SafeInternetCloseHandle(m_hInternet);
  1113. // BUGBUG: clean up window, thread and event, release buffers, etc
  1114. DllRelease();
  1115. }
  1116. // --------------------------------------------------------------------------------
  1117. // CHTTPMailTransport::HrConnectToHost
  1118. // --------------------------------------------------------------------------------
  1119. HRESULT CHTTPMailTransport::HrConnectToHost(
  1120. LPSTR pszHostName,
  1121. INTERNET_PORT nPort,
  1122. LPSTR pszUserName,
  1123. LPSTR pszPassword)
  1124. {
  1125. IxpAssert(m_hInternet);
  1126. // if a connection exists, determine if it is to the same host/port
  1127. // that the caller is specifying.
  1128. if (NULL != m_hConnection)
  1129. {
  1130. // if we are already connected to the correct host, return immediately
  1131. if (m_nCurrentPort == nPort && m_pszCurrentHost && (lstrcmp(pszHostName, m_pszCurrentHost) == 0))
  1132. return S_OK;
  1133. // if we are connected to the wrong server, close the existing connection
  1134. SafeInternetCloseHandle(m_hConnection);
  1135. SafeMemFree(m_pszCurrentHost);
  1136. m_nCurrentPort = INTERNET_INVALID_PORT_NUMBER;
  1137. }
  1138. // establish a connection to the specified server
  1139. m_hConnection = InternetConnect(
  1140. m_hInternet,
  1141. pszHostName,
  1142. nPort,
  1143. NULL, // user name
  1144. NULL, // password
  1145. INTERNET_SERVICE_HTTP, // service
  1146. 0, // flags
  1147. reinterpret_cast<DWORD_PTR>(this)); // context
  1148. // what can cause this?
  1149. if (NULL == m_hConnection)
  1150. return E_OUTOFMEMORY;
  1151. // save the host name. don't bother checking for failure...we just won't reuse
  1152. // the connection next time through.
  1153. m_pszCurrentHost = PszDupA(pszHostName);
  1154. m_nCurrentPort = nPort;
  1155. return S_OK;
  1156. }
  1157. // --------------------------------------------------------------------------------
  1158. // CHTTPMailTransport::DoLogonPrompt
  1159. // --------------------------------------------------------------------------------
  1160. HRESULT CHTTPMailTransport::DoLogonPrompt(void)
  1161. {
  1162. HRESULT hr = S_OK;
  1163. IHTTPMailCallback *pCallback = NULL;
  1164. EnterCriticalSection(&m_cs);
  1165. if (m_pCallback)
  1166. {
  1167. pCallback = m_pCallback;
  1168. pCallback->AddRef();
  1169. }
  1170. else
  1171. hr = E_FAIL;
  1172. LeaveCriticalSection(&m_cs);
  1173. if (pCallback)
  1174. {
  1175. hr = pCallback->OnLogonPrompt(&m_rServer, this);
  1176. pCallback->Release();
  1177. }
  1178. return hr;
  1179. }
  1180. // --------------------------------------------------------------------------------
  1181. // CHTTPMailTransport::DoGetParentWindow
  1182. // --------------------------------------------------------------------------------
  1183. HRESULT CHTTPMailTransport::DoGetParentWindow(HWND *phwndParent)
  1184. {
  1185. HRESULT hr = S_OK;
  1186. IHTTPMailCallback *pCallback = NULL;
  1187. EnterCriticalSection(&m_cs);
  1188. if (m_pCallback)
  1189. {
  1190. pCallback = m_pCallback;
  1191. pCallback->AddRef();
  1192. }
  1193. else
  1194. hr = E_FAIL;
  1195. LeaveCriticalSection(&m_cs);
  1196. if (pCallback)
  1197. {
  1198. hr = pCallback->GetParentWindow(phwndParent);
  1199. pCallback->Release();
  1200. }
  1201. return hr;
  1202. }
  1203. // --------------------------------------------------------------------------------
  1204. // CHTTPMailTransport::CreateWnd
  1205. // --------------------------------------------------------------------------------
  1206. BOOL CHTTPMailTransport::CreateWnd()
  1207. {
  1208. WNDCLASS wc;
  1209. IxpAssert(!m_hwnd);
  1210. if (m_hwnd)
  1211. return TRUE;
  1212. if (!GetClassInfo(g_hLocRes, s_szHTTPMailWndClass, &wc))
  1213. {
  1214. wc.style = 0;
  1215. wc.lpfnWndProc = CHTTPMailTransport::WndProc;
  1216. wc.cbClsExtra = 0;
  1217. wc.cbWndExtra = 0;
  1218. wc.hInstance = g_hLocRes;
  1219. wc.hIcon = NULL;
  1220. wc.hCursor = NULL;
  1221. wc.hbrBackground = NULL;
  1222. wc.lpszMenuName = NULL;
  1223. wc.lpszClassName = s_szHTTPMailWndClass;
  1224. RegisterClass(&wc);
  1225. }
  1226. m_hwnd = CreateWindowEx(0,
  1227. s_szHTTPMailWndClass,
  1228. s_szHTTPMailWndClass,
  1229. WS_POPUP,
  1230. CW_USEDEFAULT,
  1231. CW_USEDEFAULT,
  1232. CW_USEDEFAULT,
  1233. CW_USEDEFAULT,
  1234. NULL,
  1235. NULL,
  1236. g_hLocRes,
  1237. (LPVOID)this);
  1238. return (NULL != m_hwnd);
  1239. }
  1240. // --------------------------------------------------------------------------------
  1241. // CHTTPMailTransport::DequeueNextOperation
  1242. // --------------------------------------------------------------------------------
  1243. BOOL CHTTPMailTransport::DequeueNextOperation(void)
  1244. {
  1245. if (NULL == m_opPendingHead)
  1246. return FALSE;
  1247. IxpAssert(HTTPMAIL_NONE == m_op.rResponse.command);
  1248. IxpAssert(HTTPMAIL_NONE != m_opPendingHead->command);
  1249. m_op.rResponse.command = m_opPendingHead->command;
  1250. m_op.pfnState = m_opPendingHead->pfnState;
  1251. m_op.cState = m_opPendingHead->cState;
  1252. m_op.pszUrl = m_opPendingHead->pszUrl;
  1253. m_op.pszDestination = m_opPendingHead->pszDestination;
  1254. m_op.pszContentType = m_opPendingHead->pszContentType;
  1255. m_op.pvData = m_opPendingHead->pvData;
  1256. m_op.cbDataLen = m_opPendingHead->cbDataLen;
  1257. m_op.dwContext = m_opPendingHead->dwContext;
  1258. m_op.dwDepth = m_opPendingHead->dwDepth;
  1259. m_op.dwRHFlags = m_opPendingHead->dwRHFlags;
  1260. m_op.dwMIFlags = m_opPendingHead->dwMIFlags;
  1261. m_op.tyProp = m_opPendingHead->tyProp;
  1262. m_op.fBatch = m_opPendingHead->fBatch;
  1263. m_op.rgszAcceptTypes = m_opPendingHead->rgszAcceptTypes;
  1264. m_op.pPropFindRequest = m_opPendingHead->pPropFindRequest;
  1265. m_op.pPropPatchRequest = m_opPendingHead->pPropPatchRequest;
  1266. m_op.pParseFuncs = m_opPendingHead->pParseFuncs;
  1267. m_op.pHeaderStream = m_opPendingHead->pHeaderStream;
  1268. m_op.pBodyStream = m_opPendingHead->pBodyStream;
  1269. m_op.pszFolderTimeStamp = m_opPendingHead->pszFolderTimeStamp;
  1270. m_op.pszRootTimeStamp = m_opPendingHead->pszRootTimeStamp;
  1271. //m_op.pszFolderName = m_opPendingHead->pszFolderName;
  1272. LPHTTPQUEUEDOP pDelete = m_opPendingHead;
  1273. m_opPendingHead = m_opPendingHead->pNext;
  1274. if (NULL == m_opPendingHead)
  1275. m_opPendingTail = NULL;
  1276. MemFree(pDelete);
  1277. return TRUE;
  1278. }
  1279. // --------------------------------------------------------------------------------
  1280. // CHTTPMailTransport::FlushQueue
  1281. // --------------------------------------------------------------------------------
  1282. void CHTTPMailTransport::FlushQueue(void)
  1283. {
  1284. // destroy any commands that are pending.
  1285. // REVIEW: these commands need to notify their callers
  1286. LPHTTPQUEUEDOP pOp = m_opPendingHead;
  1287. LPHTTPQUEUEDOP pNext;
  1288. while (pOp)
  1289. {
  1290. pNext = pOp->pNext;
  1291. SafeMemFree(pOp->pszUrl);
  1292. SafeMemFree(pOp->pszDestination);
  1293. if (pOp->pszContentType)
  1294. MemFree((void *)pOp->pszContentType);
  1295. SafeMemFree(pOp->pvData);
  1296. if (pOp->rgszAcceptTypes)
  1297. FreeStringList(pOp->rgszAcceptTypes);
  1298. SafeRelease(pOp->pPropFindRequest);
  1299. SafeRelease(pOp->pPropPatchRequest);
  1300. MemFree(pOp);
  1301. pOp = pNext;
  1302. }
  1303. m_opPendingHead = m_opPendingTail = NULL;
  1304. }
  1305. // --------------------------------------------------------------------------------
  1306. // CHTTPMailTransport::TerminateIOThread
  1307. // --------------------------------------------------------------------------------
  1308. void CHTTPMailTransport::TerminateIOThread(void)
  1309. {
  1310. EnterCriticalSection(&m_cs);
  1311. // acquire a reference to the transport that will be owned
  1312. // by the io thread. the reference will be release when the
  1313. // io thread exits. this reference is not acquired when the
  1314. // thread is created, because it would prevent the transport
  1315. // from going away.
  1316. AddRef();
  1317. m_fTerminating = TRUE;
  1318. FlushQueue();
  1319. // signal the io thread to wake it.
  1320. SetEvent(m_hevPendingCommand);
  1321. LeaveCriticalSection(&m_cs);
  1322. }
  1323. // --------------------------------------------------------------------------------
  1324. // CHTTPMailTransport::IOThreadFunc
  1325. // --------------------------------------------------------------------------------
  1326. DWORD CALLBACK CHTTPMailTransport::IOThreadFuncProxy(PVOID pv)
  1327. {
  1328. CHTTPMailTransport *pHTTPMail = (CHTTPMailTransport*)pv;
  1329. DWORD dwResult = S_OK;
  1330. IxpAssert(pHTTPMail);
  1331. // Initialize COM
  1332. if(S_OK == (dwResult = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)))
  1333. {
  1334. dwResult = pHTTPMail->IOThreadFunc();
  1335. //Bug #101165 -- MSXML needs notification to clean up per thread data.
  1336. CoUninitialize();
  1337. }
  1338. return dwResult;
  1339. }
  1340. // --------------------------------------------------------------------------------
  1341. // CHTTPMailTransport::IOThreadFunc
  1342. // Called by IOThreadProxy to transition into an object method
  1343. // --------------------------------------------------------------------------------
  1344. DWORD CHTTPMailTransport::IOThreadFunc()
  1345. {
  1346. LPSTR pszVerb = NULL;
  1347. BOOL bQueueEmpty = FALSE;
  1348. // block until a command is pending.
  1349. while (WAIT_OBJECT_0 == WaitForSingleObject(m_hevPendingCommand, INFINITE))
  1350. {
  1351. if (IsTerminating())
  1352. break;
  1353. // Reset the event
  1354. ResetEvent(m_hevPendingCommand);
  1355. // unhook commands from the queue one at a time, and process them until
  1356. // the queue is empty
  1357. while (TRUE)
  1358. {
  1359. // dequeue the next operation
  1360. EnterCriticalSection(&m_cs);
  1361. IxpAssert(HTTPMAIL_NONE == m_op.rResponse.command);
  1362. bQueueEmpty = !DequeueNextOperation();
  1363. // if no commands left, break out of the loop and block
  1364. LeaveCriticalSection(&m_cs);
  1365. if (bQueueEmpty)
  1366. break;
  1367. DoOperation();
  1368. }
  1369. if (IsTerminating())
  1370. break;
  1371. }
  1372. IxpAssert(IsTerminating());
  1373. // TerminateIOThread acquired a reference that gets released here
  1374. Release();
  1375. return S_OK;
  1376. }
  1377. // --------------------------------------------------------------------------------
  1378. // CHTTPMailTransport::WndProc
  1379. // --------------------------------------------------------------------------------
  1380. LRESULT CALLBACK CHTTPMailTransport::WndProc(HWND hwnd,
  1381. UINT msg,
  1382. WPARAM wParam,
  1383. LPARAM lParam)
  1384. {
  1385. CHTTPMailTransport *pThis = (CHTTPMailTransport*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1386. LRESULT lr = 0;
  1387. switch (msg)
  1388. {
  1389. case WM_NCCREATE:
  1390. IxpAssert(!pThis);
  1391. pThis = (CHTTPMailTransport*)((LPCREATESTRUCT)lParam)->lpCreateParams;
  1392. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pThis);
  1393. lr = DefWindowProc(hwnd, msg, wParam, lParam);
  1394. break;
  1395. case SPM_HTTPMAIL_SENDRESPONSE:
  1396. IxpAssert(pThis);
  1397. pThis->InvokeResponseCallback();
  1398. break;
  1399. case SPM_HTTPMAIL_LOGONPROMPT:
  1400. IxpAssert(pThis);
  1401. lr = pThis->DoLogonPrompt();
  1402. break;
  1403. case SPM_HTTPMAIL_GETPARENTWINDOW:
  1404. IxpAssert(pThis);
  1405. lr = pThis->DoGetParentWindow((HWND *)wParam);
  1406. break;
  1407. default:
  1408. lr = DefWindowProc(hwnd, msg, wParam, lParam);
  1409. break;
  1410. }
  1411. return lr;
  1412. }
  1413. // --------------------------------------------------------------------------------
  1414. // CHTTPMailTransport::Reset
  1415. // --------------------------------------------------------------------------------
  1416. void CHTTPMailTransport::Reset(void)
  1417. {
  1418. // REVIEW: this is incomplete. Should we be aborting the current command?
  1419. EnterCriticalSection(&m_cs);
  1420. SafeRelease(m_pLogFile);
  1421. SafeInternetCloseHandle(m_hConnection);
  1422. SafeInternetCloseHandle(m_hInternet);
  1423. SafeMemFree(m_pszUserAgent);
  1424. SafeRelease(m_pCallback);
  1425. m_status = IXP_DISCONNECTED;
  1426. m_fHasServer = FALSE;
  1427. ZeroMemory(&m_rServer, sizeof(INETSERVER));
  1428. LeaveCriticalSection(&m_cs);
  1429. }
  1430. // --------------------------------------------------------------------------------
  1431. // CHTTPMailTransport::QueryInterface
  1432. // --------------------------------------------------------------------------------
  1433. STDMETHODIMP CHTTPMailTransport::QueryInterface(REFIID riid, LPVOID *ppv)
  1434. {
  1435. // Locals
  1436. HRESULT hr = S_OK;
  1437. // Validate params
  1438. if (NULL == ppv)
  1439. {
  1440. hr = TrapError(E_INVALIDARG);
  1441. goto exit;
  1442. }
  1443. // Initialize params
  1444. *ppv = NULL;
  1445. // IID_IUnknown
  1446. if (IID_IUnknown == riid)
  1447. *ppv = ((IUnknown *)(IHTTPMailTransport *)this);
  1448. // IID_IInternetTransport
  1449. else if (IID_IInternetTransport == riid)
  1450. *ppv = (IInternetTransport *)this;
  1451. // IID_IHTTPMailTransport
  1452. else if (IID_IHTTPMailTransport == riid)
  1453. *ppv = (IHTTPMailTransport *)this;
  1454. // IID_IXMLNodeFactory
  1455. else if (IID_IXMLNodeFactory == riid)
  1456. *ppv = (IXMLNodeFactory *)this;
  1457. else if (IID_IHTTPMailTransport2 == riid)
  1458. *ppv = (IHTTPMailTransport2 *)this;
  1459. // if not NULL, acquire a reference and return
  1460. if (NULL != *ppv)
  1461. {
  1462. ((LPUNKNOWN)*ppv)->AddRef();
  1463. goto exit;
  1464. }
  1465. hr = TrapError(E_NOINTERFACE);
  1466. exit:
  1467. // Done
  1468. return hr;
  1469. }
  1470. // --------------------------------------------------------------------------------
  1471. // CHTTPMailTransport::AddRef
  1472. // --------------------------------------------------------------------------------
  1473. STDMETHODIMP_(ULONG) CHTTPMailTransport::AddRef(void)
  1474. {
  1475. return ++m_cRef;
  1476. }
  1477. // --------------------------------------------------------------------------------
  1478. // CHTTPMailTransport::Release
  1479. // --------------------------------------------------------------------------------
  1480. STDMETHODIMP_(ULONG) CHTTPMailTransport::Release(void)
  1481. {
  1482. if (0 != --m_cRef)
  1483. return m_cRef;
  1484. // our refcount dropped to zero, and we aren't terminating,
  1485. // begin terminating
  1486. if (!IsTerminating())
  1487. {
  1488. TerminateIOThread();
  1489. return 1;
  1490. }
  1491. // if we were terminating, and our refCount dropped to zero,
  1492. // then the iothread has been unwound and we can safely exit.
  1493. delete this;
  1494. return 0;
  1495. }
  1496. // ----------------------------------------------------------------------------
  1497. // IInternetTransport methods
  1498. // ----------------------------------------------------------------------------
  1499. // --------------------------------------------------------------------------------
  1500. // CHTTPMailTransport::Connect
  1501. // --------------------------------------------------------------------------------
  1502. STDMETHODIMP CHTTPMailTransport::Connect(LPINETSERVER pInetServer,
  1503. boolean fAuthenticate,
  1504. boolean fCommandLogging)
  1505. {
  1506. HRESULT hr = S_OK;
  1507. if (NULL == pInetServer || FIsEmptyA(pInetServer->szServerName))
  1508. return TrapError(E_INVALIDARG);
  1509. // Thread safety
  1510. EnterCriticalSection(&m_cs);
  1511. // not init
  1512. if (NULL == m_hInternet || NULL == m_pCallback)
  1513. {
  1514. hr = TrapError(IXP_E_NOT_INIT);
  1515. goto exit;
  1516. }
  1517. FAIL_CREATEWND;
  1518. // busy
  1519. if (IXP_DISCONNECTED != m_status || m_fHasServer)
  1520. {
  1521. hr = TrapError(IXP_E_ALREADY_CONNECTED);
  1522. goto exit;
  1523. }
  1524. // copy the server struct
  1525. CopyMemory(&m_rServer, pInetServer, sizeof(INETSERVER));
  1526. m_fHasServer = TRUE;
  1527. m_fHasRootProps = FALSE;
  1528. exit:
  1529. // ThreadSafety
  1530. LeaveCriticalSection(&m_cs);
  1531. return hr;
  1532. }
  1533. // --------------------------------------------------------------------------------
  1534. // CHTTPMailTransport::DropConnection
  1535. // --------------------------------------------------------------------------------
  1536. STDMETHODIMP CHTTPMailTransport::DropConnection(void)
  1537. {
  1538. // this function is called to stop any current and pending i/o
  1539. // Locals
  1540. HRESULT hr = S_OK;
  1541. BOOL fSendResponse;
  1542. EnterCriticalSection(&m_cs);
  1543. // flush any pending i/o from the queue
  1544. FlushQueue();
  1545. // if a command is being processed, mark it aborted and
  1546. // send a response if necessary. stay in the critical
  1547. // section to prevent the io thread from sending any
  1548. // notifications at the same time.
  1549. if (m_op.rResponse.command != HTTPMAIL_NONE)
  1550. {
  1551. m_op.fAborted = TRUE;
  1552. m_op.rResponse.fDone = TRUE;
  1553. }
  1554. Disconnect();
  1555. LeaveCriticalSection(&m_cs);
  1556. return hr;
  1557. }
  1558. // --------------------------------------------------------------------------------
  1559. // CHTTPMailTransport::Disconnect
  1560. // --------------------------------------------------------------------------------
  1561. STDMETHODIMP CHTTPMailTransport::Disconnect(void)
  1562. {
  1563. // Locals
  1564. HRESULT hr = S_OK;
  1565. // Thread safety
  1566. EnterCriticalSection(&m_cs);
  1567. if (NULL == m_hConnection)
  1568. {
  1569. hr = TrapError(IXP_E_NOT_INIT);
  1570. goto exit;
  1571. }
  1572. // Disconnecting
  1573. if (m_pCallback)
  1574. m_pCallback->OnStatus(IXP_DISCONNECTING, this);
  1575. SafeInternetCloseHandle(m_hConnection);
  1576. m_status = IXP_DISCONNECTED;
  1577. ZeroMemory(&m_rServer, sizeof(INETSERVER));
  1578. if (m_pCallback)
  1579. m_pCallback->OnStatus(IXP_DISCONNECTED, this);
  1580. // Close the window
  1581. if ((NULL != m_hwnd) && (FALSE != IsWindow(m_hwnd)))
  1582. ::SendMessage(m_hwnd, WM_CLOSE, 0, 0);
  1583. m_hwnd = NULL;
  1584. m_fHasServer = FALSE;
  1585. exit:
  1586. // Thread safety
  1587. LeaveCriticalSection(&m_cs);
  1588. return hr;
  1589. }
  1590. // --------------------------------------------------------------------------------
  1591. // CHTTPMailTransport::IsState
  1592. // --------------------------------------------------------------------------------
  1593. STDMETHODIMP CHTTPMailTransport::IsState(IXPISSTATE isstate)
  1594. {
  1595. // Locals
  1596. HRESULT hr = S_OK;
  1597. // Thread safety
  1598. EnterCriticalSection(&m_cs);
  1599. switch(isstate)
  1600. {
  1601. // are we connected?
  1602. case IXP_IS_CONNECTED:
  1603. hr = (NULL == m_hConnection) ? S_FALSE : S_OK;
  1604. break;
  1605. // are we busy?
  1606. case IXP_IS_BUSY:
  1607. hr = (HTTPMAIL_NONE != m_op.rResponse.command) ? S_OK : S_FALSE;
  1608. break;
  1609. // are we ready
  1610. case IXP_IS_READY:
  1611. hr = (HTTPMAIL_NONE == m_op.rResponse.command) ? S_OK : S_FALSE;
  1612. break;
  1613. case IXP_IS_AUTHENTICATED:
  1614. // REVIEW
  1615. hr = S_OK;
  1616. break;
  1617. default:
  1618. IxpAssert(FALSE);
  1619. break;
  1620. }
  1621. // Thread safety
  1622. LeaveCriticalSection(&m_cs);
  1623. return hr;
  1624. }
  1625. // --------------------------------------------------------------------------------
  1626. // CHTTPMailTransport::GetServerInfo
  1627. // --------------------------------------------------------------------------------
  1628. STDMETHODIMP CHTTPMailTransport::GetServerInfo(LPINETSERVER pInetServer)
  1629. {
  1630. // check params
  1631. if (NULL == pInetServer)
  1632. return TrapError(E_INVALIDARG);
  1633. // Thread safety
  1634. EnterCriticalSection(&m_cs);
  1635. // Copy server info
  1636. CopyMemory(pInetServer, &m_rServer, sizeof(INETSERVER));
  1637. // Thread safety
  1638. LeaveCriticalSection(&m_cs);
  1639. // Done
  1640. return S_OK;
  1641. }
  1642. // --------------------------------------------------------------------------------
  1643. // CHTTPMailTransport::GetIXPType
  1644. // --------------------------------------------------------------------------------
  1645. STDMETHODIMP_(IXPTYPE) CHTTPMailTransport::GetIXPType(void)
  1646. {
  1647. return IXP_HTTPMail;
  1648. }
  1649. // --------------------------------------------------------------------------------
  1650. // CHTTPMailTransport::InetServerFromAccount
  1651. // --------------------------------------------------------------------------------
  1652. STDMETHODIMP CHTTPMailTransport::InetServerFromAccount(IImnAccount *pAccount, LPINETSERVER pInetServer)
  1653. {
  1654. HRESULT hr = S_OK;
  1655. DWORD fAlwaysPromptPassword = FALSE;
  1656. // check params
  1657. if (NULL == pAccount || NULL == pInetServer)
  1658. return TrapError(E_INVALIDARG);
  1659. // ZeroInit
  1660. ZeroMemory(pInetServer, sizeof(INETSERVER));
  1661. // Get the account name
  1662. if (FAILED(hr = pAccount->GetPropSz(AP_ACCOUNT_NAME, pInetServer->szAccount, ARRAYSIZE(pInetServer->szAccount))))
  1663. {
  1664. hr = TrapError(IXP_E_INVALID_ACCOUNT);
  1665. goto exit;
  1666. }
  1667. // Get the RAS connectoid
  1668. if (FAILED(pAccount->GetPropSz(AP_RAS_CONNECTOID, pInetServer->szConnectoid, ARRAYSIZE(pInetServer->szConnectoid))))
  1669. *pInetServer->szConnectoid = '\0';
  1670. // Connection Type
  1671. Assert(sizeof(pInetServer->rasconntype) == sizeof(DWORD));
  1672. if (FAILED(pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, (DWORD *)&pInetServer->rasconntype)))
  1673. pInetServer->rasconntype = RAS_CONNECT_LAN;
  1674. // Get Server Name
  1675. hr = pAccount->GetPropSz(AP_HTTPMAIL_SERVER, pInetServer->szServerName, sizeof(pInetServer->szServerName));
  1676. if (FAILED(hr))
  1677. {
  1678. hr = TrapError(IXP_E_INVALID_ACCOUNT);
  1679. goto exit;
  1680. }
  1681. // Password
  1682. if (FAILED(pAccount->GetPropDw(AP_HTTPMAIL_PROMPT_PASSWORD, &fAlwaysPromptPassword)) || FALSE == fAlwaysPromptPassword)
  1683. pAccount->GetPropSz(AP_HTTPMAIL_PASSWORD, pInetServer->szPassword, sizeof(pInetServer->szPassword));
  1684. if (fAlwaysPromptPassword)
  1685. pInetServer->dwFlags |= ISF_ALWAYSPROMPTFORPASSWORD;
  1686. // Sicily
  1687. Assert(sizeof(pInetServer->fTrySicily) == sizeof(DWORD));
  1688. pAccount->GetPropDw(AP_HTTPMAIL_USE_SICILY, (DWORD *)&pInetServer->fTrySicily);
  1689. // User Name
  1690. pAccount->GetPropSz(AP_HTTPMAIL_USERNAME, pInetServer->szUserName, sizeof(pInetServer->szUserName));
  1691. exit:
  1692. return hr;
  1693. }
  1694. // --------------------------------------------------------------------------------
  1695. // CHTTPMailTransport::HandsOffCallback
  1696. // --------------------------------------------------------------------------------
  1697. STDMETHODIMP CHTTPMailTransport::HandsOffCallback(void)
  1698. {
  1699. // Locals
  1700. HRESULT hr = S_OK;
  1701. // Thread safety
  1702. EnterCriticalSection(&m_cs);
  1703. // No current callback
  1704. if (NULL == m_pCallback)
  1705. {
  1706. hr = TrapError(S_FALSE);
  1707. goto exit;
  1708. }
  1709. // Release it
  1710. SafeRelease(m_pCallback);
  1711. exit:
  1712. // Thread safety
  1713. LeaveCriticalSection(&m_cs);
  1714. // Done
  1715. return hr;
  1716. }
  1717. // --------------------------------------------------------------------------------
  1718. // CHTTPMailTransport::GetStatus
  1719. // --------------------------------------------------------------------------------
  1720. STDMETHODIMP CHTTPMailTransport::GetStatus(IXPSTATUS *pCurrentStatus)
  1721. {
  1722. if (NULL == pCurrentStatus)
  1723. return TrapError(E_INVALIDARG);
  1724. *pCurrentStatus = m_status;
  1725. return S_OK;
  1726. }
  1727. // ----------------------------------------------------------------------------
  1728. // IHTTPMailTransport methods
  1729. // ----------------------------------------------------------------------------
  1730. // ----------------------------------------------------------------------------
  1731. // CHTTPMailTransport::GetProperty
  1732. // ----------------------------------------------------------------------------
  1733. STDMETHODIMP CHTTPMailTransport::GetProperty(
  1734. HTTPMAILPROPTYPE type,
  1735. LPSTR *ppszProp)
  1736. {
  1737. HRESULT hr = S_OK;
  1738. if (type <= HTTPMAIL_PROP_INVALID || type >= HTTPMAIL_PROP_LAST)
  1739. return E_INVALIDARG;
  1740. if (ppszProp)
  1741. *ppszProp = NULL;
  1742. if (!m_fHasRootProps || NULL == ppszProp)
  1743. {
  1744. IF_FAILEXIT(hr = QueueGetPropOperation(type));
  1745. }
  1746. switch (type)
  1747. {
  1748. case HTTPMAIL_PROP_ADBAR:
  1749. *ppszProp = PszDupA(m_rootProps.pszAdbar);
  1750. break;
  1751. case HTTPMAIL_PROP_CONTACTS:
  1752. *ppszProp = PszDupA(m_rootProps.pszContacts);
  1753. break;
  1754. case HTTPMAIL_PROP_INBOX:
  1755. *ppszProp = PszDupA(m_rootProps.pszInbox);
  1756. break;
  1757. case HTTPMAIL_PROP_OUTBOX:
  1758. *ppszProp = PszDupA(m_rootProps.pszOutbox);
  1759. break;
  1760. case HTTPMAIL_PROP_SENDMSG:
  1761. *ppszProp = PszDupA(m_rootProps.pszSendMsg);
  1762. break;
  1763. case HTTPMAIL_PROP_SENTITEMS:
  1764. *ppszProp = PszDupA(m_rootProps.pszSentItems);
  1765. break;
  1766. case HTTPMAIL_PROP_DELETEDITEMS:
  1767. *ppszProp = PszDupA(m_rootProps.pszDeletedItems);
  1768. break;
  1769. case HTTPMAIL_PROP_DRAFTS:
  1770. *ppszProp = PszDupA(m_rootProps.pszDrafts);
  1771. break;
  1772. case HTTPMAIL_PROP_MSGFOLDERROOT:
  1773. *ppszProp = PszDupA(m_rootProps.pszMsgFolderRoot);
  1774. break;
  1775. case HTTPMAIL_PROP_SIG:
  1776. *ppszProp = PszDupA(m_rootProps.pszSig);
  1777. break;
  1778. default:
  1779. hr = TrapError(E_INVALIDARG);
  1780. break;
  1781. }
  1782. if (SUCCEEDED(hr) && !*ppszProp)
  1783. hr = IXP_E_HTTP_ROOT_PROP_NOT_FOUND;
  1784. exit:
  1785. return hr;
  1786. }
  1787. HRESULT CHTTPMailTransport::QueueGetPropOperation(HTTPMAILPROPTYPE type)
  1788. {
  1789. HRESULT hr = S_OK;
  1790. LPHTTPQUEUEDOP pOp;
  1791. if (!m_fHasServer || NULL == m_rServer.szServerName)
  1792. {
  1793. hr = E_FAIL;
  1794. goto exit;
  1795. }
  1796. FAIL_CREATEWND;
  1797. // queue the getprop operation
  1798. if (FAILED(hr = AllocQueuedOperation(m_rServer.szServerName, NULL, 0, &pOp)))
  1799. goto exit;
  1800. pOp->command = HTTPMAIL_GETPROP;
  1801. pOp->tyProp = type;
  1802. pOp->pfnState = c_rgpfnRootProps;
  1803. pOp->cState = ARRAYSIZE(c_rgpfnRootProps);
  1804. pOp->pParseFuncs = c_rgpfnRootPropsParse;
  1805. pOp->dwRHFlags = (RH_XMLCONTENTTYPE | RH_BRIEF);
  1806. QueueOperation(pOp);
  1807. hr = E_PENDING;
  1808. exit:
  1809. return hr;
  1810. }
  1811. // ----------------------------------------------------------------------------
  1812. // CHTTPMailTransport::GetPropertyDw
  1813. // ----------------------------------------------------------------------------
  1814. STDMETHODIMP CHTTPMailTransport::GetPropertyDw(
  1815. HTTPMAILPROPTYPE type,
  1816. LPDWORD lpdwProp)
  1817. {
  1818. HRESULT hr = S_OK;
  1819. if (type <= HTTPMAIL_PROP_INVALID || type >= HTTPMAIL_PROP_LAST)
  1820. IF_FAILEXIT(hr = E_INVALIDARG);
  1821. if (lpdwProp)
  1822. *lpdwProp = 0;
  1823. if (!m_fHasRootProps || NULL == lpdwProp)
  1824. {
  1825. IF_FAILEXIT(hr = QueueGetPropOperation(type));
  1826. }
  1827. switch (type)
  1828. {
  1829. case HTTPMAIL_PROP_MAXPOLLINGINTERVAL:
  1830. *lpdwProp = m_rootProps.dwMaxPollingInterval;
  1831. break;
  1832. default:
  1833. hr = TrapError(E_INVALIDARG);
  1834. break;
  1835. }
  1836. exit:
  1837. return hr;
  1838. }
  1839. // ----------------------------------------------------------------------------
  1840. // CHTTPMailTransport::CommandGET
  1841. // ----------------------------------------------------------------------------
  1842. STDMETHODIMP CHTTPMailTransport::CommandGET(LPCSTR pszUrl,
  1843. LPCSTR *rgszAcceptTypes,
  1844. BOOL fTranslate,
  1845. DWORD dwContext)
  1846. {
  1847. HRESULT hr = S_OK;
  1848. LPHTTPQUEUEDOP pOp = NULL;
  1849. LPCSTR *rgszAcceptTypesCopy = NULL;
  1850. if (NULL == pszUrl)
  1851. return TrapError(E_INVALIDARG);
  1852. FAIL_CREATEWND;
  1853. if (NULL != rgszAcceptTypes)
  1854. {
  1855. hr = HrCopyStringList(rgszAcceptTypes, &rgszAcceptTypesCopy);
  1856. if (FAILED(hr))
  1857. goto exit;
  1858. }
  1859. if (FAILED(hr = AllocQueuedOperation(pszUrl, NULL, 0, &pOp)))
  1860. goto exit;
  1861. pOp->command = HTTPMAIL_GET;
  1862. pOp->dwContext = dwContext;
  1863. pOp->pfnState = c_rgpfGet;
  1864. pOp->cState = ARRAYSIZE(c_rgpfGet);
  1865. pOp->rgszAcceptTypes = rgszAcceptTypesCopy;
  1866. if (!fTranslate)
  1867. pOp->dwRHFlags = RH_TRANSLATEFALSE;
  1868. rgszAcceptTypesCopy = NULL;
  1869. QueueOperation(pOp);
  1870. exit:
  1871. if (NULL != rgszAcceptTypesCopy)
  1872. FreeStringList(rgszAcceptTypesCopy);
  1873. return hr;
  1874. }
  1875. // ----------------------------------------------------------------------------
  1876. // CHTTPMailTransport::CommandPUT
  1877. // ----------------------------------------------------------------------------
  1878. STDMETHODIMP CHTTPMailTransport::CommandPUT(
  1879. LPCSTR pszPath,
  1880. LPVOID lpvData,
  1881. ULONG cbSize,
  1882. DWORD dwContext)
  1883. {
  1884. HRESULT hr = S_OK;
  1885. LPHTTPQUEUEDOP pOp = NULL;
  1886. LPCSTR pszLocalContentType = NULL;
  1887. LPVOID lpvCopy = NULL;
  1888. if (NULL == pszPath || NULL == lpvData || 0 == cbSize)
  1889. return TrapError(E_INVALIDARG);
  1890. FAIL_CREATEWND;
  1891. if (!MemAlloc(&lpvCopy, cbSize))
  1892. {
  1893. hr = TrapError(E_OUTOFMEMORY);
  1894. goto exit;
  1895. }
  1896. CopyMemory(lpvCopy, lpvData, cbSize);
  1897. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  1898. goto exit;
  1899. pOp->command = HTTPMAIL_PUT;
  1900. pOp->dwContext = dwContext;
  1901. pOp->pfnState = c_rgpfnPut;
  1902. pOp->cState = ARRAYSIZE(c_rgpfnPut);
  1903. pOp->pvData = lpvCopy;
  1904. lpvCopy = NULL;
  1905. pOp->cbDataLen = cbSize;
  1906. QueueOperation(pOp);
  1907. exit:
  1908. SafeMemFree(lpvCopy);
  1909. return hr;
  1910. }
  1911. // ----------------------------------------------------------------------------
  1912. // CHTTPMailTransport::CommandPOST
  1913. // ----------------------------------------------------------------------------
  1914. STDMETHODIMP CHTTPMailTransport::CommandPOST(
  1915. LPCSTR pszPath,
  1916. IStream *pStream,
  1917. LPCSTR pszContentType,
  1918. DWORD dwContext)
  1919. {
  1920. HRESULT hr = S_OK;
  1921. LPHTTPQUEUEDOP pOp = NULL;
  1922. LPCSTR pszLocalContentType = NULL;
  1923. if (NULL == pszPath || NULL == pStream)
  1924. return TrapError(E_INVALIDARG);
  1925. FAIL_CREATEWND;
  1926. if (pszContentType)
  1927. {
  1928. pszLocalContentType = PszDupA(pszContentType);
  1929. if (NULL == pszLocalContentType)
  1930. {
  1931. hr = TrapError(E_OUTOFMEMORY);
  1932. goto exit;
  1933. }
  1934. }
  1935. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  1936. goto exit;
  1937. pOp->command = HTTPMAIL_POST;
  1938. pOp->dwContext = dwContext;
  1939. pOp->pfnState = c_rgpfnPost;
  1940. pOp->cState = ARRAYSIZE(c_rgpfnPost);
  1941. pOp->pBodyStream = pStream;
  1942. pOp->pBodyStream->AddRef();
  1943. pOp->pszContentType = pszLocalContentType;
  1944. pszLocalContentType = NULL;
  1945. QueueOperation(pOp);
  1946. exit:
  1947. if (pszLocalContentType)
  1948. MemFree((void *)pszLocalContentType);
  1949. return hr;
  1950. }
  1951. // ----------------------------------------------------------------------------
  1952. // CHTTPMailTransport::CommandDELETE
  1953. // ----------------------------------------------------------------------------
  1954. STDMETHODIMP CHTTPMailTransport::CommandDELETE(
  1955. LPCSTR pszPath,
  1956. DWORD dwContext)
  1957. {
  1958. HRESULT hr = S_OK;
  1959. LPHTTPQUEUEDOP pOp = NULL;
  1960. if (NULL == pszPath)
  1961. return TrapError(E_INVALIDARG);
  1962. FAIL_CREATEWND;
  1963. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  1964. goto exit;
  1965. pOp->command = HTTPMAIL_DELETE;
  1966. pOp->dwContext = dwContext;
  1967. pOp->pfnState = c_rgpfDelete;
  1968. pOp->cState = ARRAYSIZE(c_rgpfDelete);
  1969. QueueOperation(pOp);
  1970. exit:
  1971. return hr;
  1972. }
  1973. // ----------------------------------------------------------------------------
  1974. // CHTTPMailTransport::CommandBDELETE
  1975. // ----------------------------------------------------------------------------
  1976. STDMETHODIMP CHTTPMailTransport::CommandBDELETE(
  1977. LPCSTR pszPath,
  1978. LPHTTPTARGETLIST pBatchTargets,
  1979. DWORD dwContext)
  1980. {
  1981. HRESULT hr = S_OK;
  1982. LPHTTPQUEUEDOP pOp = NULL;
  1983. LPVOID pvXML = NULL;
  1984. DWORD dwXMLLen = 0;
  1985. if (NULL == pszPath || NULL == pBatchTargets)
  1986. return TrapError(E_INVALIDARG);
  1987. FAIL_CREATEWND;
  1988. if (FAILED(hr = HrGenerateSimpleBatchXML(c_szDelete, pBatchTargets, &pvXML, &dwXMLLen)))
  1989. goto exit;
  1990. if (FAILED(hr = AllocQueuedOperation(pszPath, pvXML, dwXMLLen, &pOp, TRUE)))
  1991. goto exit;
  1992. pvXML = NULL;
  1993. pOp->command = HTTPMAIL_BDELETE;
  1994. pOp->dwContext = dwContext;
  1995. pOp->pfnState = c_rgpfDelete;
  1996. pOp->cState = ARRAYSIZE(c_rgpfDelete);
  1997. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  1998. QueueOperation(pOp);
  1999. exit:
  2000. SafeMemFree(pvXML);
  2001. return hr;
  2002. }
  2003. // ----------------------------------------------------------------------------
  2004. // CHTTPMailTransport::CommandPROPFIND
  2005. // ----------------------------------------------------------------------------
  2006. STDMETHODIMP CHTTPMailTransport::CommandPROPFIND(
  2007. LPCSTR pszPath,
  2008. IPropFindRequest *pRequest,
  2009. DWORD dwDepth,
  2010. DWORD dwContext)
  2011. {
  2012. if (NULL == pszPath || NULL == pRequest)
  2013. return TrapError(E_INVALIDARG);
  2014. return E_NOTIMPL;
  2015. }
  2016. // --------------------------------------------------------------------------------
  2017. // CHTTPMailTransport::CommandPROPPATCH
  2018. // --------------------------------------------------------------------------------
  2019. STDMETHODIMP CHTTPMailTransport::CommandPROPPATCH(
  2020. LPCSTR pszUrl,
  2021. IPropPatchRequest *pRequest,
  2022. DWORD dwContext)
  2023. {
  2024. if (NULL == pszUrl || NULL == pRequest)
  2025. return TrapError(E_INVALIDARG);
  2026. HRESULT hr = S_OK;
  2027. LPHTTPQUEUEDOP pOp = NULL;
  2028. FAIL_CREATEWND;
  2029. if (FAILED(hr = AllocQueuedOperation(pszUrl, NULL, 0, &pOp)))
  2030. goto exit;
  2031. pOp->command = HTTPMAIL_PROPPATCH;
  2032. pOp->dwContext = dwContext;
  2033. pOp->pfnState = c_rgpfnPropPatch;
  2034. pOp->cState = ARRAYSIZE(c_rgpfnPropPatch);
  2035. pOp->pPropPatchRequest = pRequest;
  2036. pRequest->AddRef();
  2037. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  2038. QueueOperation(pOp);
  2039. exit:
  2040. return hr;
  2041. }
  2042. // --------------------------------------------------------------------------------
  2043. // CHTTPMailTransport::CommandMKCOL
  2044. // --------------------------------------------------------------------------------
  2045. HRESULT CHTTPMailTransport::CommandMKCOL(LPCSTR pszUrl, DWORD dwContext)
  2046. {
  2047. HRESULT hr = S_OK;
  2048. LPHTTPQUEUEDOP pOp = NULL;
  2049. if (NULL == pszUrl)
  2050. return TrapError(E_INVALIDARG);
  2051. FAIL_CREATEWND;
  2052. if (FAILED(hr = AllocQueuedOperation(pszUrl, NULL, 0, &pOp)))
  2053. goto exit;
  2054. pOp->command = HTTPMAIL_MKCOL;
  2055. pOp->dwContext = dwContext;
  2056. pOp->pfnState = c_rgpfnMkCol;
  2057. pOp->cState = ARRAYSIZE(c_rgpfnMkCol);
  2058. QueueOperation(pOp);
  2059. exit:
  2060. return hr;
  2061. }
  2062. // --------------------------------------------------------------------------------
  2063. // CHTTPMailTransport::CommandCOPY
  2064. // --------------------------------------------------------------------------------
  2065. STDMETHODIMP CHTTPMailTransport::CommandCOPY(
  2066. LPCSTR pszPath,
  2067. LPCSTR pszDestination,
  2068. BOOL fAllowRename,
  2069. DWORD dwContext)
  2070. {
  2071. HRESULT hr = S_OK;
  2072. LPHTTPQUEUEDOP pOp;
  2073. LPSTR pszDupDestination = NULL;
  2074. if (NULL == pszPath || NULL == pszDestination)
  2075. return TrapError(E_INVALIDARG);
  2076. FAIL_CREATEWND;
  2077. pszDupDestination = PszDupA(pszDestination);
  2078. if (NULL == pszDupDestination)
  2079. return TrapError(E_OUTOFMEMORY);
  2080. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2081. goto exit;
  2082. pOp->command = HTTPMAIL_COPY;
  2083. pOp->dwContext = dwContext;
  2084. pOp->pfnState = c_rgpfnCopy;
  2085. pOp->cState = ARRAYSIZE(c_rgpfnCopy);
  2086. pOp->pszDestination = pszDupDestination;
  2087. pszDupDestination = NULL;
  2088. if (fAllowRename)
  2089. pOp->dwRHFlags = RH_ALLOWRENAME;
  2090. QueueOperation(pOp);
  2091. exit:
  2092. SafeMemFree(pszDupDestination);
  2093. return hr;
  2094. }
  2095. // --------------------------------------------------------------------------------
  2096. // CHTTPMailTransport::CommandBCOPY
  2097. // --------------------------------------------------------------------------------
  2098. STDMETHODIMP CHTTPMailTransport::CommandBCOPY(
  2099. LPCSTR pszSourceCollection,
  2100. LPHTTPTARGETLIST pTargets,
  2101. LPCSTR pszDestCollection,
  2102. LPHTTPTARGETLIST pDestinations,
  2103. BOOL fAllowRename,
  2104. DWORD dwContext)
  2105. {
  2106. HRESULT hr = S_OK;
  2107. LPHTTPQUEUEDOP pOp = NULL;
  2108. LPVOID pvXML = NULL;
  2109. DWORD dwXMLLen = 0;
  2110. LPSTR pszDupDestination = NULL;
  2111. if (NULL == pszSourceCollection || NULL == pTargets || NULL == pszDestCollection)
  2112. return TrapError(E_INVALIDARG);
  2113. FAIL_CREATEWND;
  2114. pszDupDestination = PszDupA(pszDestCollection);
  2115. if (NULL == pszDupDestination)
  2116. {
  2117. hr = TrapError(E_OUTOFMEMORY);
  2118. goto exit;
  2119. }
  2120. if (NULL == pDestinations)
  2121. hr = HrGenerateSimpleBatchXML(c_szCopy, pTargets, &pvXML, &dwXMLLen);
  2122. else
  2123. hr = HrGenerateMultiDestBatchXML(c_szCopy, pTargets, pDestinations, &pvXML, &dwXMLLen);
  2124. if (FAILED(hr))
  2125. goto exit;
  2126. if (FAILED(hr = AllocQueuedOperation(pszSourceCollection, pvXML, dwXMLLen, &pOp, TRUE)))
  2127. goto exit;
  2128. pvXML = NULL;
  2129. pOp->command = HTTPMAIL_BCOPY;
  2130. pOp->dwContext = dwContext;
  2131. pOp->pfnState = c_rgpfnBMove;
  2132. pOp->cState = ARRAYSIZE(c_rgpfnBMove);
  2133. pOp->pParseFuncs = c_rgpfnBCopyMoveParse;
  2134. pOp->pszDestination = pszDupDestination;
  2135. pszDupDestination = NULL;
  2136. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  2137. if (fAllowRename)
  2138. pOp->dwRHFlags |= RH_ALLOWRENAME;
  2139. QueueOperation(pOp);
  2140. exit:
  2141. SafeMemFree(pvXML);
  2142. SafeMemFree(pszDupDestination);
  2143. return hr;
  2144. }
  2145. // --------------------------------------------------------------------------------
  2146. // CHTTPMailTransport::CommandMOVE
  2147. // --------------------------------------------------------------------------------
  2148. STDMETHODIMP CHTTPMailTransport::CommandMOVE(
  2149. LPCSTR pszPath,
  2150. LPCSTR pszDestination,
  2151. BOOL fAllowRename,
  2152. DWORD dwContext)
  2153. {
  2154. HRESULT hr = S_OK;
  2155. LPHTTPQUEUEDOP pOp;
  2156. LPSTR pszDupDestination = NULL;
  2157. if (NULL == pszPath || NULL == pszDestination)
  2158. return TrapError(E_INVALIDARG);
  2159. FAIL_CREATEWND;
  2160. pszDupDestination = PszDupA(pszDestination);
  2161. if (NULL == pszDupDestination)
  2162. return TrapError(E_OUTOFMEMORY);
  2163. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2164. goto exit;
  2165. pOp->command = HTTPMAIL_MOVE;
  2166. pOp->dwContext = dwContext;
  2167. pOp->pfnState = c_rgpfnMove;
  2168. pOp->cState = ARRAYSIZE(c_rgpfnMove);
  2169. pOp->pszDestination = pszDupDestination;
  2170. pszDupDestination = NULL;
  2171. if (fAllowRename)
  2172. pOp->dwRHFlags = RH_ALLOWRENAME;
  2173. QueueOperation(pOp);
  2174. exit:
  2175. SafeMemFree(pszDupDestination);
  2176. return hr;
  2177. }
  2178. // --------------------------------------------------------------------------------
  2179. // CHTTPMailTransport::CommandBMOVE
  2180. // --------------------------------------------------------------------------------
  2181. STDMETHODIMP CHTTPMailTransport::CommandBMOVE(
  2182. LPCSTR pszSourceCollection,
  2183. LPHTTPTARGETLIST pTargets,
  2184. LPCSTR pszDestCollection,
  2185. LPHTTPTARGETLIST pDestinations,
  2186. BOOL fAllowRename,
  2187. DWORD dwContext)
  2188. {
  2189. HRESULT hr = S_OK;
  2190. LPHTTPQUEUEDOP pOp = NULL;
  2191. LPVOID pvXML = NULL;
  2192. DWORD dwXMLLen = 0;
  2193. LPSTR pszDupDestination = NULL;
  2194. if (NULL == pszSourceCollection || NULL == pTargets || NULL == pszDestCollection)
  2195. return TrapError(E_INVALIDARG);
  2196. FAIL_CREATEWND;
  2197. pszDupDestination = PszDupA(pszDestCollection);
  2198. if (NULL == pszDupDestination)
  2199. {
  2200. hr = TrapError(E_OUTOFMEMORY);
  2201. goto exit;
  2202. }
  2203. if (NULL == pDestinations)
  2204. hr = HrGenerateSimpleBatchXML(c_szMove, pTargets, &pvXML, &dwXMLLen);
  2205. else
  2206. hr = HrGenerateMultiDestBatchXML(c_szMove, pTargets, pDestinations, &pvXML, &dwXMLLen);
  2207. if (FAILED(hr))
  2208. goto exit;
  2209. if (FAILED(hr = AllocQueuedOperation(pszSourceCollection, pvXML, dwXMLLen, &pOp, TRUE)))
  2210. goto exit;
  2211. pvXML = NULL;
  2212. pOp->command = HTTPMAIL_BMOVE;
  2213. pOp->dwContext = dwContext;
  2214. pOp->pfnState = c_rgpfnBMove;
  2215. pOp->cState = ARRAYSIZE(c_rgpfnBMove);
  2216. pOp->pParseFuncs = c_rgpfnBCopyMoveParse;
  2217. pOp->pszDestination = pszDupDestination;
  2218. pszDupDestination = NULL;
  2219. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  2220. if (fAllowRename)
  2221. pOp->dwRHFlags |= RH_ALLOWRENAME;
  2222. QueueOperation(pOp);
  2223. exit:
  2224. SafeMemFree(pvXML);
  2225. SafeMemFree(pszDupDestination);
  2226. return hr;
  2227. }
  2228. // --------------------------------------------------------------------------------
  2229. // CHTTPMailTransport::MemberInfo
  2230. // --------------------------------------------------------------------------------
  2231. STDMETHODIMP CHTTPMailTransport::MemberInfo(
  2232. LPCSTR pszPath,
  2233. MEMBERINFOFLAGS flags,
  2234. DWORD dwDepth,
  2235. BOOL fIncludeRoot,
  2236. DWORD dwContext)
  2237. {
  2238. HRESULT hr = S_OK;
  2239. LPHTTPQUEUEDOP pOp = NULL;
  2240. if (NULL == pszPath)
  2241. return TrapError(E_INVALIDARG);
  2242. FAIL_CREATEWND;
  2243. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2244. goto exit;
  2245. pOp->command = HTTPMAIL_MEMBERINFO;
  2246. pOp->dwMIFlags = flags;
  2247. pOp->dwDepth = dwDepth;
  2248. pOp->dwContext = dwContext;
  2249. pOp->pfnState = c_rgpfnMemberInfo;
  2250. pOp->cState = ARRAYSIZE(c_rgpfnMemberInfo);
  2251. pOp->pParseFuncs = c_rgpfnMemberInfoParse;
  2252. pOp->dwRHFlags = (RH_BRIEF | RH_XMLCONTENTTYPE);
  2253. if (!fIncludeRoot)
  2254. pOp->dwRHFlags |= RH_NOROOT;
  2255. QueueOperation(pOp);
  2256. exit:
  2257. return hr;
  2258. }
  2259. // --------------------------------------------------------------------------------
  2260. // CHTTPMailTransport::FindFolders
  2261. // --------------------------------------------------------------------------------
  2262. HRESULT CHTTPMailTransport::FindFolders(LPCSTR pszPath, DWORD dwContext)
  2263. {
  2264. return E_NOTIMPL;
  2265. }
  2266. // --------------------------------------------------------------------------------
  2267. // CHTTPMailTransport::MarkRead
  2268. // --------------------------------------------------------------------------------
  2269. HRESULT CHTTPMailTransport::MarkRead(
  2270. LPCSTR pszPath,
  2271. LPHTTPTARGETLIST pTargets,
  2272. BOOL fMarkRead,
  2273. DWORD dwContext)
  2274. {
  2275. HRESULT hr = S_OK;
  2276. LPHTTPQUEUEDOP pOp = NULL;
  2277. CPropPatchRequest *pRequest = NULL;
  2278. LPSTR pszXML = NULL;
  2279. if (NULL == pszPath)
  2280. return TrapError(E_INVALIDARG);
  2281. FAIL_CREATEWND;
  2282. pRequest = new CPropPatchRequest();
  2283. if (NULL == pRequest)
  2284. {
  2285. hr = TrapError(E_OUTOFMEMORY);
  2286. goto exit;
  2287. }
  2288. if (fMarkRead)
  2289. FAIL_EXIT(hr = pRequest->SetProperty(DAVNAMESPACE_HTTPMAIL, "read", "1"));
  2290. else
  2291. FAIL_EXIT(hr = pRequest->SetProperty(DAVNAMESPACE_HTTPMAIL, "read", "0"));
  2292. FAIL_EXIT(hr = pRequest->GenerateXML(pTargets, &pszXML));
  2293. FAIL_EXIT(hr = AllocQueuedOperation(pszPath, pszXML, lstrlen(pszXML), &pOp, TRUE));
  2294. pszXML = NULL;
  2295. pOp->command = HTTPMAIL_MARKREAD;
  2296. pOp->dwContext = dwContext;
  2297. pOp->pfnState = c_rgpfnMarkRead;
  2298. pOp->cState = ARRAYSIZE(c_rgpfnMarkRead);
  2299. pOp->pParseFuncs = c_rgpfnMemberErrorParse;
  2300. pOp->dwRHFlags = (RH_BRIEF | RH_XMLCONTENTTYPE);
  2301. if (pTargets && pTargets->cTarget > 0)
  2302. pOp->fBatch = TRUE;
  2303. QueueOperation(pOp);
  2304. exit:
  2305. SafeRelease(pRequest);
  2306. SafeMemFree(pszXML);
  2307. return hr;
  2308. }
  2309. // --------------------------------------------------------------------------------
  2310. // CHTTPMailTransport::SendMessage
  2311. // --------------------------------------------------------------------------------
  2312. HRESULT CHTTPMailTransport::SendMessage(LPCSTR pszPath,
  2313. LPCSTR pszFrom,
  2314. LPHTTPTARGETLIST pTargets,
  2315. BOOL fSaveInSent,
  2316. IStream *pMessageStream,
  2317. DWORD dwContext)
  2318. {
  2319. HRESULT hr = S_OK;
  2320. LPHTTPQUEUEDOP pOp = NULL;
  2321. IStream *pRfc821Stream = NULL;
  2322. if (NULL == pszPath ||
  2323. NULL == pszFrom ||
  2324. NULL == pTargets || pTargets->cTarget < 1 ||
  2325. NULL == pMessageStream)
  2326. return E_INVALIDARG;
  2327. FAIL_CREATEWND;
  2328. // build the rfc821 stream that will precede the mime message
  2329. FAIL_EXIT(hr = _HrGenerateRfc821Stream(pszFrom, pTargets, &pRfc821Stream));
  2330. FAIL_EXIT(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp));
  2331. pOp->command = HTTPMAIL_SENDMESSAGE;
  2332. pOp->dwContext = dwContext;
  2333. pOp->pfnState = c_rgpfnSendMessage;
  2334. pOp->cState = ARRAYSIZE(c_rgpfnSendMessage);
  2335. pOp->pHeaderStream = pRfc821Stream;
  2336. pRfc821Stream = NULL;
  2337. pOp->pBodyStream = pMessageStream;
  2338. if (NULL != pOp->pBodyStream)
  2339. pOp->pBodyStream->AddRef();
  2340. pOp->dwRHFlags = (RH_TRANSLATETRUE | RH_SMTPMESSAGECONTENTTYPE);
  2341. pOp->dwRHFlags |= (fSaveInSent ? RH_SAVEINSENTTRUE : RH_SAVEINSENTFALSE);
  2342. QueueOperation(pOp);
  2343. exit:
  2344. SafeRelease(pRfc821Stream);
  2345. return hr;
  2346. }
  2347. // --------------------------------------------------------------------------------
  2348. // CHTTPMailTransport::ListContacts
  2349. // --------------------------------------------------------------------------------
  2350. HRESULT CHTTPMailTransport::ListContacts(LPCSTR pszPath, DWORD dwContext)
  2351. {
  2352. HRESULT hr = S_OK;
  2353. LPHTTPQUEUEDOP pOp = NULL;
  2354. if (NULL == pszPath)
  2355. return TrapError(E_INVALIDARG);
  2356. FAIL_CREATEWND;
  2357. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2358. goto exit;
  2359. pOp->command = HTTPMAIL_LISTCONTACTS;
  2360. pOp->dwContext = dwContext;
  2361. pOp->pfnState = c_rgpfnListContacts;
  2362. pOp->cState = ARRAYSIZE(c_rgpfnListContacts);
  2363. pOp->pParseFuncs = c_rgpfnListContactsParse;
  2364. pOp->dwDepth = 1;
  2365. pOp->dwRHFlags = (RH_NOROOT | RH_XMLCONTENTTYPE);
  2366. QueueOperation(pOp);
  2367. exit:
  2368. return hr;
  2369. }
  2370. // --------------------------------------------------------------------------------
  2371. // CHTTPMailTransport::ListContactInfos
  2372. // --------------------------------------------------------------------------------
  2373. HRESULT CHTTPMailTransport::ListContactInfos(LPCSTR pszCollectionPath, DWORD dwContext)
  2374. {
  2375. HRESULT hr = S_OK;
  2376. LPHTTPQUEUEDOP pOp = NULL;
  2377. if (NULL == pszCollectionPath)
  2378. return TrapError(E_INVALIDARG);
  2379. FAIL_CREATEWND;
  2380. if (FAILED(hr = AllocQueuedOperation(pszCollectionPath, NULL, 0, &pOp)))
  2381. goto exit;
  2382. pOp->command = HTTPMAIL_CONTACTINFO;
  2383. pOp->dwContext = dwContext;
  2384. pOp->pfnState = c_rgpfnContactInfo;
  2385. pOp->cState = ARRAYSIZE(c_rgpfnContactInfo);
  2386. pOp->pParseFuncs = c_rgpfnContactInfoParse;
  2387. pOp->dwDepth = 1;
  2388. pOp->dwRHFlags = (RH_NOROOT | RH_XMLCONTENTTYPE);
  2389. QueueOperation(pOp);
  2390. exit:
  2391. return hr;
  2392. }
  2393. // --------------------------------------------------------------------------------
  2394. // CHTTPMailTransport::ContactInfo
  2395. // --------------------------------------------------------------------------------
  2396. HRESULT CHTTPMailTransport::ContactInfo(LPCSTR pszPath, DWORD dwContext)
  2397. {
  2398. HRESULT hr = S_OK;
  2399. LPHTTPQUEUEDOP pOp = NULL;
  2400. if (NULL == pszPath)
  2401. return TrapError(E_INVALIDARG);
  2402. FAIL_CREATEWND;
  2403. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2404. goto exit;
  2405. pOp->command = HTTPMAIL_CONTACTINFO;
  2406. pOp->dwContext = dwContext;
  2407. pOp->pfnState = c_rgpfnContactInfo;
  2408. pOp->cState = ARRAYSIZE(c_rgpfnContactInfo);
  2409. pOp->pParseFuncs = c_rgpfnContactInfoParse;
  2410. pOp->dwDepth = 0;
  2411. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  2412. QueueOperation(pOp);
  2413. exit:
  2414. return hr;
  2415. }
  2416. // --------------------------------------------------------------------------------
  2417. // CHTTPMailTransport::PostContact
  2418. // --------------------------------------------------------------------------------
  2419. HRESULT CHTTPMailTransport::PostContact(LPCSTR pszPath,
  2420. LPHTTPCONTACTINFO pciInfo,
  2421. DWORD dwContext)
  2422. {
  2423. HRESULT hr = S_OK;
  2424. LPHTTPQUEUEDOP pOp = NULL;
  2425. LPVOID pvXML = NULL;
  2426. DWORD cb;
  2427. if (NULL == pciInfo)
  2428. return TrapError(E_INVALIDARG);
  2429. FAIL_CREATEWND;
  2430. if (FAILED(hr = HrGeneratePostContactXML(pciInfo, &pvXML, &cb)))
  2431. goto exit;
  2432. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2433. goto exit;
  2434. pOp->pvData = pvXML;
  2435. pOp->cbDataLen = cb;
  2436. pvXML = NULL;
  2437. pOp->command = HTTPMAIL_POSTCONTACT;
  2438. pOp->dwContext = dwContext;
  2439. pOp->pfnState = c_rgpfnPostContact;
  2440. pOp->cState = ARRAYSIZE(c_rgpfnPostContact);
  2441. pOp->dwDepth = 0;
  2442. pOp->dwRHFlags = (RH_XMLCONTENTTYPE | RH_TRANSLATEFALSE);
  2443. QueueOperation(pOp);
  2444. exit:
  2445. SafeMemFree(pvXML);
  2446. return hr;
  2447. }
  2448. // --------------------------------------------------------------------------------
  2449. // CHTTPMailTransport::PatchContact
  2450. // --------------------------------------------------------------------------------
  2451. HRESULT CHTTPMailTransport::PatchContact(LPCSTR pszPath,
  2452. LPHTTPCONTACTINFO pciInfo,
  2453. DWORD dwContext)
  2454. {
  2455. HRESULT hr = S_OK;
  2456. LPHTTPQUEUEDOP pOp = NULL;
  2457. IPropPatchRequest *pRequest = NULL;
  2458. if (NULL == pciInfo)
  2459. return TrapError(E_INVALIDARG);
  2460. FAIL_CREATEWND;
  2461. if (FAILED(hr = HrCreatePatchContactRequest(pciInfo, &pRequest)))
  2462. goto exit;
  2463. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  2464. goto exit;
  2465. pOp->command = HTTPMAIL_PATCHCONTACT;
  2466. pOp->dwContext = dwContext;
  2467. pOp->pfnState = c_rgpfnPatchContact;
  2468. pOp->cState = ARRAYSIZE(c_rgpfnPatchContact);
  2469. pOp->pPropPatchRequest = pRequest;
  2470. pRequest = NULL;
  2471. pOp->dwRHFlags = RH_XMLCONTENTTYPE;
  2472. QueueOperation(pOp);
  2473. exit:
  2474. SafeRelease(pRequest);
  2475. return hr;
  2476. }
  2477. // --------------------------------------------------------------------------------
  2478. // INodeFactory Methods
  2479. // --------------------------------------------------------------------------------
  2480. // --------------------------------------------------------------------------------
  2481. // CHTTPMailTransport::NotifyEvent
  2482. // --------------------------------------------------------------------------------
  2483. STDMETHODIMP CHTTPMailTransport::NotifyEvent(IXMLNodeSource* pSource,
  2484. XML_NODEFACTORY_EVENT iEvt)
  2485. {
  2486. return S_OK;
  2487. }
  2488. // --------------------------------------------------------------------------------
  2489. // CHTTPMailTransport::BeginChildren
  2490. // --------------------------------------------------------------------------------
  2491. STDMETHODIMP CHTTPMailTransport::BeginChildren(IXMLNodeSource* pSource, XML_NODE_INFO *pNodeInfo)
  2492. {
  2493. if (m_op.dwStackDepth <= ELE_STACK_CAPACITY)
  2494. m_op.rgEleStack[m_op.dwStackDepth - 1].fBeganChildren = TRUE;
  2495. return S_OK;
  2496. }
  2497. // --------------------------------------------------------------------------------
  2498. // CHTTPMailTransport::EndChildren
  2499. // --------------------------------------------------------------------------------
  2500. STDMETHODIMP CHTTPMailTransport::EndChildren(
  2501. IXMLNodeSource* pSource,
  2502. BOOL fEmpty,
  2503. XML_NODE_INFO *pNodeInfo)
  2504. {
  2505. HRESULT hr = S_OK;
  2506. IxpAssert(HTTPMAIL_NONE != m_op.rResponse.command);
  2507. IxpAssert(NULL != m_op.pParseFuncs);
  2508. if (HTTPMAIL_NONE == m_op.rResponse.command || NULL == m_op.pParseFuncs)
  2509. {
  2510. hr = E_FAIL;
  2511. goto exit;
  2512. }
  2513. if (XML_ELEMENT == pNodeInfo->dwType)
  2514. hr = (this->*(m_op.pParseFuncs->pfnEndChildren))();
  2515. exit:
  2516. return hr;
  2517. }
  2518. // --------------------------------------------------------------------------------
  2519. // CHTTPMailTransport::Error
  2520. // --------------------------------------------------------------------------------
  2521. STDMETHODIMP CHTTPMailTransport::Error(IXMLNodeSource* pSource,
  2522. HRESULT hrErrorCode,
  2523. USHORT cNumRecs,
  2524. XML_NODE_INFO** apNodeInfo)
  2525. {
  2526. BSTR bstr = NULL;
  2527. if (NULL == m_op.rResponse.rIxpResult.pszResponse)
  2528. {
  2529. if (FAILED(pSource->GetErrorInfo(&bstr)))
  2530. goto exit;
  2531. HrBSTRToLPSZ(CP_ACP, bstr, &m_op.rResponse.rIxpResult.pszResponse);
  2532. }
  2533. exit:
  2534. if (NULL != bstr)
  2535. SysFreeString(bstr);
  2536. return S_OK;
  2537. }
  2538. // --------------------------------------------------------------------------------
  2539. // CHTTPMailTransport::CreateNode
  2540. // --------------------------------------------------------------------------------
  2541. STDMETHODIMP CHTTPMailTransport::CreateNode(
  2542. IXMLNodeSource* pSource,
  2543. PVOID pNodeParent,
  2544. USHORT cNumRecs,
  2545. XML_NODE_INFO** apNodeInfo)
  2546. {
  2547. HRESULT hr = S_OK;
  2548. LPPCDATABUFFER pTextBuffer = NULL;
  2549. CXMLNamespace *pBaseNamespace = m_op.pTopNamespace;
  2550. XML_NODE_INFO *pNodeInfo;
  2551. IxpAssert(HTTPMAIL_NONE != m_op.rResponse.command);
  2552. IxpAssert(NULL != m_op.pParseFuncs);
  2553. if (HTTPMAIL_NONE == m_op.rResponse.command || NULL == m_op.pParseFuncs)
  2554. {
  2555. hr = E_FAIL;
  2556. goto exit;
  2557. }
  2558. if (NULL == apNodeInfo || 0 == cNumRecs)
  2559. {
  2560. hr = E_INVALIDARG;
  2561. goto exit;
  2562. }
  2563. pNodeInfo = apNodeInfo[0];
  2564. switch (pNodeInfo->dwType)
  2565. {
  2566. case XML_ELEMENT:
  2567. if (cNumRecs > 1 && FAILED(hr = PushNamespaces(apNodeInfo, cNumRecs)))
  2568. goto exit;
  2569. hr = (this->*(m_op.pParseFuncs->pfnCreateElement))(pBaseNamespace, pNodeInfo->pwcText, pNodeInfo->ulLen, pNodeInfo->ulNsPrefixLen, pNodeInfo->fTerminal);
  2570. break;
  2571. case XML_PCDATA:
  2572. // we only parse element content...we don't care about attributes
  2573. if (InValidElementChildren())
  2574. {
  2575. // get the buffer
  2576. pTextBuffer = m_op.rgEleStack[m_op.dwStackDepth - 1].pTextBuffer;
  2577. // request one if we don't already have one
  2578. if (NULL == pTextBuffer)
  2579. {
  2580. if (FAILED(hr = _GetTextBuffer(&pTextBuffer)))
  2581. goto exit;
  2582. m_op.rgEleStack[m_op.dwStackDepth - 1].pTextBuffer = pTextBuffer;
  2583. }
  2584. hr = _AppendTextToBuffer(pTextBuffer, pNodeInfo->pwcText, pNodeInfo->ulLen);
  2585. goto exit;
  2586. }
  2587. break;
  2588. default:
  2589. break;
  2590. }
  2591. exit:
  2592. return hr;
  2593. }
  2594. // --------------------------------------------------------------------------------
  2595. // CHTTPMailTransport::_HrThunkConnectionError
  2596. // --------------------------------------------------------------------------------
  2597. HRESULT CHTTPMailTransport::_HrThunkConnectionError(void)
  2598. {
  2599. return _HrThunkConnectionError(m_op.dwHttpStatus);
  2600. }
  2601. // --------------------------------------------------------------------------------
  2602. // CHTTPMailTransport::_HrThunkConnectionError
  2603. // --------------------------------------------------------------------------------
  2604. HRESULT CHTTPMailTransport::_HrThunkConnectionError(DWORD dwStatus)
  2605. {
  2606. IxpAssert(NULL == m_op.rResponse.rIxpResult.pszResponse);
  2607. IxpAssert(NULL == m_op.rResponse.rIxpResult.pszProblem);
  2608. if (m_pLogFile && !m_op.fLoggedResponse)
  2609. _LogResponse(NULL, 0);
  2610. m_op.rResponse.rIxpResult.hrResult = HttpErrorToIxpResult(dwStatus);
  2611. _GetRequestHeader(&m_op.rResponse.rIxpResult.pszResponse, HTTP_QUERY_STATUS_TEXT);
  2612. m_op.rResponse.rIxpResult.dwSocketError = GetLastError();
  2613. return _HrThunkResponse(TRUE);
  2614. }
  2615. // --------------------------------------------------------------------------------
  2616. // CHTTPMailTransport::_HrThunkResponse
  2617. // --------------------------------------------------------------------------------
  2618. HRESULT CHTTPMailTransport::_HrThunkResponse(BOOL fDone)
  2619. {
  2620. HRESULT hr = S_OK;
  2621. BOOL fSendResponse;
  2622. // Thread safety
  2623. EnterCriticalSection(&m_cs);
  2624. IxpAssert(HTTPMAIL_NONE != m_op.rResponse.command);
  2625. if (m_op.rResponse.fDone)
  2626. {
  2627. fSendResponse = FALSE;
  2628. }
  2629. else
  2630. {
  2631. fSendResponse = TRUE;
  2632. if (!fDone && WasAborted())
  2633. {
  2634. m_op.rResponse.rIxpResult.hrResult = IXP_E_USER_CANCEL;
  2635. m_op.rResponse.fDone = TRUE;
  2636. }
  2637. else
  2638. m_op.rResponse.fDone = fDone;
  2639. }
  2640. LeaveCriticalSection(&m_cs);
  2641. if (fSendResponse)
  2642. hr = (HRESULT) ::SendMessage(m_hwnd, SPM_HTTPMAIL_SENDRESPONSE, 0, NULL);
  2643. return hr;
  2644. }
  2645. // --------------------------------------------------------------------------------
  2646. // CHTTPMailTransport::InvokeResponseCallback
  2647. // --------------------------------------------------------------------------------
  2648. HRESULT CHTTPMailTransport::InvokeResponseCallback(void)
  2649. {
  2650. HRESULT hr = S_OK;
  2651. IHTTPMailCallback *pCallback = NULL;
  2652. EnterCriticalSection(&m_cs);
  2653. if (m_pCallback)
  2654. {
  2655. pCallback = m_pCallback;
  2656. pCallback->AddRef();
  2657. }
  2658. LeaveCriticalSection(&m_cs);
  2659. if (pCallback)
  2660. {
  2661. hr = pCallback->OnResponse(&m_op.rResponse);
  2662. pCallback->Release();
  2663. }
  2664. return hr;
  2665. }
  2666. // --------------------------------------------------------------------------------
  2667. // CHTTPMailTransport::InitNew
  2668. // --------------------------------------------------------------------------------
  2669. STDMETHODIMP CHTTPMailTransport::InitNew(
  2670. LPCSTR pszUserAgent,
  2671. LPCSTR pszLogFilePath,
  2672. IHTTPMailCallback *pCallback)
  2673. {
  2674. HRESULT hr = S_OK;
  2675. if (NULL == pszUserAgent || NULL == pCallback)
  2676. return TrapError(E_INVALIDARG);
  2677. IxpAssert(NULL == m_hInternet);
  2678. // Thread Safety
  2679. EnterCriticalSection(&m_cs);
  2680. if (IXP_DISCONNECTED != m_status)
  2681. {
  2682. hr = TrapError(IXP_E_ALREADY_CONNECTED);
  2683. goto exit;
  2684. }
  2685. Reset();
  2686. m_pszUserAgent = PszDupA(pszUserAgent);
  2687. if (NULL == m_pszUserAgent)
  2688. {
  2689. hr = TrapError(E_OUTOFMEMORY);
  2690. goto exit;
  2691. }
  2692. // open log file
  2693. if (pszLogFilePath)
  2694. CreateLogFile(g_hInst, pszLogFilePath, "HTTPMAIL", DONT_TRUNCATE, &m_pLogFile,
  2695. FILE_SHARE_READ | FILE_SHARE_WRITE);
  2696. m_pCallback = pCallback;
  2697. m_pCallback->AddRef();
  2698. m_hInternet = InternetOpen(m_pszUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
  2699. if (NULL == m_hInternet)
  2700. {
  2701. hr = TrapError(IXP_E_SOCKET_INIT_ERROR);
  2702. goto exit;
  2703. }
  2704. // Install the callback ptr for the internet handle and all of its derived handles
  2705. //InternetSetStatusCallbackA(m_hInternet, StatusCallbackProxy);
  2706. exit:
  2707. LeaveCriticalSection(&m_cs);
  2708. return hr;
  2709. }
  2710. // --------------------------------------------------------------------------------
  2711. // CHTTPMailTransport::OnStatusCallback
  2712. // --------------------------------------------------------------------------------
  2713. void CHTTPMailTransport::OnStatusCallback(
  2714. HINTERNET hInternet,
  2715. DWORD dwInternetStatus,
  2716. LPVOID pvStatusInformation,
  2717. DWORD dwStatusInformationLength)
  2718. {
  2719. #if 0
  2720. // Locals
  2721. IXPSTATUS ixps;
  2722. EnterCriticalSection(&m_cs);
  2723. // if the status message is one of the defined IXPSTATUS messages,
  2724. // notify the callback.
  2725. if ((NULL != m_pCallback) && TranslateWinInetMsg(dwInternetStatus, &ixps))
  2726. m_pCallback->OnStatus(ixps, (IHTTPMailTransport *)this);
  2727. // for now, we just handle the request_complete message
  2728. if (INTERNET_STATUS_REQUEST_COMPLETE == dwInternetStatus)
  2729. HrCommandCompleted();
  2730. LeaveCriticalSection(&m_cs);
  2731. #endif
  2732. }
  2733. // ----------------------------------------------------------------------------
  2734. // CHTTPMailTransport::AllocQueuedOperation
  2735. // ----------------------------------------------------------------------------
  2736. HRESULT CHTTPMailTransport::AllocQueuedOperation(
  2737. LPCSTR pszUrl,
  2738. LPVOID pvData,
  2739. ULONG cbDataLen,
  2740. LPHTTPQUEUEDOP *ppOp,
  2741. BOOL fAdoptData)
  2742. {
  2743. HRESULT hr = S_OK;
  2744. LPHTTPQUEUEDOP pTempOp = NULL;
  2745. if (!MemAlloc((void **)&pTempOp , sizeof(HTTPQUEUEDOP)))
  2746. {
  2747. hr = E_OUTOFMEMORY;
  2748. goto exit;
  2749. }
  2750. ZeroMemory(pTempOp, sizeof(HTTPQUEUEDOP));
  2751. if (NULL != pszUrl)
  2752. {
  2753. pTempOp->pszUrl = PszDupA(pszUrl);
  2754. if (NULL == pTempOp->pszUrl)
  2755. {
  2756. hr = E_OUTOFMEMORY;
  2757. goto exit;
  2758. }
  2759. }
  2760. // can't have a length if data ptr is null
  2761. IxpAssert(!pvData || cbDataLen);
  2762. if (pvData)
  2763. {
  2764. if (!fAdoptData)
  2765. {
  2766. if (!MemAlloc((LPVOID*)&pTempOp->pvData, cbDataLen + 1))
  2767. {
  2768. hr = E_OUTOFMEMORY;
  2769. goto exit;
  2770. }
  2771. CopyMemory(pTempOp->pvData, pvData, cbDataLen);
  2772. ((char *)pTempOp->pvData)[cbDataLen] = '\0';
  2773. }
  2774. else
  2775. pTempOp->pvData = pvData;
  2776. pTempOp->cbDataLen = cbDataLen;
  2777. }
  2778. *ppOp = pTempOp;
  2779. pTempOp = NULL;
  2780. exit:
  2781. if (pTempOp)
  2782. {
  2783. SafeMemFree(pTempOp->pszUrl);
  2784. if (!fAdoptData)
  2785. SafeMemFree(pTempOp->pvData);
  2786. MemFree(pTempOp);
  2787. }
  2788. return hr;
  2789. }
  2790. // ----------------------------------------------------------------------------
  2791. // CHTTPMailTransport::QueueOperation
  2792. // ----------------------------------------------------------------------------
  2793. void CHTTPMailTransport::QueueOperation(LPHTTPQUEUEDOP pOp)
  2794. {
  2795. // Thread safety
  2796. EnterCriticalSection(&m_cs);
  2797. if (m_opPendingTail)
  2798. m_opPendingTail->pNext = pOp;
  2799. else
  2800. {
  2801. // if there is no tail, there shouldn't be a head
  2802. IxpAssert(!m_opPendingHead);
  2803. m_opPendingHead = m_opPendingTail = pOp;
  2804. }
  2805. // signal the io thread
  2806. SetEvent(m_hevPendingCommand);
  2807. // Thread Safety
  2808. LeaveCriticalSection(&m_cs);
  2809. }
  2810. // --------------------------------------------------------------------------------
  2811. // CHTTPMailTransport::StatusCallbackProxy
  2812. // --------------------------------------------------------------------------------
  2813. void CHTTPMailTransport::StatusCallbackProxy(
  2814. HINTERNET hInternet,
  2815. DWORD dwContext,
  2816. DWORD dwInternetStatus,
  2817. LPVOID pvStatusInformation,
  2818. DWORD dwStatusInformationLength)
  2819. {
  2820. // Locals
  2821. CHTTPMailTransport *pHTTPMail = reinterpret_cast<CHTTPMailTransport *>(IntToPtr(dwContext));
  2822. IxpAssert(NULL != pHTTPMail);
  2823. if (NULL != pHTTPMail)
  2824. pHTTPMail->OnStatusCallback(hInternet, dwInternetStatus, pvStatusInformation, dwStatusInformationLength);
  2825. }
  2826. // --------------------------------------------------------------------------------
  2827. // CHTTPMailTransport::DoOperation
  2828. // --------------------------------------------------------------------------------
  2829. void CHTTPMailTransport::DoOperation(void)
  2830. {
  2831. HRESULT hr = S_OK;
  2832. while (m_op.iState < m_op.cState)
  2833. {
  2834. hr = (this->*(m_op.pfnState[m_op.iState]))();
  2835. if (FAILED(hr))
  2836. break;
  2837. m_op.iState++;
  2838. }
  2839. if (!m_op.rResponse.fDone && FAILED(hr))
  2840. {
  2841. m_op.rResponse.rIxpResult.hrResult = hr;
  2842. _HrThunkResponse(TRUE);
  2843. }
  2844. FreeOperation();
  2845. }
  2846. // --------------------------------------------------------------------------------
  2847. // CHTTPMailTransport::FreeOperation
  2848. // --------------------------------------------------------------------------------
  2849. void CHTTPMailTransport::FreeOperation(void)
  2850. {
  2851. // Thread Safety
  2852. EnterCriticalSection(&m_cs);
  2853. SafeMemFree(m_op.pszUrl);
  2854. SafeMemFree(m_op.pszDestination);
  2855. if (m_op.pszContentType)
  2856. {
  2857. MemFree((void *)m_op.pszContentType);
  2858. m_op.pszContentType = NULL;
  2859. }
  2860. SafeMemFree(m_op.pvData);
  2861. SafeInternetCloseHandle(m_op.hRequest);
  2862. SafeRelease(m_op.pPropFindRequest);
  2863. SafeRelease(m_op.pPropPatchRequest);
  2864. if (NULL != m_op.rgszAcceptTypes)
  2865. FreeStringList(m_op.rgszAcceptTypes);
  2866. SafeRelease(m_op.pHeaderStream);
  2867. SafeRelease(m_op.pBodyStream);
  2868. if (m_op.pTextBuffer)
  2869. _FreeTextBuffer(m_op.pTextBuffer);
  2870. // Free the response
  2871. SafeMemFree(m_op.rResponse.rIxpResult.pszResponse);
  2872. SafeMemFree(m_op.rResponse.rIxpResult.pszProblem);
  2873. PopNamespaces(NULL);
  2874. // in the case of an error, the element stack can
  2875. // contain text buffers that need to be freed
  2876. for (DWORD i = 0; i < m_op.dwStackDepth; ++i)
  2877. {
  2878. if (NULL != m_op.rgEleStack[i].pTextBuffer)
  2879. _FreeTextBuffer(m_op.rgEleStack[i].pTextBuffer);
  2880. }
  2881. SafeMemFree(m_op.rResponse.rIxpResult.pszResponse);
  2882. switch (m_op.rResponse.command)
  2883. {
  2884. case HTTPMAIL_GET:
  2885. SafeMemFree(m_op.rResponse.rGetInfo.pvBody);
  2886. SafeMemFree(m_op.rResponse.rGetInfo.pszContentType);
  2887. break;
  2888. case HTTPMAIL_POST:
  2889. case HTTPMAIL_SENDMESSAGE:
  2890. SafeMemFree(m_op.rResponse.rPostInfo.pszLocation);
  2891. break;
  2892. case HTTPMAIL_COPY:
  2893. case HTTPMAIL_MOVE:
  2894. case HTTPMAIL_MKCOL:
  2895. SafeMemFree(m_op.rResponse.rCopyMoveInfo.pszLocation);
  2896. break;
  2897. case HTTPMAIL_BCOPY:
  2898. case HTTPMAIL_BMOVE:
  2899. SafeMemFree(m_op.rResponse.rBCopyMoveList.prgBCopyMove);
  2900. break;
  2901. case HTTPMAIL_MEMBERINFO:
  2902. FreeMemberInfoList();
  2903. SafeMemFree(m_op.rResponse.rMemberInfoList.prgMemberInfo);
  2904. SafeMemFree(m_op.pszRootTimeStamp);
  2905. SafeMemFree(m_op.pszFolderTimeStamp);
  2906. SafeMemFree(m_op.rResponse.rMemberInfoList.pszRootTimeStamp);
  2907. SafeMemFree(m_op.rResponse.rMemberInfoList.pszFolderTimeStamp);
  2908. break;
  2909. case HTTPMAIL_MARKREAD:
  2910. FreeMemberErrorList();
  2911. SafeMemFree(m_op.rResponse.rMemberErrorList.prgMemberError);
  2912. break;
  2913. case HTTPMAIL_LISTCONTACTS:
  2914. FreeContactIdList();
  2915. SafeMemFree(m_op.rResponse.rContactIdList.prgContactId);
  2916. break;
  2917. case HTTPMAIL_CONTACTINFO:
  2918. FreeContactInfoList();
  2919. SafeMemFree(m_op.rResponse.rContactInfoList.prgContactInfo);
  2920. break;
  2921. case HTTPMAIL_POSTCONTACT:
  2922. XP_FREE_STRUCT(HTTPCONTACTID, &m_op.rResponse.rPostContactInfo, NULL);
  2923. break;
  2924. case HTTPMAIL_PATCHCONTACT:
  2925. XP_FREE_STRUCT(HTTPCONTACTID, &m_op.rResponse.rPatchContactInfo, NULL);
  2926. break;
  2927. default:
  2928. break;
  2929. }
  2930. ZeroMemory(&m_op, sizeof(HTTPMAILOPERATION));
  2931. m_op.rResponse.command = HTTPMAIL_NONE;
  2932. // Thread Safety
  2933. LeaveCriticalSection(&m_cs);
  2934. }
  2935. // --------------------------------------------------------------------------------
  2936. // CHTTPMailTransport::_BindToStruct
  2937. // --------------------------------------------------------------------------------
  2938. HRESULT CHTTPMailTransport::_BindToStruct(const WCHAR *pwcText,
  2939. ULONG ulLen,
  2940. const XPCOLUMN *prgCols,
  2941. DWORD cCols,
  2942. LPVOID pTarget,
  2943. BOOL *pfWasBound)
  2944. {
  2945. HRESULT hr = S_OK;
  2946. DWORD dwColIndex;
  2947. DWORD dwColFlags;
  2948. LPSTR *ppsz;
  2949. DWORD *pdw;
  2950. BOOL *pb;
  2951. HTTPMAILSPECIALFOLDER *ptySpecial;
  2952. HTTPMAILCONTACTTYPE *ptyContact;
  2953. HMELE ele;
  2954. HRESULT *phr;
  2955. if (pfWasBound)
  2956. *pfWasBound = FALSE;
  2957. // if the stack is overflowed, we definitely won't do anything with the text
  2958. if (m_op.dwStackDepth >= ELE_STACK_CAPACITY)
  2959. goto exit;
  2960. ele = m_op.rgEleStack[m_op.dwStackDepth - 1].ele;
  2961. for (dwColIndex = 0; dwColIndex < cCols; dwColIndex++)
  2962. {
  2963. if (ele == prgCols[dwColIndex].ele)
  2964. break;
  2965. }
  2966. if (dwColIndex >= cCols)
  2967. goto exit;
  2968. dwColFlags = prgCols[dwColIndex].dwFlags;
  2969. // the column may require validation of the element stack
  2970. if (!!(dwColFlags & XPCF_MSVALIDPROP))
  2971. {
  2972. if (!VALIDSTACK(c_rgPropFindPropValueStack))
  2973. goto exit;
  2974. }
  2975. else if (!!(dwColFlags & XPCF_MSVALIDMSRESPONSECHILD))
  2976. {
  2977. if (!VALIDSTACK(c_rgMultiStatusResponseChildStack))
  2978. goto exit;
  2979. }
  2980. if (dwColIndex < cCols)
  2981. {
  2982. switch (prgCols[dwColIndex].cdt)
  2983. {
  2984. case XPCDT_STRA:
  2985. ppsz = (LPSTR *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  2986. SafeMemFree(*ppsz);
  2987. hr = AllocStrFromStrNW(pwcText, ulLen, ppsz);
  2988. break;
  2989. case XPCDT_DWORD:
  2990. pdw = (DWORD *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  2991. *pdw = 0;
  2992. hr = StrNToDwordW(pwcText, ulLen, pdw);
  2993. break;
  2994. case XPCDT_BOOL:
  2995. pb = (BOOL *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  2996. *pb = FALSE;
  2997. hr = StrNToBoolW(pwcText, ulLen, pb);
  2998. break;
  2999. case XPCDT_IXPHRESULT:
  3000. phr = (HRESULT *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  3001. *phr = S_OK;
  3002. hr = StatusStrNToIxpHr(pwcText, ulLen, phr);
  3003. break;
  3004. case XPCDT_HTTPSPECIALFOLDER:
  3005. ptySpecial = (HTTPMAILSPECIALFOLDER *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  3006. *ptySpecial = HTTPMAIL_SF_NONE;
  3007. hr = StrNToSpecialFolderW(pwcText, ulLen, ptySpecial);
  3008. break;
  3009. case XPCDT_HTTPCONTACTTYPE:
  3010. ptyContact = (HTTPMAILCONTACTTYPE *)(((char *)pTarget) + prgCols[dwColIndex].offset);
  3011. *ptyContact = HTTPMAIL_CT_CONTACT;
  3012. hr = StrNToContactTypeW(pwcText, ulLen, ptyContact);
  3013. break;
  3014. default:
  3015. IxpAssert(FALSE);
  3016. break;
  3017. }
  3018. if (FAILED(hr))
  3019. goto exit;
  3020. // set the bit in the flag word to indicate that this field
  3021. // has been set.
  3022. if (!(dwColFlags & XPCF_DONTSETFLAG))
  3023. m_op.dwPropFlags |= (1 << dwColIndex);
  3024. if (pfWasBound)
  3025. *pfWasBound = TRUE;
  3026. }
  3027. exit:
  3028. return hr;
  3029. }
  3030. // --------------------------------------------------------------------------------
  3031. // CHTTPMailTransport::_FreeStruct
  3032. // --------------------------------------------------------------------------------
  3033. void CHTTPMailTransport::_FreeStruct(const XPCOLUMN *prgCols,
  3034. DWORD cCols,
  3035. LPVOID pTarget,
  3036. DWORD *pdwFlags)
  3037. {
  3038. DWORD dwFlags;
  3039. DWORD dwIndex = 0;
  3040. LPSTR *ppsz;
  3041. DWORD *pdw;
  3042. BOOL *pb;
  3043. HTTPMAILSPECIALFOLDER *ptySpecial;
  3044. HTTPMAILCONTACTTYPE *ptyContact;
  3045. HRESULT *phr;
  3046. if (NULL != pdwFlags)
  3047. {
  3048. dwFlags = *pdwFlags;
  3049. *pdwFlags = NOFLAGS;
  3050. }
  3051. else
  3052. dwFlags = 0xFFFFFFFF;
  3053. while (0 != dwFlags && dwIndex < cCols)
  3054. {
  3055. // test the low bit
  3056. if (!!(dwFlags & 0x00000001))
  3057. {
  3058. switch (prgCols[dwIndex].cdt)
  3059. {
  3060. case XPCDT_STRA:
  3061. ppsz = (LPSTR *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3062. SafeMemFree(*ppsz);
  3063. break;
  3064. case XPCDT_DWORD:
  3065. pdw = (DWORD *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3066. *pdw = 0;
  3067. break;
  3068. case XPCDT_BOOL:
  3069. pb = (BOOL *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3070. *pb = FALSE;
  3071. break;
  3072. case XPCDT_IXPHRESULT:
  3073. phr = (HRESULT *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3074. *phr = S_OK;
  3075. break;
  3076. case XPCDT_HTTPSPECIALFOLDER:
  3077. ptySpecial = (HTTPMAILSPECIALFOLDER *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3078. *ptySpecial = HTTPMAIL_SF_NONE;
  3079. break;
  3080. case XPCDT_HTTPCONTACTTYPE:
  3081. ptyContact = (HTTPMAILCONTACTTYPE *)(((char *)pTarget) + prgCols[dwIndex].offset);
  3082. *ptyContact = HTTPMAIL_CT_CONTACT;
  3083. break;
  3084. default:
  3085. IxpAssert(FALSE);
  3086. break;
  3087. }
  3088. }
  3089. dwFlags >>= 1;
  3090. dwIndex++;
  3091. }
  3092. }
  3093. // --------------------------------------------------------------------------------
  3094. // CHTTPMailTransport::_AppendTextToBuffer
  3095. // --------------------------------------------------------------------------------
  3096. HRESULT CHTTPMailTransport::_AppendTextToBuffer(LPPCDATABUFFER pTextBuffer,
  3097. const WCHAR *pwcText,
  3098. ULONG ulLen)
  3099. {
  3100. HRESULT hr = S_OK;
  3101. ULONG ulNewCapacity = pTextBuffer->ulLen + ulLen;
  3102. IxpAssert(ulLen > 0);
  3103. // grow the buffer if necessary, and append the text
  3104. if (pTextBuffer->ulCapacity < ulNewCapacity)
  3105. {
  3106. if (!MemRealloc((void **)&(pTextBuffer->pwcText), sizeof(WCHAR) * ulNewCapacity))
  3107. {
  3108. hr = E_OUTOFMEMORY;
  3109. goto exit;
  3110. }
  3111. pTextBuffer->ulCapacity = ulNewCapacity;
  3112. }
  3113. // copy the new text over. special case the one-byte case to avoid
  3114. // calls to CopyMemory when we see one character entities
  3115. if (1 == ulLen)
  3116. {
  3117. pTextBuffer->pwcText[pTextBuffer->ulLen++] = *pwcText;
  3118. }
  3119. else
  3120. {
  3121. CopyMemory(&pTextBuffer->pwcText[pTextBuffer->ulLen], pwcText, sizeof(WCHAR) * ulLen);
  3122. pTextBuffer->ulLen += ulLen;
  3123. }
  3124. exit:
  3125. return hr;
  3126. }
  3127. // --------------------------------------------------------------------------------
  3128. // CHTTPMailTransport::_AllocTextBuffer
  3129. // --------------------------------------------------------------------------------
  3130. HRESULT CHTTPMailTransport::_AllocTextBuffer(LPPCDATABUFFER *ppTextBuffer)
  3131. {
  3132. HRESULT hr = S_OK;
  3133. IxpAssert(NULL != ppTextBuffer);
  3134. *ppTextBuffer = NULL;
  3135. if (!MemAlloc((void **)ppTextBuffer, sizeof(PCDATABUFFER)))
  3136. {
  3137. hr = E_OUTOFMEMORY;
  3138. goto exit;
  3139. }
  3140. // allocate the buffer
  3141. if (!MemAlloc((void **)(&((*ppTextBuffer)->pwcText)), PCDATA_BUFSIZE * sizeof(WCHAR)))
  3142. {
  3143. MemFree(*ppTextBuffer);
  3144. *ppTextBuffer = NULL;
  3145. hr = E_OUTOFMEMORY;
  3146. goto exit;
  3147. }
  3148. (*ppTextBuffer)->ulLen = 0;
  3149. (*ppTextBuffer)->ulCapacity = PCDATA_BUFSIZE ;
  3150. exit:
  3151. return hr;
  3152. }
  3153. // --------------------------------------------------------------------------------
  3154. // CHTTPMailTransport::FreeTextBuffer
  3155. // --------------------------------------------------------------------------------
  3156. void CHTTPMailTransport::_FreeTextBuffer(LPPCDATABUFFER pTextBuffer)
  3157. {
  3158. if (pTextBuffer)
  3159. {
  3160. if (pTextBuffer->pwcText)
  3161. MemFree(pTextBuffer->pwcText);
  3162. MemFree(pTextBuffer);
  3163. }
  3164. }
  3165. // --------------------------------------------------------------------------------
  3166. // CHTTPMailTransport::FreeMemberInfoList
  3167. // --------------------------------------------------------------------------------
  3168. void CHTTPMailTransport::FreeMemberInfoList(void)
  3169. {
  3170. DWORD cInfo = m_op.rResponse.rMemberInfoList.cMemberInfo;
  3171. LPHTTPMEMBERINFO rgInfo = m_op.rResponse.rMemberInfoList.prgMemberInfo;
  3172. // free the completed infos
  3173. for (DWORD i = 0; i < cInfo; i++)
  3174. XP_FREE_STRUCT(HTTPMEMBERINFO, &rgInfo[i], NULL);
  3175. // free the partial info
  3176. if (m_op.dwPropFlags)
  3177. {
  3178. IxpAssert(cInfo < MEMBERINFO_MAXRESPONSES);
  3179. XP_FREE_STRUCT(HTTPMEMBERINFO, &rgInfo[cInfo], &m_op.dwPropFlags);
  3180. }
  3181. m_op.rResponse.rMemberInfoList.cMemberInfo= 0;
  3182. }
  3183. // --------------------------------------------------------------------------------
  3184. // CHTTPMailTransport::FreeMemberErrorList
  3185. // --------------------------------------------------------------------------------
  3186. void CHTTPMailTransport::FreeMemberErrorList(void)
  3187. {
  3188. DWORD cInfo = m_op.rResponse.rMemberErrorList.cMemberError;
  3189. LPHTTPMEMBERERROR rgInfo = m_op.rResponse.rMemberErrorList.prgMemberError;
  3190. // free the completed infos
  3191. for (DWORD i = 0; i < cInfo; i++)
  3192. XP_FREE_STRUCT(HTTPMEMBERERROR, &rgInfo[i], NULL);
  3193. // free the partial info
  3194. if (m_op.dwPropFlags)
  3195. {
  3196. IxpAssert(cInfo < MEMBERERROR_MAXRESPONSES);
  3197. XP_FREE_STRUCT(HTTPMEMBERERROR, &rgInfo[cInfo], &m_op.dwPropFlags);
  3198. }
  3199. m_op.rResponse.rMemberErrorList.cMemberError = 0;
  3200. }
  3201. // --------------------------------------------------------------------------------
  3202. // CHTTPMailTransport::FreeContactIdList
  3203. // --------------------------------------------------------------------------------
  3204. void CHTTPMailTransport::FreeContactIdList(void)
  3205. {
  3206. DWORD cId = m_op.rResponse.rContactIdList.cContactId;
  3207. LPHTTPCONTACTID rgId = m_op.rResponse.rContactIdList.prgContactId;
  3208. // free the completed ids
  3209. for (DWORD i = 0; i < cId; ++i)
  3210. XP_FREE_STRUCT(HTTPCONTACTID, &rgId[i], NULL);
  3211. // free the partial id
  3212. if (m_op.dwPropFlags)
  3213. {
  3214. IxpAssert(cId < LISTCONTACTS_MAXRESPONSES);
  3215. XP_FREE_STRUCT(HTTPCONTACTID, &rgId[cId], &m_op.dwPropFlags);
  3216. m_op.dwPropFlags = NOFLAGS;
  3217. }
  3218. m_op.rResponse.rContactIdList.cContactId = 0;
  3219. }
  3220. // --------------------------------------------------------------------------------
  3221. // CHTTPMailTransport::FreeContactInfoList
  3222. // --------------------------------------------------------------------------------
  3223. void CHTTPMailTransport::FreeContactInfoList(void)
  3224. {
  3225. DWORD cInfo = m_op.rResponse.rContactInfoList.cContactInfo;
  3226. LPHTTPCONTACTINFO rgInfo = m_op.rResponse.rContactInfoList.prgContactInfo;
  3227. // free the completed ids
  3228. for (DWORD i = 0; i < cInfo; ++i)
  3229. XP_FREE_STRUCT(HTTPCONTACTINFO, &rgInfo[i], NULL);
  3230. // free the partial info
  3231. if (m_op.dwPropFlags)
  3232. {
  3233. IxpAssert(cInfo < CONTACTINFO_MAXRESPONSES);
  3234. XP_FREE_STRUCT(HTTPCONTACTINFO, &rgInfo[cInfo], &m_op.dwPropFlags);
  3235. }
  3236. m_op.rResponse.rContactInfoList.cContactInfo = 0;
  3237. }
  3238. // --------------------------------------------------------------------------------
  3239. // CHTTPMailTransport::FreeBCopyMoveList
  3240. // --------------------------------------------------------------------------------
  3241. void CHTTPMailTransport::FreeBCopyMoveList(void)
  3242. {
  3243. DWORD cInfo = m_op.rResponse.rBCopyMoveList.cBCopyMove;
  3244. LPHTTPMAILBCOPYMOVE rgInfo = m_op.rResponse.rBCopyMoveList.prgBCopyMove;
  3245. // free the completed records
  3246. for (DWORD i = 0; i < cInfo; ++i)
  3247. XP_FREE_STRUCT(HTTPMAILBCOPYMOVE, &rgInfo[i], NULL);
  3248. // free the partial info
  3249. if (m_op.dwPropFlags)
  3250. {
  3251. IxpAssert(cInfo < BCOPYMOVE_MAXRESPONSES);
  3252. XP_FREE_STRUCT(HTTPMAILBCOPYMOVE, &rgInfo[cInfo], &m_op.dwPropFlags);
  3253. }
  3254. m_op.rResponse.rBCopyMoveList.cBCopyMove = 0;
  3255. }
  3256. // --------------------------------------------------------------------------------
  3257. // CHTTPMailTransport::ValidStack
  3258. // --------------------------------------------------------------------------------
  3259. BOOL CHTTPMailTransport::ValidStack(const HMELE *prgEle, DWORD cEle)
  3260. {
  3261. BOOL bResult = TRUE;
  3262. DWORD dw;
  3263. if (cEle != m_op.dwStackDepth)
  3264. {
  3265. bResult = FALSE;
  3266. goto exit;
  3267. }
  3268. IxpAssert(cEle <= ELE_STACK_CAPACITY);
  3269. for (dw = 0; dw < cEle; ++dw)
  3270. {
  3271. if (prgEle[dw] != HMELE_UNKNOWN && prgEle[dw] != m_op.rgEleStack[dw].ele)
  3272. {
  3273. bResult = FALSE;
  3274. goto exit;
  3275. }
  3276. }
  3277. exit:
  3278. return bResult;
  3279. }
  3280. // --------------------------------------------------------------------------------
  3281. // CHTTPMailTransport::PopNamespaces
  3282. // --------------------------------------------------------------------------------
  3283. void CHTTPMailTransport::PopNamespaces(CXMLNamespace *pBaseNamespace)
  3284. {
  3285. CXMLNamespace *pTemp;
  3286. while (pBaseNamespace != m_op.pTopNamespace)
  3287. {
  3288. IxpAssert(m_op.pTopNamespace);
  3289. pTemp = m_op.pTopNamespace->GetParent();
  3290. m_op.pTopNamespace->Release();
  3291. m_op.pTopNamespace = pTemp;
  3292. }
  3293. }
  3294. // --------------------------------------------------------------------------------
  3295. // CHTTPMailTransport::PushNamespaces
  3296. // --------------------------------------------------------------------------------
  3297. HRESULT CHTTPMailTransport::PushNamespaces(XML_NODE_INFO** apNodeInfo, USHORT cNumRecs)
  3298. {
  3299. HRESULT hr = S_OK;
  3300. CXMLNamespace *pNamespace = NULL;
  3301. for (USHORT i = 0; i < cNumRecs; ++i)
  3302. {
  3303. if (apNodeInfo[i]->dwType == XML_ATTRIBUTE && apNodeInfo[i]->dwSubType == XML_NS)
  3304. {
  3305. // better have at least one more record
  3306. IxpAssert(i < (cNumRecs - 1));
  3307. if (i < (cNumRecs - 1) && apNodeInfo[i + 1]->dwType == XML_PCDATA)
  3308. {
  3309. pNamespace = new CXMLNamespace();
  3310. if (!pNamespace)
  3311. {
  3312. hr = E_OUTOFMEMORY;
  3313. goto exit;
  3314. }
  3315. if (apNodeInfo[i]->ulLen != apNodeInfo[i]->ulNsPrefixLen)
  3316. {
  3317. if (FAILED(hr = pNamespace->SetPrefix(
  3318. &apNodeInfo[i]->pwcText[apNodeInfo[i]->ulNsPrefixLen + 1],
  3319. apNodeInfo[i]->ulLen - (apNodeInfo[i]->ulNsPrefixLen + 1))))
  3320. goto exit;
  3321. }
  3322. if (FAILED(hr = pNamespace->SetNamespace(apNodeInfo[i + 1]->pwcText, apNodeInfo[i + 1]->ulLen)))
  3323. goto exit;
  3324. pNamespace->SetParent(m_op.pTopNamespace);
  3325. if (m_op.pTopNamespace)
  3326. m_op.pTopNamespace->Release();
  3327. m_op.pTopNamespace = pNamespace;
  3328. pNamespace = NULL;
  3329. }
  3330. }
  3331. }
  3332. exit:
  3333. SafeRelease(pNamespace);
  3334. return hr;
  3335. }
  3336. // --------------------------------------------------------------------------------
  3337. // CHTTPMailTransport::AllocStrFromStrW
  3338. // --------------------------------------------------------------------------------
  3339. HRESULT CHTTPMailTransport::AllocStrFromStrNW(
  3340. const WCHAR *pwcText,
  3341. ULONG ulLen,
  3342. LPSTR *ppszAlloc)
  3343. {
  3344. HRESULT hr = S_OK;
  3345. DWORD iBufferSize;
  3346. DWORD iConvertedChars;
  3347. IxpAssert(NULL != ppszAlloc);
  3348. if (NULL == ppszAlloc)
  3349. return E_INVALIDARG;
  3350. *ppszAlloc = NULL;
  3351. // if pwcText is NULL, the result is null, but not an error
  3352. if (NULL == pwcText)
  3353. goto exit;
  3354. iBufferSize = WideCharToMultiByte(CP_ACP, 0, pwcText, ulLen, NULL, 0, NULL, NULL);
  3355. if (0 == iBufferSize)
  3356. {
  3357. m_op.rResponse.rIxpResult.uiServerError = GetLastError();
  3358. hr = TrapError(E_FAIL);
  3359. goto exit;
  3360. }
  3361. // allocate the buffer (add 1 to the size to allow for eos)
  3362. if (!MemAlloc((void **)ppszAlloc, iBufferSize + 1))
  3363. {
  3364. hr = TrapError(E_OUTOFMEMORY);
  3365. goto exit;
  3366. }
  3367. // convert the string
  3368. iConvertedChars = WideCharToMultiByte(CP_ACP, 0, pwcText, ulLen, *ppszAlloc, iBufferSize, NULL, NULL);
  3369. if (0 == iConvertedChars)
  3370. {
  3371. m_op.rResponse.rIxpResult.uiServerError = GetLastError();
  3372. hr = TrapError(E_FAIL);
  3373. goto exit;
  3374. }
  3375. IxpAssert(iConvertedChars == iBufferSize);
  3376. // terminate the new string
  3377. (*ppszAlloc)[iConvertedChars] = 0;
  3378. exit:
  3379. return hr;
  3380. }
  3381. // --------------------------------------------------------------------------------
  3382. // CHTTPMailTransport::StrNToDwordW
  3383. // --------------------------------------------------------------------------------
  3384. HRESULT CHTTPMailTransport::StrNToDwordW(const WCHAR *pwcText, ULONG ulLen, DWORD *pdw)
  3385. {
  3386. HRESULT hr = S_OK;
  3387. int i;
  3388. WCHAR wcBuf[32];
  3389. WCHAR *pwcUseBuf;
  3390. BOOL fFreeBuf = FALSE;
  3391. IxpAssert(NULL != pdw);
  3392. if (NULL == pdw)
  3393. return E_INVALIDARG;
  3394. *pdw = 0;
  3395. if (NULL == pwcText)
  3396. goto exit;
  3397. // decide whether to use a local buffer or an allocated buffer
  3398. if (ulLen < 32)
  3399. pwcUseBuf = wcBuf;
  3400. else
  3401. {
  3402. if (!MemAlloc((void **)&pwcUseBuf, (ulLen + 1) * sizeof(WCHAR)))
  3403. {
  3404. hr = E_OUTOFMEMORY;
  3405. goto exit;
  3406. }
  3407. fFreeBuf = TRUE;
  3408. }
  3409. // copy the string over
  3410. CopyMemory(pwcUseBuf, pwcText, ulLen * sizeof(WCHAR));
  3411. pwcUseBuf[ulLen] = 0;
  3412. *pdw = StrToIntW(pwcUseBuf);
  3413. exit:
  3414. if (fFreeBuf)
  3415. MemFree(pwcUseBuf);
  3416. return hr;
  3417. }
  3418. // --------------------------------------------------------------------------------
  3419. // CHTTPMailTransport::StrNToSpecialFolderW
  3420. // --------------------------------------------------------------------------------
  3421. HRESULT CHTTPMailTransport::StrNToSpecialFolderW(const WCHAR *pwcText,
  3422. ULONG ulLen,
  3423. HTTPMAILSPECIALFOLDER *ptySpecial)
  3424. {
  3425. HRESULT hr = S_OK;
  3426. if (NULL == ptySpecial)
  3427. return E_INVALIDARG;
  3428. *ptySpecial = HTTPMAIL_SF_UNRECOGNIZED;
  3429. if (NULL != pwcText && ulLen > 0)
  3430. {
  3431. for (DWORD dw = 0; dw < ARRAYSIZE(c_rgpfnSpecialFolder); dw++)
  3432. {
  3433. if (ulLen == c_rgpfnSpecialFolder[dw].ulLen)
  3434. {
  3435. if (0 == StrCmpNW(c_rgpfnSpecialFolder[dw].pwcName, pwcText, ulLen))
  3436. {
  3437. *ptySpecial = c_rgpfnSpecialFolder[dw].tyFolder;
  3438. break;
  3439. }
  3440. }
  3441. }
  3442. }
  3443. return hr;
  3444. }
  3445. // --------------------------------------------------------------------------------
  3446. // CHTTPMailTransport::StrNToContactTypeW
  3447. // --------------------------------------------------------------------------------
  3448. HRESULT CHTTPMailTransport::StrNToContactTypeW(const WCHAR *pwcText,
  3449. ULONG ulLen,
  3450. HTTPMAILCONTACTTYPE *ptyContact)
  3451. {
  3452. HRESULT hr = S_OK;
  3453. BOOL fGroup = FALSE;
  3454. IxpAssert(NULL != ptyContact);
  3455. if (NULL == ptyContact)
  3456. return E_INVALIDARG;
  3457. // for now, we treat the presence of the <group> element as an indication that
  3458. // the contact is a group
  3459. *ptyContact = HTTPMAIL_CT_GROUP;
  3460. #if 0
  3461. // for now, we treat the value as an integer-based bool
  3462. hr = StrNToBoolW(pwcText, ulLen, &fGroup);
  3463. // default is contact
  3464. *ptyContact = fGroup ? HTTPMAIL_CT_GROUP : HTTPMAIL_CT_CONTACT;
  3465. #endif
  3466. return hr;
  3467. }
  3468. // --------------------------------------------------------------------------------
  3469. // CHTTPMailTransport::StrNToBoolW
  3470. // --------------------------------------------------------------------------------
  3471. HRESULT CHTTPMailTransport::StrNToBoolW(const WCHAR *pwcText, DWORD ulLen, BOOL *pb)
  3472. {
  3473. HRESULT hr = S_OK;
  3474. DWORD dw;
  3475. IxpAssert(NULL != pb);
  3476. if (NULL == pb)
  3477. return E_INVALIDARG;
  3478. *pb = FALSE;
  3479. if (NULL == pwcText)
  3480. goto exit;
  3481. if (FAILED(hr = StrNToDwordW(pwcText, ulLen, &dw)))
  3482. goto exit;
  3483. if (dw != 0)
  3484. *pb = TRUE;
  3485. exit:
  3486. return hr;
  3487. }
  3488. // --------------------------------------------------------------------------------
  3489. // CHTTPMailTransport::StatusStrNToIxpHr
  3490. // --------------------------------------------------------------------------------
  3491. HRESULT CHTTPMailTransport::StatusStrNToIxpHr(const WCHAR *pwcText, DWORD ulLen, HRESULT *phr)
  3492. {
  3493. HRESULT hr = S_OK;
  3494. DWORD dw;
  3495. LPSTR pszStatus = NULL;
  3496. DWORD dwStatus = 0;
  3497. IxpAssert(NULL != phr);
  3498. if (NULL == phr)
  3499. return E_INVALIDARG;
  3500. *phr = S_OK;
  3501. if (NULL == pwcText)
  3502. goto exit;
  3503. if (FAILED(hr = AllocStrFromStrNW(pwcText, ulLen, &pszStatus)) || NULL == pszStatus)
  3504. goto exit;
  3505. HrParseHTTPStatus(pszStatus, &dwStatus);
  3506. if (dwStatus < 200 || dwStatus > 299)
  3507. *phr = HttpErrorToIxpResult(dwStatus);
  3508. exit:
  3509. SafeMemFree(pszStatus);
  3510. return hr;
  3511. }
  3512. // --------------------------------------------------------------------------------
  3513. // CHTTPMailTransport::CommandToVerb
  3514. // --------------------------------------------------------------------------------
  3515. LPSTR CHTTPMailTransport::CommandToVerb(HTTPMAILCOMMAND command)
  3516. {
  3517. LPSTR pszVerb = NULL;
  3518. // convert the command to a string
  3519. switch (command)
  3520. {
  3521. case HTTPMAIL_GET:
  3522. pszVerb = "GET";
  3523. break;
  3524. case HTTPMAIL_POST:
  3525. case HTTPMAIL_SENDMESSAGE:
  3526. pszVerb = "POST";
  3527. break;
  3528. case HTTPMAIL_PUT:
  3529. pszVerb = "PUT";
  3530. break;
  3531. case HTTPMAIL_GETPROP:
  3532. case HTTPMAIL_PROPFIND:
  3533. case HTTPMAIL_MEMBERINFO:
  3534. case HTTPMAIL_LISTCONTACTS:
  3535. case HTTPMAIL_CONTACTINFO:
  3536. pszVerb = "PROPFIND";
  3537. break;
  3538. case HTTPMAIL_MARKREAD:
  3539. if (m_op.fBatch)
  3540. pszVerb = "BPROPPATCH";
  3541. else
  3542. pszVerb = "PROPPATCH";
  3543. break;
  3544. case HTTPMAIL_MKCOL:
  3545. pszVerb = "MKCOL";
  3546. break;
  3547. case HTTPMAIL_COPY:
  3548. pszVerb = "COPY";
  3549. break;
  3550. case HTTPMAIL_BCOPY:
  3551. pszVerb = "BCOPY";
  3552. break;
  3553. case HTTPMAIL_MOVE:
  3554. pszVerb = "MOVE";
  3555. break;
  3556. case HTTPMAIL_BMOVE:
  3557. pszVerb = "BMOVE";
  3558. break;
  3559. case HTTPMAIL_PROPPATCH:
  3560. pszVerb = "PROPPATCH";
  3561. break;
  3562. case HTTPMAIL_DELETE:
  3563. pszVerb = "DELETE";
  3564. break;
  3565. case HTTPMAIL_BDELETE:
  3566. pszVerb = "BDELETE";
  3567. break;
  3568. case HTTPMAIL_POSTCONTACT:
  3569. // first post the contact, then do a propfind
  3570. if (NULL == m_op.rResponse.rPostContactInfo.pszHref)
  3571. pszVerb = "POST";
  3572. else
  3573. pszVerb = "PROPFIND";
  3574. break;
  3575. case HTTPMAIL_PATCHCONTACT:
  3576. // first patch the contact, then do a propfind
  3577. if (NULL == m_op.rResponse.rPatchContactInfo.pszHref)
  3578. pszVerb = "PROPPATCH";
  3579. else
  3580. pszVerb = "PROPFIND";
  3581. break;
  3582. default:
  3583. pszVerb = "";
  3584. IxpAssert(FALSE);
  3585. break;
  3586. }
  3587. return pszVerb;
  3588. }
  3589. // --------------------------------------------------------------------------------
  3590. // CHTTPMailTransport::UpdateLogonInfo
  3591. // --------------------------------------------------------------------------------
  3592. HRESULT CHTTPMailTransport::UpdateLogonInfo(void)
  3593. {
  3594. // send the message synchronously
  3595. return (HRESULT) (::SendMessage(m_hwnd, SPM_HTTPMAIL_LOGONPROMPT, NULL, NULL));
  3596. }
  3597. // --------------------------------------------------------------------------------
  3598. // CHTTPMailTransport::GetParentWindow
  3599. // --------------------------------------------------------------------------------
  3600. HRESULT CHTTPMailTransport::GetParentWindow(HWND *phwndParent)
  3601. {
  3602. // send the message synchronously
  3603. return (HRESULT) (::SendMessage(m_hwnd, SPM_HTTPMAIL_GETPARENTWINDOW, (WPARAM)phwndParent, NULL));
  3604. }
  3605. // --------------------------------------------------------------------------------
  3606. // CHTTPMailTransport::ReadBytes
  3607. // --------------------------------------------------------------------------------
  3608. BOOL CHTTPMailTransport::ReadBytes(LPSTR pszBuffer, DWORD cbBufferSize, DWORD *pcbBytesRead)
  3609. {
  3610. return InternetReadFile(m_op.hRequest, pszBuffer, cbBufferSize, pcbBytesRead);
  3611. }
  3612. // --------------------------------------------------------------------------------
  3613. // CHTTPMailTransport::_GetStatusCode
  3614. // --------------------------------------------------------------------------------
  3615. BOOL CHTTPMailTransport::_GetStatusCode(DWORD *pdw)
  3616. {
  3617. IxpAssert(NULL != pdw);
  3618. DWORD dwStatusSize = sizeof(DWORD);
  3619. *pdw = 0;
  3620. return HttpQueryInfo(m_op.hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_STATUS_CODE, pdw, &dwStatusSize, NULL);
  3621. }
  3622. // --------------------------------------------------------------------------------
  3623. // CHTTPMailTransport::_GetContentLength
  3624. // --------------------------------------------------------------------------------
  3625. BOOL CHTTPMailTransport::_GetContentLength(DWORD *pdw)
  3626. {
  3627. IxpAssert(NULL != pdw);
  3628. DWORD dwLengthSize = sizeof(DWORD);
  3629. *pdw = 0;
  3630. return HttpQueryInfo(m_op.hRequest, HTTP_QUERY_FLAG_NUMBER | HTTP_QUERY_CONTENT_LENGTH, pdw, &dwLengthSize, NULL);
  3631. }
  3632. // --------------------------------------------------------------------------------
  3633. // CHTTPMailTransport::_GetRequestHeader
  3634. // --------------------------------------------------------------------------------
  3635. HRESULT CHTTPMailTransport::_GetRequestHeader(LPSTR *ppszHeader, DWORD dwHeader)
  3636. {
  3637. HRESULT hr = S_OK;
  3638. DWORD dwSize = MAX_PATH;
  3639. LPSTR pszHeader = NULL;
  3640. Assert(NULL != ppszHeader);
  3641. *ppszHeader = NULL;
  3642. retry:
  3643. pszHeader = (LPSTR)ZeroAllocate(dwSize);
  3644. if (!pszHeader)
  3645. {
  3646. hr = E_OUTOFMEMORY;
  3647. goto exit;
  3648. }
  3649. if (!HttpQueryInfo(m_op.hRequest, dwHeader, pszHeader, &dwSize, NULL))
  3650. {
  3651. if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
  3652. goto exit;
  3653. SafeMemFree(pszHeader);
  3654. goto retry;
  3655. }
  3656. *ppszHeader = pszHeader;
  3657. pszHeader = NULL;
  3658. exit:
  3659. SafeMemFree(pszHeader);
  3660. return hr;
  3661. }
  3662. // --------------------------------------------------------------------------------
  3663. // CHTTPMailTransport::_AddRequestHeader
  3664. // --------------------------------------------------------------------------------
  3665. HRESULT CHTTPMailTransport::_AddRequestHeader(LPCSTR pszHeader)
  3666. {
  3667. HRESULT hr = S_OK;
  3668. if (!HttpAddRequestHeaders(m_op.hRequest, pszHeader, lstrlen(pszHeader), HTTP_ADDREQ_FLAG_ADD))
  3669. hr = HrGetLastError();
  3670. return hr;
  3671. }
  3672. // --------------------------------------------------------------------------------
  3673. // CHTTPMailTransport::_AuthCurrentRequest
  3674. // --------------------------------------------------------------------------------
  3675. BOOL CHTTPMailTransport::_AuthCurrentRequest(DWORD dwStatus, BOOL fRetryAuth)
  3676. {
  3677. BOOL fResult = FALSE;
  3678. HRESULT hr;
  3679. // unused code to let wininet do the ui
  3680. #if 0
  3681. if (HTTP_STATUS_PROXY_AUTH_REQ == dwStatus || HTTP_STATUS_DENIED == dwStatus)
  3682. {
  3683. if (!fRequestedParent)
  3684. {
  3685. GetParentWindow(&hwndParent);
  3686. fRequestedParent = TRUE;
  3687. }
  3688. hr = InternetErrorDlg(hwndParent, m_op.hRequest, hr,
  3689. FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
  3690. FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
  3691. FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
  3692. NULL);
  3693. if (ERROR_INTERNET_FORCE_RETRY == hr)
  3694. goto resend;
  3695. }
  3696. #endif
  3697. // TODO: should probably let wininet handle proxy auth errors
  3698. #if 0
  3699. case HTTP_STATUS_PROXY_AUTH_REQ: //Proxy Authentication Required
  3700. InternetSetOption(m_op.hRequest, INTERNET_OPTION_PROXY_USERNAME,
  3701. GetUserName(), strlen(GetUserName())+1);
  3702. InternetSetOption(m_op.hRequest, INTERNET_OPTION_PROXY_PASSWORD,
  3703. GetPassword(), strlen(GetPassword())+1);
  3704. break;
  3705. #endif
  3706. if (HTTP_STATUS_DENIED == dwStatus) //Server Authentication Required
  3707. {
  3708. if (fRetryAuth || (SUCCEEDED(hr = UpdateLogonInfo()) && S_FALSE != hr))
  3709. {
  3710. InternetSetOption(m_op.hRequest, INTERNET_OPTION_USERNAME,
  3711. GetUserName(), strlen(GetUserName())+1);
  3712. InternetSetOption(m_op.hRequest, INTERNET_OPTION_PASSWORD,
  3713. GetPassword(), strlen(GetPassword())+1);
  3714. fResult = TRUE;
  3715. }
  3716. }
  3717. return fResult;
  3718. }
  3719. // --------------------------------------------------------------------------------
  3720. // CHTTPMailTransport::_LogRequest
  3721. // --------------------------------------------------------------------------------
  3722. void CHTTPMailTransport::_LogRequest(LPVOID pvData, DWORD cbData)
  3723. {
  3724. HRESULT hr = S_OK;
  3725. CByteStream bs;
  3726. LPSTR pszCommand = CommandToVerb(m_op.rResponse.command);
  3727. LPSTR pszLogData = NULL;
  3728. Assert(NULL != m_pLogFile);
  3729. if (NULL == m_pLogFile)
  3730. return;
  3731. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3732. FAIL_EXIT_STREAM_WRITE(bs, pszCommand);
  3733. FAIL_EXIT_STREAM_WRITE(bs, c_szSpace);
  3734. FAIL_EXIT_STREAM_WRITE(bs, m_op.pszUrl);
  3735. if (pvData && cbData)
  3736. {
  3737. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3738. if (FAILED(hr = bs.Write(pvData, cbData, NULL)))
  3739. goto exit;
  3740. }
  3741. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3742. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3743. FAIL_EXIT(hr = bs.HrAcquireStringA(NULL, &pszLogData, ACQ_DISPLACE));
  3744. m_pLogFile->WriteLog(LOGFILE_TX, pszLogData);
  3745. exit:
  3746. SafeMemFree(pszLogData);
  3747. return;
  3748. }
  3749. // --------------------------------------------------------------------------------
  3750. // CHTTPMailTransport::_LogResponse
  3751. // --------------------------------------------------------------------------------
  3752. void CHTTPMailTransport::_LogResponse(LPVOID pvData, DWORD cbData)
  3753. {
  3754. HRESULT hr = S_OK;
  3755. CByteStream bs;
  3756. LPSTR pszHeaders = NULL;
  3757. LPSTR pszLogData = NULL;
  3758. Assert(NULL != m_pLogFile);
  3759. if (NULL == m_pLogFile || m_op.fLoggedResponse)
  3760. return;
  3761. FAIL_EXIT(_GetRequestHeader(&pszHeaders, HTTP_QUERY_RAW_HEADERS_CRLF));
  3762. if (pszHeaders)
  3763. {
  3764. // prefix with a CRLF
  3765. if ('\r' != pszHeaders[0])
  3766. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3767. FAIL_EXIT_STREAM_WRITE(bs, pszHeaders);
  3768. }
  3769. if (pvData && cbData)
  3770. {
  3771. if (FAILED(hr = bs.Write(pvData, cbData, NULL)))
  3772. goto exit;
  3773. }
  3774. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3775. FAIL_EXIT_STREAM_WRITE(bs, c_szCRLF);
  3776. FAIL_EXIT(hr = bs.HrAcquireStringA(NULL, &pszLogData, ACQ_DISPLACE));
  3777. m_pLogFile->WriteLog(LOGFILE_RX, pszLogData);
  3778. exit:
  3779. m_op.fLoggedResponse = TRUE;
  3780. SafeMemFree(pszHeaders);
  3781. SafeMemFree(pszLogData);
  3782. return;
  3783. }
  3784. // --------------------------------------------------------------------------------
  3785. // CHTTPMailTransport::TranslateWinInetMsg
  3786. // --------------------------------------------------------------------------------
  3787. BOOL CHTTPMailTransport::TranslateWinInetMsg(
  3788. DWORD dwInternetStatus,
  3789. IXPSTATUS *pIxpStatus)
  3790. {
  3791. IxpAssert(NULL != pIxpStatus);
  3792. switch (dwInternetStatus)
  3793. {
  3794. case INTERNET_STATUS_RESOLVING_NAME:
  3795. *pIxpStatus = IXP_FINDINGHOST;
  3796. break;
  3797. case INTERNET_STATUS_CONNECTING_TO_SERVER:
  3798. *pIxpStatus = IXP_CONNECTING;
  3799. break;
  3800. case INTERNET_STATUS_CONNECTED_TO_SERVER:
  3801. *pIxpStatus = IXP_CONNECTED;
  3802. break;
  3803. case INTERNET_STATUS_CLOSING_CONNECTION:
  3804. *pIxpStatus = IXP_DISCONNECTING;
  3805. break;
  3806. case INTERNET_STATUS_CONNECTION_CLOSED:
  3807. *pIxpStatus = IXP_DISCONNECTED;
  3808. break;
  3809. case INTERNET_STATUS_REQUEST_COMPLETE:
  3810. *pIxpStatus = IXP_LAST;
  3811. break;
  3812. default:
  3813. // status codes that are not translated:
  3814. // INTERNET_STATUS_NAME_RESOLVED
  3815. // INTERNET_STATUS_SENDING_REQUEST
  3816. // INTERNET_STATUS_ REQUEST_SENT
  3817. // INTERNET_STATUS_RECEIVING_RESPONSE
  3818. // INTERNET_STATUS_RESPONSE_RECEIVED
  3819. // INTERNET_STATUS_REDIRECT
  3820. // INTERNET_STATUS_HANDLE_CREATED
  3821. // INTERNET_STATUS_HANDLE_CLOSING
  3822. return FALSE;
  3823. }
  3824. return TRUE;
  3825. }
  3826. // --------------------------------------------------------------------------------
  3827. // CHTTPMailTransport::_CreateXMLParser
  3828. // --------------------------------------------------------------------------------
  3829. HRESULT CHTTPMailTransport::_CreateXMLParser()
  3830. {
  3831. HRESULT hr = S_OK;
  3832. if (NULL == m_pParser)
  3833. {
  3834. // instantiate the xml document
  3835. hr = ::CoCreateInstance(CLSID_XMLParser,
  3836. NULL,
  3837. CLSCTX_INPROC_SERVER,
  3838. IID_IXMLParser,
  3839. reinterpret_cast<void **>(&m_pParser));
  3840. if (FAILED(hr))
  3841. goto exit;
  3842. if (FAILED(hr = m_pParser->SetFlags(XMLFLAG_FLOATINGAMP)))
  3843. goto exit;
  3844. }
  3845. hr = m_pParser->SetFactory(this);
  3846. exit:
  3847. return hr;
  3848. }
  3849. // --------------------------------------------------------------------------------
  3850. // CHTTPMailTransport::OpenRequest
  3851. // --------------------------------------------------------------------------------
  3852. HRESULT CHTTPMailTransport::OpenRequest(void)
  3853. {
  3854. LPSTR pszVerb = NULL;
  3855. HRESULT hr = S_OK;
  3856. LPSTR pszHostName = NULL;
  3857. LPSTR pszUrlPath = NULL;
  3858. INTERNET_PORT nPort;
  3859. LPSTR pszUserName = GetUserName();
  3860. LPSTR pszPassword = GetPassword();
  3861. if (NULL == pszUserName)
  3862. pszUserName = "";
  3863. if (NULL == pszPassword)
  3864. pszPassword = "";
  3865. // crack the url into component parts
  3866. if (FAILED(hr = HrCrackUrl(m_op.pszUrl, &pszHostName, &pszUrlPath, &nPort)))
  3867. {
  3868. TrapError(hr);
  3869. goto exit;
  3870. }
  3871. if (FAILED(hr = HrConnectToHost(pszHostName, nPort, pszUserName, NULL)))
  3872. {
  3873. TrapError(hr);
  3874. goto exit;
  3875. }
  3876. // We have to set the password and username on every connection. If we don't,
  3877. // and and incorrect password or username forces us to prompt the user, the
  3878. // newly entered data won't get used on subsequent requests
  3879. InternetSetOption(GetConnection(), INTERNET_OPTION_USERNAME, pszUserName, lstrlen(pszUserName) + 1);
  3880. InternetSetOption(GetConnection(), INTERNET_OPTION_PASSWORD, pszPassword, lstrlen(pszPassword) + 1);
  3881. FAIL_ABORT;
  3882. // convert the command to a verb string
  3883. pszVerb = CommandToVerb(m_op.rResponse.command);
  3884. // Open the HTTP request
  3885. m_op.hRequest = HttpOpenRequest(
  3886. GetConnection(),
  3887. pszVerb,
  3888. pszUrlPath,
  3889. NULL,
  3890. NULL,
  3891. m_op.rgszAcceptTypes,
  3892. INTERNET_FLAG_EXISTING_CONNECT |
  3893. INTERNET_FLAG_RELOAD |
  3894. INTERNET_FLAG_KEEP_CONNECTION,
  3895. 0);
  3896. if (NULL == m_op.hRequest)
  3897. {
  3898. DWORD dwErr = GetLastError();
  3899. hr = E_FAIL;
  3900. }
  3901. exit:
  3902. SafeMemFree(pszHostName);
  3903. SafeMemFree(pszUrlPath);
  3904. return hr;
  3905. }
  3906. // --------------------------------------------------------------------------------
  3907. // CHTTPMailTransport::SendPostRequest
  3908. // --------------------------------------------------------------------------------
  3909. HRESULT CHTTPMailTransport::SendPostRequest(void)
  3910. {
  3911. HRESULT hr = S_OK;
  3912. INTERNET_BUFFERS buffers;
  3913. DWORD cbData;
  3914. ULONG cbRead;
  3915. ULONG cbWritten;
  3916. BOOL fResult;
  3917. CHAR localBuffer[HTTPMAIL_BUFSIZE];
  3918. LARGE_INTEGER liOrigin = {0,0};
  3919. DWORD dwBufferLength;
  3920. BOOL fSentData = FALSE;
  3921. BOOL fWillSend;
  3922. DWORD dwWinInetErr = 0;
  3923. BOOL fRetryAuth = FALSE;
  3924. // log the request, but don't log the request body
  3925. if (m_pLogFile)
  3926. _LogRequest(NULL, 0);
  3927. if (m_op.pHeaderStream)
  3928. {
  3929. if (FAILED(hr = HrGetStreamSize(m_op.pHeaderStream, &m_op.rResponse.rPostInfo.cbTotal)))
  3930. goto exit;
  3931. }
  3932. if (m_op.pBodyStream)
  3933. {
  3934. if (FAILED(hr = HrGetStreamSize(m_op.pBodyStream, &cbData)))
  3935. goto exit;
  3936. m_op.rResponse.rPostInfo.cbTotal += cbData;
  3937. }
  3938. buffers.dwStructSize = sizeof(INTERNET_BUFFERSA);
  3939. buffers.Next = NULL;
  3940. buffers.lpcszHeader = NULL;
  3941. buffers.dwHeadersLength = 0;
  3942. buffers.dwHeadersTotal = 0;
  3943. buffers.lpvBuffer = NULL;
  3944. buffers.dwBufferLength = 0;
  3945. buffers.dwBufferTotal = m_op.rResponse.rPostInfo.cbTotal;
  3946. buffers.dwOffsetLow = 0;
  3947. buffers.dwOffsetHigh = 0;
  3948. resend:
  3949. if (fSentData)
  3950. {
  3951. m_op.rResponse.rPostInfo.fResend = TRUE;
  3952. m_op.rResponse.rPostInfo.cbCurrent = 0;
  3953. _HrThunkResponse(FALSE);
  3954. m_op.rResponse.rPostInfo.fResend = FALSE;
  3955. FAIL_ABORT;
  3956. }
  3957. fResult = HttpSendRequestEx(m_op.hRequest, &buffers, NULL, 0, 0);
  3958. if (!fResult)
  3959. {
  3960. dwWinInetErr = GetLastError();
  3961. if (ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION == dwWinInetErr)
  3962. {
  3963. fRetryAuth = TRUE;
  3964. goto resend;
  3965. }
  3966. _HrThunkConnectionError(dwWinInetErr);
  3967. hr = E_FAIL;
  3968. goto exit;
  3969. }
  3970. // with some auth methods (e.g., NTLM), wininet will send a post request
  3971. // with a content length of 0, and will ignore calls to InternetWriteFile
  3972. // until the server sends a 100 (continue) response. wininet will then
  3973. // return ERROR_INTERNET_FORCE_RETRY to force a resend. we detect this
  3974. // case here so that we don't send a bunch of OnResponse progress notifications
  3975. // when no data is actually going out over the wire
  3976. // this constant isn't in the wininet headers as of 10/6/98!!
  3977. #ifndef INTERNET_OPTION_DETECT_POST_SEND
  3978. #define INTERNET_OPTION_DETECT_POST_SEND 71
  3979. #endif
  3980. dwBufferLength = sizeof(fWillSend);
  3981. if (!InternetQueryOption(m_op.hRequest, INTERNET_OPTION_DETECT_POST_SEND, &fWillSend, &dwBufferLength))
  3982. fWillSend = TRUE;
  3983. else
  3984. {
  3985. Assert(dwBufferLength == sizeof(BOOL));
  3986. }
  3987. if (fWillSend)
  3988. {
  3989. fSentData = TRUE;
  3990. if (m_op.pHeaderStream)
  3991. {
  3992. // rewind the stream
  3993. if (FAILED(hr = m_op.pHeaderStream->Seek(liOrigin, STREAM_SEEK_SET, NULL)))
  3994. goto exit;
  3995. while (TRUE)
  3996. {
  3997. if (FAILED(hr = m_op.pHeaderStream->Read(localBuffer, sizeof(localBuffer), &cbRead)))
  3998. goto exit;
  3999. if (0 == cbRead)
  4000. break;
  4001. fResult = InternetWriteFile(m_op.hRequest, localBuffer, cbRead, &cbWritten);
  4002. IxpAssert(!fResult || (cbRead == cbWritten));
  4003. if (!fResult)
  4004. {
  4005. _HrThunkConnectionError(GetLastError());
  4006. hr = E_FAIL;
  4007. goto exit;
  4008. }
  4009. m_op.rResponse.rPostInfo.cbIncrement = cbWritten;
  4010. m_op.rResponse.rPostInfo.cbCurrent += cbWritten;
  4011. _HrThunkResponse(FALSE);
  4012. m_op.rResponse.rPostInfo.cbIncrement = 0;
  4013. FAIL_ABORT;
  4014. }
  4015. }
  4016. if (m_op.pBodyStream)
  4017. {
  4018. // rewind the stream
  4019. if (FAILED(hr = m_op.pBodyStream->Seek(liOrigin, STREAM_SEEK_SET, NULL)))
  4020. goto exit;
  4021. while (TRUE)
  4022. {
  4023. if (FAILED(hr = m_op.pBodyStream->Read(localBuffer, sizeof(localBuffer), &cbRead)))
  4024. goto exit;
  4025. if (0 == cbRead)
  4026. break;
  4027. fResult = InternetWriteFile(m_op.hRequest, localBuffer, cbRead, &cbWritten);
  4028. IxpAssert(!fResult || (cbRead == cbWritten));
  4029. if (!fResult)
  4030. {
  4031. _HrThunkConnectionError(GetLastError());
  4032. hr = E_FAIL;
  4033. goto exit;
  4034. }
  4035. m_op.rResponse.rPostInfo.cbIncrement = cbWritten;
  4036. m_op.rResponse.rPostInfo.cbCurrent += cbWritten;
  4037. _HrThunkResponse(FALSE);
  4038. m_op.rResponse.rPostInfo.cbIncrement = 0;
  4039. FAIL_ABORT;
  4040. }
  4041. }
  4042. }
  4043. fResult = HttpEndRequest(m_op.hRequest, NULL, 0, 0);
  4044. if (!fResult)
  4045. {
  4046. if (ERROR_INTERNET_FORCE_RETRY == GetLastError())
  4047. goto resend;
  4048. _HrThunkConnectionError(GetLastError());
  4049. }
  4050. if (!_GetStatusCode(&m_op.dwHttpStatus))
  4051. {
  4052. _HrThunkConnectionError(GetLastError());
  4053. hr = E_FAIL;
  4054. goto exit;
  4055. }
  4056. if (_AuthCurrentRequest(m_op.dwHttpStatus, fRetryAuth))
  4057. {
  4058. fRetryAuth = FALSE;
  4059. goto resend;
  4060. }
  4061. if (!fResult)
  4062. {
  4063. _HrThunkConnectionError();
  4064. hr = E_FAIL;
  4065. goto exit;
  4066. }
  4067. // status codes not in the 200-299 range indicate an error
  4068. if (200 > m_op.dwHttpStatus || 299 < m_op.dwHttpStatus)
  4069. {
  4070. _HrThunkConnectionError();
  4071. hr = E_FAIL;
  4072. }
  4073. exit:
  4074. return hr;
  4075. }
  4076. // --------------------------------------------------------------------------------
  4077. // CHTTPMailTransport::SendRequest
  4078. // --------------------------------------------------------------------------------
  4079. HRESULT CHTTPMailTransport::SendRequest(void)
  4080. {
  4081. HRESULT hr = S_OK;
  4082. DWORD dwError;
  4083. BOOL bResult;
  4084. HWND hwndParent = NULL;
  4085. BOOL fRequestedParent = FALSE;
  4086. DWORD dwWinInetErr = 0;
  4087. BOOL fRetryAuth = FALSE;
  4088. // log the request, including the requets body
  4089. if (m_pLogFile)
  4090. _LogRequest(m_op.pvData, m_op.cbDataLen);
  4091. resend:
  4092. hr = S_OK;
  4093. bResult = HttpSendRequest(m_op.hRequest, NULL, 0L, m_op.pvData, m_op.cbDataLen);
  4094. if (!bResult)
  4095. {
  4096. dwWinInetErr = GetLastError();
  4097. if (ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION == dwWinInetErr)
  4098. {
  4099. fRetryAuth = TRUE;
  4100. goto resend;
  4101. }
  4102. _HrThunkConnectionError(dwWinInetErr);
  4103. hr = E_FAIL;
  4104. goto exit;
  4105. }
  4106. if (!_GetStatusCode(&m_op.dwHttpStatus))
  4107. {
  4108. _HrThunkConnectionError(GetLastError());
  4109. hr = E_FAIL;
  4110. goto exit;
  4111. }
  4112. if (_AuthCurrentRequest(m_op.dwHttpStatus, fRetryAuth))
  4113. {
  4114. fRetryAuth = FALSE;
  4115. goto resend;
  4116. }
  4117. // status codes not in the 200-299 range indicate an error
  4118. if (200 > m_op.dwHttpStatus|| 299 < m_op.dwHttpStatus)
  4119. {
  4120. _HrThunkConnectionError();
  4121. hr = E_FAIL;
  4122. goto exit;
  4123. }
  4124. exit:
  4125. return hr;
  4126. }
  4127. // --------------------------------------------------------------------------------
  4128. // CHTTPMailTransport::RequireMultiStatus
  4129. // --------------------------------------------------------------------------------
  4130. HRESULT CHTTPMailTransport::RequireMultiStatus(void)
  4131. {
  4132. HRESULT hr = S_OK;
  4133. if (207 != m_op.dwHttpStatus)
  4134. {
  4135. _HrThunkConnectionError(ERROR_INTERNET_CANNOT_CONNECT);
  4136. hr = E_FAIL;
  4137. }
  4138. return hr;
  4139. }
  4140. // --------------------------------------------------------------------------------
  4141. // CHTTPMailTransport::FinalizeRequest
  4142. // --------------------------------------------------------------------------------
  4143. HRESULT CHTTPMailTransport::FinalizeRequest(void)
  4144. {
  4145. HRESULT hr = S_OK;
  4146. LPSTR pszTimestampHeader = NULL;
  4147. // log the response if it hasn't already been logged
  4148. if (m_pLogFile && !m_op.fLoggedResponse)
  4149. _LogResponse(NULL, 0);
  4150. if (HTTPMAIL_MEMBERINFO == m_op.rResponse.command)
  4151. {
  4152. // Get the headers and copy them. If we don't get timestamp header, its not a big deal. We don't report an error.
  4153. hr = _HrGetTimestampHeader(&pszTimestampHeader);
  4154. if (SUCCEEDED(hr))
  4155. {
  4156. // Get the Active timestamp
  4157. FAIL_EXIT(hr = _HrParseAndCopy(c_szActive, &m_op.rResponse.rMemberInfoList.pszFolderTimeStamp, pszTimestampHeader));
  4158. // Get RootTimeStamp which for some strange reason comes as Folders TimeStamp
  4159. // This call might fail for legitimate reasons. For Inbox list headers we do not get a RootTimeStamp.
  4160. // Hence we do not exit if we can't get root time stamp.
  4161. _HrParseAndCopy(c_szFolders, &m_op.rResponse.rMemberInfoList.pszRootTimeStamp, pszTimestampHeader);
  4162. SafeMemFree(pszTimestampHeader);
  4163. }
  4164. }
  4165. hr = _HrThunkResponse(TRUE);
  4166. exit:
  4167. return hr;
  4168. }
  4169. // --------------------------------------------------------------------------------
  4170. // CHTTPMailTransport::ProcessGetResponse
  4171. // --------------------------------------------------------------------------------
  4172. HRESULT CHTTPMailTransport::ProcessGetResponse(void)
  4173. {
  4174. HRESULT hr = S_OK;
  4175. BOOL bRead;
  4176. DWORD cbReadBytes = 0;
  4177. // log the respnse, but don't log the response body
  4178. if (m_pLogFile && !m_op.fLoggedResponse)
  4179. _LogResponse(NULL, 0);
  4180. Assert(NULL == m_op.rResponse.rGetInfo.pszContentType);
  4181. // extract the content type header
  4182. FAIL_EXIT(hr = _GetRequestHeader(&m_op.rResponse.rGetInfo.pszContentType, HTTP_QUERY_CONTENT_TYPE));
  4183. // try to get the content length
  4184. m_op.rResponse.rGetInfo.fTotalKnown = _GetContentLength(&m_op.rResponse.rGetInfo.cbTotal);
  4185. do
  4186. {
  4187. // The buffer is owned by this object, but the client
  4188. // has the option of taking ownership of the buffer
  4189. // whenever a read completes. We reallocate the buffer
  4190. // here if necessary
  4191. FAIL_ABORT;
  4192. if (!m_op.rResponse.rGetInfo.pvBody && !MemAlloc((void**)&m_op.rResponse.rGetInfo.pvBody, HTTPMAIL_BUFSIZE + 1))
  4193. {
  4194. hr = E_OUTOFMEMORY;
  4195. break;
  4196. }
  4197. bRead = ReadBytes((char *)m_op.rResponse.rGetInfo.pvBody, HTTPMAIL_BUFSIZE, &cbReadBytes);
  4198. m_op.rResponse.rGetInfo.cbIncrement = cbReadBytes;
  4199. m_op.rResponse.rGetInfo.cbCurrent += cbReadBytes;
  4200. // we guarantee space for the terminating null by allocating
  4201. // a buffer one larger than bufsize
  4202. static_cast<char *>(m_op.rResponse.rGetInfo.pvBody)[cbReadBytes] = '\0';
  4203. // Send a message to the window that lives in the client's thread
  4204. _HrThunkResponse(0 == cbReadBytes);
  4205. } while (0 < cbReadBytes);
  4206. exit:
  4207. SafeMemFree(m_op.rResponse.rGetInfo.pvBody);
  4208. return hr;
  4209. }
  4210. // --------------------------------------------------------------------------------
  4211. // CHTTPMailTransport::ProcessPostResponse
  4212. // --------------------------------------------------------------------------------
  4213. HRESULT CHTTPMailTransport::ProcessPostResponse(void)
  4214. {
  4215. HRESULT hr = S_OK;
  4216. // log the response
  4217. if (m_pLogFile && !m_op.fLoggedResponse)
  4218. _LogResponse(NULL, 0);
  4219. if (m_op.dwHttpStatus < 200 || m_op.dwHttpStatus > 299)
  4220. {
  4221. _HrThunkConnectionError();
  4222. hr = E_FAIL;
  4223. goto exit;
  4224. }
  4225. hr = _GetRequestHeader(&m_op.rResponse.rPostInfo.pszLocation, HTTP_QUERY_LOCATION);
  4226. exit:
  4227. return hr;
  4228. }
  4229. // --------------------------------------------------------------------------------
  4230. // CHTTPMailTransport::ProcessXMLResponse
  4231. // --------------------------------------------------------------------------------
  4232. HRESULT CHTTPMailTransport::ProcessXMLResponse(void)
  4233. {
  4234. HRESULT hr = S_OK;
  4235. BOOL bRead;
  4236. LPSTR pszBody = NULL;
  4237. DWORD cbLength = 0;
  4238. CByteStream *pLogStream = NULL;
  4239. BOOL fFoundBytes = FALSE;
  4240. if (m_pLogFile && !m_op.fLoggedResponse)
  4241. pLogStream = new CByteStream();
  4242. // we only parse xml if the response is a 207 (multistatus)
  4243. if (m_op.dwHttpStatus != 207)
  4244. goto exit;
  4245. // create the xml parser
  4246. if (FAILED(hr = _CreateXMLParser()))
  4247. goto exit;
  4248. if (!MemAlloc((void **)&pszBody, HTTPMAIL_BUFSIZE))
  4249. {
  4250. hr = E_OUTOFMEMORY;
  4251. goto exit;
  4252. }
  4253. do
  4254. {
  4255. FAIL_ABORT;
  4256. bRead = ReadBytes(pszBody, HTTPMAIL_BUFSIZE, &cbLength);
  4257. if (0 == cbLength)
  4258. {
  4259. if (fFoundBytes)
  4260. {
  4261. // parse any remaining bytes in the parser's buffer
  4262. if (FAILED(hr = m_pParser->PushData(NULL, 0, TRUE)))
  4263. goto exit;
  4264. if (FAILED(hr = m_pParser->Run(-1)))
  4265. goto exit;
  4266. }
  4267. break;
  4268. }
  4269. fFoundBytes = TRUE;
  4270. // if logging, write the block into the log stream
  4271. if (pLogStream)
  4272. pLogStream->Write(pszBody, cbLength, NULL);
  4273. if (FAILED(hr = m_pParser->PushData(pszBody, cbLength, FALSE)))
  4274. goto exit;
  4275. if (FAILED(hr = m_pParser->Run(-1)))
  4276. {
  4277. if (hr == E_PENDING)
  4278. hr = S_OK;
  4279. else
  4280. goto exit;
  4281. }
  4282. } while (TRUE);
  4283. exit:
  4284. SafeMemFree(pszBody);
  4285. if (pLogStream)
  4286. {
  4287. LPSTR pszLog = NULL;
  4288. DWORD dwLog = 0;
  4289. pLogStream->HrAcquireStringA(&dwLog, &pszLog, ACQ_DISPLACE);
  4290. _LogResponse(pszLog, dwLog);
  4291. SafeMemFree(pszLog);
  4292. delete pLogStream;
  4293. }
  4294. if (m_pParser)
  4295. m_pParser->Reset();
  4296. return hr;
  4297. }
  4298. // --------------------------------------------------------------------------------
  4299. // CHTTPMailTransport::GeneratePropFindXML
  4300. // --------------------------------------------------------------------------------
  4301. HRESULT CHTTPMailTransport::GeneratePropFindXML(void)
  4302. {
  4303. HRESULT hr = S_OK;
  4304. LPSTR pszXML = NULL;
  4305. IxpAssert(NULL == m_op.pvData && 0 == m_op.cbDataLen);
  4306. IxpAssert(NULL != m_op.pPropFindRequest);
  4307. if (FAILED(hr = m_op.pPropFindRequest->GenerateXML(&pszXML)))
  4308. goto exit;
  4309. m_op.pvData = pszXML;
  4310. m_op.cbDataLen = lstrlen(pszXML);
  4311. exit:
  4312. return hr;
  4313. }
  4314. // --------------------------------------------------------------------------------
  4315. // CHTTPMailTransport::AddDepthHeader
  4316. // --------------------------------------------------------------------------------
  4317. HRESULT CHTTPMailTransport::AddDepthHeader(void)
  4318. {
  4319. HRESULT hr = S_OK;
  4320. char szDepthHeader[64];
  4321. if (0 != m_op.dwDepth && !!(m_op.dwRHFlags & RH_NOROOT))
  4322. {
  4323. if (DEPTH_INFINITY == m_op.dwDepth)
  4324. StrCpyN(szDepthHeader, c_szDepthInfinityNoRootHeader, ARRAYSIZE(szDepthHeader));
  4325. else
  4326. wnsprintf(szDepthHeader, ARRAYSIZE(szDepthHeader), c_szDepthNoRootHeader, m_op.dwDepth);
  4327. }
  4328. else
  4329. {
  4330. if (DEPTH_INFINITY == m_op.dwDepth)
  4331. StrCpyN(szDepthHeader, c_szDepthInfinityHeader, ARRAYSIZE(szDepthHeader));
  4332. else
  4333. wnsprintf(szDepthHeader, ARRAYSIZE(szDepthHeader), c_szDepthHeader, m_op.dwDepth);
  4334. }
  4335. if (!HttpAddRequestHeaders(m_op.hRequest, szDepthHeader, lstrlen(szDepthHeader), HTTP_ADDREQ_FLAG_ADD))
  4336. {
  4337. _HrThunkConnectionError();
  4338. hr = E_FAIL;
  4339. }
  4340. return hr;
  4341. }
  4342. // --------------------------------------------------------------------------------
  4343. // CHTTPMailTransport::GeneratePropPatchXML
  4344. // --------------------------------------------------------------------------------
  4345. HRESULT CHTTPMailTransport::GeneratePropPatchXML(void)
  4346. {
  4347. HRESULT hr = S_OK;
  4348. LPSTR pszXML = NULL;
  4349. IxpAssert(NULL == m_op.pvData && 0 == m_op.cbDataLen);
  4350. IxpAssert(NULL != m_op.pPropPatchRequest);
  4351. if (FAILED(hr = m_op.pPropPatchRequest->GenerateXML(&pszXML)))
  4352. goto exit;
  4353. m_op.pvData = pszXML;
  4354. m_op.cbDataLen = lstrlen(pszXML);
  4355. exit:
  4356. return hr;
  4357. }
  4358. // --------------------------------------------------------------------------------
  4359. // CHTTPMailTransport::ProcessCreatedResponse
  4360. // --------------------------------------------------------------------------------
  4361. HRESULT CHTTPMailTransport::ProcessCreatedResponse(void)
  4362. {
  4363. HRESULT hr = S_OK;
  4364. if (m_pLogFile && !m_op.fLoggedResponse)
  4365. _LogResponse(NULL, 0);
  4366. if (HTTP_STATUS_CREATED != m_op.dwHttpStatus)
  4367. {
  4368. _HrThunkConnectionError();
  4369. hr = E_FAIL;
  4370. }
  4371. return hr;
  4372. }
  4373. // --------------------------------------------------------------------------------
  4374. // CHTTPMailTransport::AddCommonHeaders
  4375. // --------------------------------------------------------------------------------
  4376. HRESULT CHTTPMailTransport::AddCommonHeaders(void)
  4377. {
  4378. HRESULT hr = S_OK;
  4379. CHAR szHeader[CCHMAX_RES];
  4380. if (!!(RH_ALLOWRENAME & m_op.dwRHFlags))
  4381. {
  4382. if (FAILED(hr = _AddRequestHeader(c_szAllowRenameHeader)))
  4383. goto exit;
  4384. }
  4385. if (!!(RH_TRANSLATEFALSE & m_op.dwRHFlags))
  4386. {
  4387. if (FAILED(hr = _AddRequestHeader(c_szTranslateFalseHeader)))
  4388. goto exit;
  4389. }
  4390. if (!!(RH_TRANSLATETRUE & m_op.dwRHFlags))
  4391. {
  4392. if (FAILED(hr = _AddRequestHeader(c_szTranslateTrueHeader)))
  4393. goto exit;
  4394. }
  4395. if (!!(RH_XMLCONTENTTYPE & m_op.dwRHFlags))
  4396. {
  4397. IxpAssert(NULL == m_op.pszContentType);
  4398. m_op.pszContentType = PszDupA(c_szXmlContentType);
  4399. if (NULL == m_op.pszContentType)
  4400. {
  4401. hr = TrapError(E_OUTOFMEMORY);
  4402. goto exit;
  4403. }
  4404. if (FAILED(hr = AddContentTypeHeader()))
  4405. goto exit;
  4406. }
  4407. if (!!(RH_MESSAGECONTENTTYPE & m_op.dwRHFlags))
  4408. {
  4409. IxpAssert(NULL == m_op.pszContentType);
  4410. m_op.pszContentType = PszDupA(c_szMailContentType);
  4411. if (NULL == m_op.pszContentType)
  4412. {
  4413. hr = TrapError(E_OUTOFMEMORY);
  4414. goto exit;
  4415. }
  4416. if (FAILED(hr = AddContentTypeHeader()))
  4417. goto exit;
  4418. }
  4419. if (!!(RH_SMTPMESSAGECONTENTTYPE & m_op.dwRHFlags))
  4420. {
  4421. IxpAssert(NULL == m_op.pszContentType);
  4422. m_op.pszContentType = PszDupA(c_szSmtpMessageContentType);
  4423. if (NULL == m_op.pszContentType)
  4424. {
  4425. hr = TrapError(E_OUTOFMEMORY);
  4426. goto exit;
  4427. }
  4428. if (FAILED(hr = AddContentTypeHeader()))
  4429. goto exit;
  4430. }
  4431. if (!!(RH_BRIEF & m_op.dwRHFlags))
  4432. {
  4433. if (FAILED(hr = _AddRequestHeader(c_szBriefHeader)))
  4434. goto exit;
  4435. }
  4436. if (!!(RH_SAVEINSENTTRUE & m_op.dwRHFlags))
  4437. {
  4438. FAIL_EXIT(hr = _AddRequestHeader(c_szSaveInSentTrue));
  4439. }
  4440. if (!!(RH_SAVEINSENTFALSE & m_op.dwRHFlags))
  4441. {
  4442. FAIL_EXIT(hr = _AddRequestHeader(c_szSaveInSentFalse));
  4443. }
  4444. if (!!(RH_ROOTTIMESTAMP & m_op.dwRHFlags))
  4445. {
  4446. wnsprintf(szHeader, ARRAYSIZE(szHeader), c_szRootTimeStampHeader, m_op.pszRootTimeStamp, m_op.pszFolderTimeStamp);
  4447. FAIL_EXIT(hr = _AddRequestHeader(szHeader));
  4448. }
  4449. if (!!(RH_FOLDERTIMESTAMP & m_op.dwRHFlags))
  4450. {
  4451. wnsprintf(szHeader, ARRAYSIZE(szHeader), c_szFolderTimeStampHeader, m_op.pszFolderTimeStamp);
  4452. FAIL_EXIT(hr = _AddRequestHeader(szHeader));
  4453. }
  4454. // Fix for 88820
  4455. if (!!(RH_ADDCHARSET & m_op.dwRHFlags))
  4456. {
  4457. CODEPAGEINFO CodePageInfo;
  4458. MimeOleGetCodePageInfo(CP_ACP, &CodePageInfo);
  4459. *szHeader = 0;
  4460. wnsprintf(szHeader, ARRAYSIZE(szHeader), c_szAcceptCharset, CodePageInfo.szWebCset);
  4461. FAIL_EXIT(hr = _AddRequestHeader(szHeader));
  4462. }
  4463. // end of fix
  4464. exit:
  4465. return hr;
  4466. }
  4467. // CHTTPMailTransport::AddCharsetLine
  4468. // --------------------------------------------------------------------------------
  4469. HRESULT CHTTPMailTransport::AddCharsetLine(void)
  4470. {
  4471. HRESULT hr = S_OK;
  4472. CHAR szHeader[CCHMAX_RES];
  4473. CODEPAGEINFO CodePageInfo;
  4474. MimeOleGetCodePageInfo(CP_ACP, &CodePageInfo);
  4475. *szHeader = 0;
  4476. wnsprintf(szHeader, ARRAYSIZE(szHeader), c_szAcceptCharset, CodePageInfo.szWebCset);
  4477. hr = _AddRequestHeader(szHeader);
  4478. return hr;
  4479. }
  4480. // --------------------------------------------------------------------------------
  4481. // CHTTPMailTransport::AddDestinationHeader
  4482. // --------------------------------------------------------------------------------
  4483. HRESULT CHTTPMailTransport::AddDestinationHeader(void)
  4484. {
  4485. HRESULT hr = S_OK;
  4486. ULONG cchSize = (lstrlen(c_szDestinationHeader) + lstrlen(m_op.pszDestination) + 1);
  4487. LPSTR pszDestHeader = NULL;
  4488. if (!MemAlloc((void **)&pszDestHeader, cchSize * sizeof(pszDestHeader[0])))
  4489. {
  4490. hr = E_OUTOFMEMORY;
  4491. goto exit;
  4492. }
  4493. wnsprintf(pszDestHeader, cchSize, "%s%s", c_szDestinationHeader, m_op.pszDestination);
  4494. hr = _AddRequestHeader(pszDestHeader);
  4495. exit:
  4496. SafeMemFree(pszDestHeader);
  4497. return hr;
  4498. }
  4499. // --------------------------------------------------------------------------------
  4500. // CHTTPMailTransport::AddContentTypeHeader
  4501. // --------------------------------------------------------------------------------
  4502. HRESULT CHTTPMailTransport::AddContentTypeHeader(void)
  4503. {
  4504. HRESULT hr = S_OK;
  4505. ULONG cchSize;
  4506. LPSTR pszContentTypeHeader = NULL;
  4507. if (NULL == m_op.pszContentType)
  4508. goto exit;
  4509. cchSize = lstrlen(c_szContentTypeHeader) + lstrlen(m_op.pszContentType) + 1;
  4510. if (!MemAlloc((void **)&pszContentTypeHeader, cchSize * sizeof(pszContentTypeHeader[0])))
  4511. {
  4512. hr = E_OUTOFMEMORY;
  4513. goto exit;
  4514. }
  4515. wnsprintf(pszContentTypeHeader, cchSize, "%s%s", c_szContentTypeHeader, m_op.pszContentType);
  4516. hr = _AddRequestHeader(pszContentTypeHeader);
  4517. exit:
  4518. SafeMemFree(pszContentTypeHeader);
  4519. return hr;
  4520. }
  4521. // --------------------------------------------------------------------------------
  4522. // CHTTPMailTransport::ProcessLocationResponse
  4523. // --------------------------------------------------------------------------------
  4524. HRESULT CHTTPMailTransport::ProcessLocationResponse(void)
  4525. {
  4526. _GetRequestHeader(&m_op.rResponse.rCopyMoveInfo.pszLocation, HTTP_QUERY_LOCATION);
  4527. return S_OK;
  4528. }
  4529. // --------------------------------------------------------------------------------
  4530. // CHTTPMailTransport::InitBCopyMove
  4531. // --------------------------------------------------------------------------------
  4532. HRESULT CHTTPMailTransport::InitBCopyMove(void)
  4533. {
  4534. HRESULT hr = S_OK;
  4535. // allocate a buffer to contain the response list
  4536. if (!MemAlloc((void **)&m_op.rResponse.rBCopyMoveList.prgBCopyMove,
  4537. BCOPYMOVE_MAXRESPONSES * sizeof(HTTPMAILBCOPYMOVE)))
  4538. {
  4539. hr = TrapError(E_OUTOFMEMORY);
  4540. goto exit;
  4541. }
  4542. ZeroMemory(m_op.rResponse.rBCopyMoveList.prgBCopyMove, BCOPYMOVE_MAXRESPONSES * sizeof(HTTPMAILBCOPYMOVE));
  4543. exit:
  4544. return hr;
  4545. }
  4546. // --------------------------------------------------------------------------------
  4547. // CHTTPMailTransport::InitRootProps
  4548. // --------------------------------------------------------------------------------
  4549. HRESULT CHTTPMailTransport::InitRootProps(void)
  4550. {
  4551. HRESULT hr = S_OK;
  4552. // it is possible to end up here, and have the root props
  4553. // if the caller either forced the request to go async,
  4554. // or queued up multiple requests for root props.
  4555. if (GetHasRootProps())
  4556. {
  4557. // finalize the root props, and return an error.
  4558. // this will generate the response to the caller,
  4559. // and fall out of the fsm.
  4560. FinalizeRootProps();
  4561. hr = E_FAIL;
  4562. }
  4563. else
  4564. {
  4565. IxpAssert(NULL == m_op.pPropFindRequest);
  4566. m_op.pPropFindRequest = new CPropFindRequest();
  4567. if (NULL == m_op.pPropFindRequest)
  4568. {
  4569. hr = E_OUTOFMEMORY;
  4570. goto exit;
  4571. }
  4572. hr = XP_CREATE_PROPFIND_REQUEST(ROOTPROPS, m_op.pPropFindRequest);
  4573. }
  4574. exit:
  4575. return hr;
  4576. }
  4577. // --------------------------------------------------------------------------------
  4578. // CHTTPMailTransport::FinalizeRootProps
  4579. // --------------------------------------------------------------------------------
  4580. HRESULT CHTTPMailTransport::FinalizeRootProps(void)
  4581. {
  4582. HRESULT hr = S_OK;
  4583. m_fHasRootProps = TRUE;
  4584. m_op.rResponse.rGetPropInfo.type = m_op.tyProp;
  4585. if (m_op.tyProp != HTTPMAIL_PROP_MAXPOLLINGINTERVAL)
  4586. {
  4587. m_op.rResponse.rIxpResult.hrResult = GetProperty(m_op.tyProp, &m_op.rResponse.rGetPropInfo.pszProp);
  4588. }
  4589. else
  4590. {
  4591. m_op.rResponse.rIxpResult.hrResult = GetPropertyDw(m_op.tyProp, &m_op.rResponse.rGetPropInfo.dwProp);
  4592. }
  4593. hr = _HrThunkResponse(TRUE);
  4594. SafeMemFree(m_op.rResponse.rGetPropInfo.pszProp);
  4595. return hr;
  4596. }
  4597. // --------------------------------------------------------------------------------
  4598. // CHTTPMailTransport::InitMemberInfo
  4599. // --------------------------------------------------------------------------------
  4600. HRESULT CHTTPMailTransport::InitMemberInfo(void)
  4601. {
  4602. HRESULT hr = S_OK;
  4603. IxpAssert(NULL == m_op.pPropFindRequest);
  4604. // create the propfind request
  4605. m_op.pPropFindRequest = new CPropFindRequest();
  4606. if (NULL == m_op.pPropFindRequest)
  4607. {
  4608. hr = TrapError(E_OUTOFMEMORY);
  4609. goto exit;
  4610. }
  4611. // always add the common properties
  4612. FAIL_EXIT(hr = XP_CREATE_PROPFIND_REQUEST(HTTPMEMBERINFO_COMMON, m_op.pPropFindRequest));
  4613. // if the client requested folder props, add that schema
  4614. if (!!(m_op.dwMIFlags & HTTP_MEMBERINFO_FOLDERPROPS))
  4615. FAIL_EXIT(hr = XP_CREATE_PROPFIND_REQUEST(HTTPMEMBERINFO_FOLDER, m_op.pPropFindRequest));
  4616. // if the client requested message props, add that schema
  4617. if (!!(m_op.dwMIFlags & HTTP_MEMBERINFO_MESSAGEPROPS))
  4618. FAIL_EXIT(hr = XP_CREATE_PROPFIND_REQUEST(HTTPMEMBERINFO_MESSAGE, m_op.pPropFindRequest));
  4619. // allocate a buffer to contain the response list
  4620. if (!MemAlloc((void **)&m_op.rResponse.rMemberInfoList.prgMemberInfo,
  4621. MEMBERINFO_MAXRESPONSES * sizeof(HTTPMEMBERINFO)))
  4622. {
  4623. hr = TrapError(E_OUTOFMEMORY);
  4624. goto exit;
  4625. }
  4626. ZeroMemory(m_op.rResponse.rMemberInfoList.prgMemberInfo, MEMBERINFO_MAXRESPONSES * sizeof(HTTPMEMBERINFO));
  4627. exit:
  4628. return hr;
  4629. }
  4630. // --------------------------------------------------------------------------------
  4631. // CHTTPMailTransport::InitMemberError
  4632. // --------------------------------------------------------------------------------
  4633. HRESULT CHTTPMailTransport::InitMemberError(void)
  4634. {
  4635. HRESULT hr = S_OK;
  4636. // allocate a buffer to contain the response list
  4637. if (!MemAlloc((void **)&m_op.rResponse.rMemberErrorList.prgMemberError,
  4638. MEMBERERROR_MAXRESPONSES * sizeof(HTTPMEMBERERROR)))
  4639. {
  4640. hr = TrapError(E_OUTOFMEMORY);
  4641. goto exit;
  4642. }
  4643. ZeroMemory(m_op.rResponse.rMemberErrorList.prgMemberError, MEMBERERROR_MAXRESPONSES * sizeof(HTTPMEMBERERROR));
  4644. exit:
  4645. return hr;
  4646. }
  4647. // --------------------------------------------------------------------------------
  4648. // InitListContacts
  4649. // --------------------------------------------------------------------------------
  4650. HRESULT CHTTPMailTransport::InitListContacts(void)
  4651. {
  4652. HRESULT hr = S_OK;
  4653. IxpAssert(NULL == m_op.pPropFindRequest);
  4654. m_op.pPropFindRequest = new CPropFindRequest();
  4655. if (NULL == m_op.pPropFindRequest)
  4656. {
  4657. hr = E_OUTOFMEMORY;
  4658. goto exit;
  4659. }
  4660. hr = XP_CREATE_PROPFIND_REQUEST(HTTPCONTACTID, m_op.pPropFindRequest);
  4661. if (FAILED(hr))
  4662. goto exit;
  4663. // allocate a buffer to contain the response list
  4664. if (!MemAlloc((void **)&m_op.rResponse.rContactIdList.prgContactId,
  4665. LISTCONTACTS_MAXRESPONSES * sizeof(HTTPCONTACTID)))
  4666. {
  4667. hr = E_OUTOFMEMORY;
  4668. goto exit;
  4669. }
  4670. ZeroMemory(m_op.rResponse.rContactIdList.prgContactId, LISTCONTACTS_MAXRESPONSES * sizeof(HTTPCONTACTID));
  4671. exit:
  4672. return hr;
  4673. }
  4674. // --------------------------------------------------------------------------------
  4675. // CHTTPMailTransport::InitContactInfo
  4676. // --------------------------------------------------------------------------------
  4677. HRESULT CHTTPMailTransport::InitContactInfo(void)
  4678. {
  4679. HRESULT hr = S_OK;
  4680. IxpAssert(NULL == m_op.pPropFindRequest);
  4681. m_op.pPropFindRequest = new CPropFindRequest();
  4682. if (NULL == m_op.pPropFindRequest)
  4683. {
  4684. hr = E_OUTOFMEMORY;
  4685. goto exit;
  4686. }
  4687. hr = XP_CREATE_PROPFIND_REQUEST(HTTPCONTACTINFO, m_op.pPropFindRequest);
  4688. if (FAILED(hr))
  4689. goto exit;
  4690. // allocate a buffer to contain the response list
  4691. if (!MemAlloc((void **)&m_op.rResponse.rContactInfoList.prgContactInfo,
  4692. CONTACTINFO_MAXRESPONSES * sizeof(HTTPCONTACTINFO)))
  4693. {
  4694. hr = E_OUTOFMEMORY;
  4695. goto exit;
  4696. }
  4697. ZeroMemory(m_op.rResponse.rContactInfoList.prgContactInfo, CONTACTINFO_MAXRESPONSES * sizeof(HTTPCONTACTINFO));
  4698. exit:
  4699. return hr;
  4700. }
  4701. // --------------------------------------------------------------------------------
  4702. // CHTTPMailTransport::ProcessPostContactResponse
  4703. // --------------------------------------------------------------------------------
  4704. HRESULT CHTTPMailTransport::ProcessPostContactResponse(void)
  4705. {
  4706. HRESULT hr = S_OK;
  4707. DWORD dwSize = MAX_PATH;
  4708. LPSTR pszLocation = NULL;
  4709. DWORD dwContext;
  4710. int iState;
  4711. if (m_pLogFile && !m_op.fLoggedResponse)
  4712. _LogResponse(NULL, 0);
  4713. if (HTTP_STATUS_CREATED != m_op.dwHttpStatus)
  4714. {
  4715. _HrThunkConnectionError();
  4716. hr = E_FAIL;
  4717. goto exit;
  4718. }
  4719. if (FAILED(hr = _GetRequestHeader(&pszLocation, HTTP_QUERY_LOCATION)))
  4720. goto exit;
  4721. // Prepare for the next phase
  4722. // save the context and the state
  4723. dwContext = m_op.dwContext;
  4724. iState = m_op.iState;
  4725. FreeOperation();
  4726. // restore context, state, parsing funcs, etc.
  4727. m_op.rResponse.command = HTTPMAIL_POSTCONTACT;
  4728. m_op.pszUrl = pszLocation;
  4729. pszLocation = NULL;
  4730. m_op.dwContext = dwContext;
  4731. m_op.pfnState = c_rgpfnPostContact;
  4732. m_op.cState = ARRAYSIZE(c_rgpfnPostContact);
  4733. m_op.iState = iState;
  4734. m_op.pParseFuncs = c_rgpfnPostOrPatchContactParse;
  4735. m_op.dwDepth = 0;
  4736. m_op.dwRHFlags = (RH_XMLCONTENTTYPE | RH_BRIEF);
  4737. m_op.rResponse.rPostContactInfo.pszHref = PszDupA(m_op.pszUrl);
  4738. if (NULL == m_op.rResponse.rPostContactInfo.pszHref)
  4739. hr = E_OUTOFMEMORY;
  4740. exit:
  4741. SafeMemFree(pszLocation);
  4742. return hr;
  4743. }
  4744. // --------------------------------------------------------------------------------
  4745. // CHTTPMailTransport::ProcessPatchContactResponse
  4746. // --------------------------------------------------------------------------------
  4747. HRESULT CHTTPMailTransport::ProcessPatchContactResponse(void)
  4748. {
  4749. HRESULT hr = S_OK;
  4750. LPSTR pszUrl = NULL;
  4751. DWORD dwContext;
  4752. int iState;
  4753. IHTTPMailCallback *pCallback = NULL;
  4754. // REVIEW: we should be handling multistatus responses
  4755. if (200 > m_op.dwHttpStatus || 300 < m_op.dwHttpStatus)
  4756. {
  4757. _HrThunkConnectionError();
  4758. hr = E_FAIL;
  4759. goto exit;
  4760. }
  4761. // prepare for the next phase
  4762. // save the context and the state
  4763. pszUrl = m_op.pszUrl;
  4764. m_op.pszUrl = NULL;
  4765. dwContext = m_op.dwContext;
  4766. iState = m_op.iState;
  4767. FreeOperation();
  4768. // restore context, etc.
  4769. m_op.rResponse.command = HTTPMAIL_PATCHCONTACT;
  4770. m_op.pszUrl = pszUrl;
  4771. m_op.dwContext = dwContext;
  4772. m_op.pfnState = c_rgpfnPatchContact;
  4773. m_op.cState = ARRAYSIZE(c_rgpfnPatchContact);
  4774. m_op.iState = iState;
  4775. m_op.pParseFuncs = c_rgpfnPostOrPatchContactParse; // share the post contact parse funcs
  4776. m_op.dwDepth = 0;
  4777. m_op.rResponse.rPatchContactInfo.pszHref = PszDupA(m_op.pszUrl);
  4778. m_op.dwRHFlags = (RH_BRIEF | RH_XMLCONTENTTYPE);
  4779. pszUrl = NULL;
  4780. exit:
  4781. return hr;
  4782. }
  4783. // --------------------------------------------------------------------------------
  4784. // XML Parsing Callbacks
  4785. // --------------------------------------------------------------------------------
  4786. // --------------------------------------------------------------------------------
  4787. // CHTTPMailTransport::CreateElement
  4788. // --------------------------------------------------------------------------------
  4789. HRESULT CHTTPMailTransport::CreateElement(
  4790. CXMLNamespace *pBaseNamespace,
  4791. const WCHAR *pwcText,
  4792. ULONG ulLen,
  4793. ULONG ulNamespaceLen,
  4794. BOOL fTerminal)
  4795. {
  4796. // increment the stack pointer and, if there is room on the stack,
  4797. // push the element type
  4798. if (!fTerminal)
  4799. {
  4800. if (m_op.dwStackDepth < ELE_STACK_CAPACITY)
  4801. {
  4802. m_op.rgEleStack[m_op.dwStackDepth].ele = XMLElementToID(pwcText, ulLen, ulNamespaceLen, m_op.pTopNamespace);
  4803. m_op.rgEleStack[m_op.dwStackDepth].pBaseNamespace = pBaseNamespace;
  4804. m_op.rgEleStack[m_op.dwStackDepth].fBeganChildren = FALSE;
  4805. m_op.rgEleStack[m_op.dwStackDepth].pTextBuffer = NULL;
  4806. }
  4807. ++m_op.dwStackDepth;
  4808. }
  4809. return S_OK;
  4810. }
  4811. // --------------------------------------------------------------------------------
  4812. // CHTTPMailTransport::EndChildren
  4813. // --------------------------------------------------------------------------------
  4814. HRESULT CHTTPMailTransport::EndChildren(void)
  4815. {
  4816. HRESULT hr = S_OK;
  4817. // decrement the stack pointer
  4818. if (m_op.dwStackDepth <= ELE_STACK_CAPACITY)
  4819. {
  4820. LPPCDATABUFFER pTextBuffer = m_op.rgEleStack[m_op.dwStackDepth - 1].pTextBuffer;
  4821. if (pTextBuffer)
  4822. {
  4823. hr = (this->*(m_op.pParseFuncs->pfnHandleText))(pTextBuffer->pwcText, pTextBuffer->ulLen);
  4824. _ReleaseTextBuffer(pTextBuffer);
  4825. }
  4826. else
  4827. hr = (this->*(m_op.pParseFuncs->pfnHandleText))(NULL, 0);
  4828. // unroll the namespace
  4829. PopNamespaces(m_op.rgEleStack[m_op.dwStackDepth - 1].pBaseNamespace);
  4830. }
  4831. --m_op.dwStackDepth;
  4832. return hr;
  4833. }
  4834. // --------------------------------------------------------------------------------
  4835. // CHTTPMailTransport::BCopyMove_HandleText
  4836. // --------------------------------------------------------------------------------
  4837. HRESULT CHTTPMailTransport::BCopyMove_HandleText(const WCHAR *pwcText, ULONG ulLen)
  4838. {
  4839. HRESULT hr = S_OK;
  4840. LPHTTPMAILBCOPYMOVE pInfo = &m_op.rResponse.rBCopyMoveList.prgBCopyMove[m_op.rResponse.rBCopyMoveList.cBCopyMove];
  4841. return XP_BIND_TO_STRUCT(HTTPMAILBCOPYMOVE, pwcText, ulLen, pInfo, NULL);
  4842. }
  4843. // --------------------------------------------------------------------------------
  4844. // CHTTPMailTransport::BCopyMove_EndChildren
  4845. // --------------------------------------------------------------------------------
  4846. HRESULT CHTTPMailTransport::BCopyMove_EndChildren(void)
  4847. {
  4848. HRESULT hr = S_OK;
  4849. if (StackTop(HMELE_DAV_RESPONSE) && VALIDSTACK(c_rgPropFindResponseStack))
  4850. {
  4851. // clear the prop flags, since we are about to increment the count
  4852. m_op.dwPropFlags = NOFLAGS;
  4853. // increment the list count and, if we've hit the max, send the notification
  4854. if (BCOPYMOVE_MAXRESPONSES == ++m_op.rResponse.rBCopyMoveList.cBCopyMove)
  4855. {
  4856. if (FAILED(hr = _HrThunkResponse(FALSE)))
  4857. goto exit;
  4858. FreeBCopyMoveList();
  4859. }
  4860. }
  4861. hr = EndChildren();
  4862. exit:
  4863. return hr;
  4864. }
  4865. // --------------------------------------------------------------------------------
  4866. // CHTTPMailTransport::PropFind_HandleText
  4867. // --------------------------------------------------------------------------------
  4868. HRESULT CHTTPMailTransport::PropFind_HandleText(const WCHAR *pwcText, ULONG ulLen)
  4869. {
  4870. HRESULT hr = S_OK;
  4871. LPSTR pszStatus = NULL;
  4872. // the only element that is handled here is <status>
  4873. if (StackTop(HMELE_DAV_STATUS) && VALIDSTACK(c_rgPropFindStatusStack))
  4874. {
  4875. m_op.fFoundStatus = TRUE;
  4876. m_op.dwStatus = 0;
  4877. if (SUCCEEDED(hr = AllocStrFromStrNW(pwcText, ulLen, &pszStatus)) && NULL != pszStatus)
  4878. {
  4879. // ignore errors parsing the status...we treat malformed status
  4880. // as status 0, which is an error
  4881. HrParseHTTPStatus(pszStatus, &m_op.dwStatus);
  4882. }
  4883. }
  4884. SafeMemFree(pszStatus);
  4885. return hr;
  4886. }
  4887. // --------------------------------------------------------------------------------
  4888. // CHTTPMailTransport::RootProps_HandleText
  4889. // --------------------------------------------------------------------------------
  4890. HRESULT CHTTPMailTransport::RootProps_HandleText(const WCHAR *pwcText, ULONG ulLen)
  4891. {
  4892. HRESULT hr = S_OK;
  4893. BOOL fWasBound = FALSE;
  4894. hr = XP_BIND_TO_STRUCT(ROOTPROPS, pwcText, ulLen, &m_rootProps, &fWasBound);
  4895. if (FAILED(hr))
  4896. goto exit;
  4897. if (!fWasBound)
  4898. hr = PropFind_HandleText(pwcText, ulLen);
  4899. exit:
  4900. return hr;
  4901. }
  4902. // --------------------------------------------------------------------------------
  4903. // CHTTPMailTransport::RootProps_EndChildren
  4904. // --------------------------------------------------------------------------------
  4905. HRESULT CHTTPMailTransport::RootProps_EndChildren(void)
  4906. {
  4907. // if we are popping a prop node with a bad status code,
  4908. // free any data associated with the node
  4909. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  4910. {
  4911. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  4912. XP_FREE_STRUCT(ROOTPROPS, &m_rootProps, &m_op.dwPropFlags);
  4913. m_op.fFoundStatus = FALSE;
  4914. m_op.dwPropFlags = NOFLAGS;
  4915. }
  4916. return EndChildren();
  4917. }
  4918. // --------------------------------------------------------------------------------
  4919. // CHTTPMailTransport::MemberInfo_HandleText
  4920. // --------------------------------------------------------------------------------
  4921. HRESULT CHTTPMailTransport::MemberInfo_HandleText(const WCHAR *pwcText, ULONG ulLen)
  4922. {
  4923. HRESULT hr = S_OK;
  4924. LPHTTPMEMBERINFO pInfo = &m_op.rResponse.rMemberInfoList.prgMemberInfo[m_op.rResponse.rMemberInfoList.cMemberInfo];
  4925. BOOL fWasBound = FALSE;
  4926. FAIL_EXIT(hr = XP_BIND_TO_STRUCT(HTTPMEMBERINFO, pwcText, ulLen, pInfo, &fWasBound));
  4927. if (!fWasBound)
  4928. hr = PropFind_HandleText(pwcText, ulLen);
  4929. exit:
  4930. return hr;
  4931. }
  4932. // --------------------------------------------------------------------------------
  4933. // CHTTPMailTransport::MemberInfo_EndChildren
  4934. // --------------------------------------------------------------------------------
  4935. HRESULT CHTTPMailTransport::MemberInfo_EndChildren(void)
  4936. {
  4937. HRESULT hr = S_OK;
  4938. // if we are popping a propstat node with a bad status code,
  4939. // free any data associated with the node
  4940. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  4941. {
  4942. // grab a pointer to the folder info we are accumulating
  4943. LPHTTPMEMBERINFO pInfo =
  4944. &m_op.rResponse.rMemberInfoList.prgMemberInfo[m_op.rResponse.rMemberInfoList.cMemberInfo];
  4945. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  4946. XP_FREE_STRUCT(HTTPMEMBERINFO, pInfo, &m_op.dwPropFlags);
  4947. m_op.fFoundStatus = FALSE;
  4948. m_op.dwPropFlags = NOFLAGS;
  4949. }
  4950. else if (StackTop(HMELE_DAV_RESPONSE) && VALIDSTACK(c_rgPropFindResponseStack))
  4951. {
  4952. // increment the list count and, if we've hit the max, send the notification
  4953. if (MEMBERINFO_MAXRESPONSES == ++m_op.rResponse.rMemberInfoList.cMemberInfo)
  4954. {
  4955. if (FAILED(hr = _HrThunkResponse(FALSE)))
  4956. goto exit;
  4957. FreeMemberInfoList();
  4958. }
  4959. }
  4960. hr = EndChildren();
  4961. exit:
  4962. return hr;
  4963. }
  4964. // --------------------------------------------------------------------------------
  4965. // CHTTPMailTransport::MemberError_HandleText
  4966. // --------------------------------------------------------------------------------
  4967. HRESULT CHTTPMailTransport::MemberError_HandleText(const WCHAR *pwcText, ULONG ulLen)
  4968. {
  4969. HRESULT hr = S_OK;
  4970. LPHTTPMEMBERERROR pInfo = &m_op.rResponse.rMemberErrorList.prgMemberError[m_op.rResponse.rMemberErrorList.cMemberError];
  4971. BOOL fWasBound = FALSE;
  4972. FAIL_EXIT(hr = XP_BIND_TO_STRUCT(HTTPMEMBERERROR, pwcText, ulLen, pInfo, &fWasBound));
  4973. if (!fWasBound)
  4974. hr = PropFind_HandleText(pwcText, ulLen);
  4975. exit:
  4976. return hr;
  4977. }
  4978. // --------------------------------------------------------------------------------
  4979. // CHTTPMailTransport::MemberError_EndChildren
  4980. // --------------------------------------------------------------------------------
  4981. HRESULT CHTTPMailTransport::MemberError_EndChildren(void)
  4982. {
  4983. HRESULT hr = S_OK;
  4984. // if we are popping a propstat node with a bad status code,
  4985. // free any data associated with the node
  4986. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  4987. {
  4988. // grab a pointer to the folder info we are accumulating
  4989. LPHTTPMEMBERERROR pInfo =
  4990. &m_op.rResponse.rMemberErrorList.prgMemberError[m_op.rResponse.rMemberErrorList.cMemberError];
  4991. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  4992. XP_FREE_STRUCT(HTTPMEMBERERROR, pInfo, &m_op.dwPropFlags);
  4993. m_op.fFoundStatus = FALSE;
  4994. m_op.dwPropFlags = NOFLAGS;
  4995. }
  4996. else if (StackTop(HMELE_DAV_RESPONSE) && VALIDSTACK(c_rgPropFindResponseStack))
  4997. {
  4998. // increment the list count and, if we've hit the max, send the notification
  4999. if (MEMBERERROR_MAXRESPONSES == ++m_op.rResponse.rMemberErrorList.cMemberError)
  5000. {
  5001. if (FAILED(hr = _HrThunkResponse(FALSE)))
  5002. goto exit;
  5003. FreeMemberErrorList();
  5004. }
  5005. }
  5006. hr = EndChildren();
  5007. exit:
  5008. return hr;
  5009. }
  5010. // --------------------------------------------------------------------------------
  5011. // CHTTPMailTransport::ListContacts_HandleText
  5012. // --------------------------------------------------------------------------------
  5013. HRESULT CHTTPMailTransport::ListContacts_HandleText(const WCHAR *pwcText, ULONG ulLen)
  5014. {
  5015. HRESULT hr = S_OK;
  5016. LPHTTPCONTACTID pId = &m_op.rResponse.rContactIdList.prgContactId[m_op.rResponse.rContactIdList.cContactId];
  5017. BOOL fWasBound = FALSE;
  5018. hr = XP_BIND_TO_STRUCT(HTTPCONTACTID, pwcText, ulLen, pId, &fWasBound);
  5019. if (FAILED(hr))
  5020. goto exit;
  5021. if (!fWasBound)
  5022. hr = PropFind_HandleText(pwcText, ulLen);
  5023. exit:
  5024. return hr;
  5025. }
  5026. // --------------------------------------------------------------------------------
  5027. // CHTTPMailTransport::ListContacts_EndChildren
  5028. // --------------------------------------------------------------------------------
  5029. HRESULT CHTTPMailTransport::ListContacts_EndChildren(void)
  5030. {
  5031. HRESULT hr = S_OK;
  5032. // if we are popping a propstat node with a bad status code,
  5033. // free any data associated with the node
  5034. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  5035. {
  5036. // grab a pointer to the contact id we are accumulating
  5037. LPHTTPCONTACTID pId = &m_op.rResponse.rContactIdList.prgContactId[m_op.rResponse.rContactIdList.cContactId];
  5038. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  5039. XP_FREE_STRUCT(HTTPCONTACTID, pId, &m_op.dwPropFlags);
  5040. m_op.fFoundStatus = FALSE;
  5041. m_op.dwPropFlags = NOFLAGS;
  5042. }
  5043. else if (StackTop(HMELE_DAV_RESPONSE) && VALIDSTACK(c_rgPropFindResponseStack))
  5044. {
  5045. // increment the list count and, if we've hit the max, send the notification
  5046. if (LISTCONTACTS_MAXRESPONSES == ++m_op.rResponse.rContactIdList.cContactId)
  5047. {
  5048. if (FAILED(hr = _HrThunkResponse(FALSE)))
  5049. goto exit;
  5050. FreeContactIdList();
  5051. }
  5052. }
  5053. hr = EndChildren();
  5054. exit:
  5055. return hr;
  5056. }
  5057. // --------------------------------------------------------------------------------
  5058. // CHTTPMailTransport::ContactInfo_HandleText
  5059. // --------------------------------------------------------------------------------
  5060. HRESULT CHTTPMailTransport::ContactInfo_HandleText(const WCHAR *pwcText, ULONG ulLen)
  5061. {
  5062. HRESULT hr = S_OK;
  5063. LPHTTPCONTACTINFO pInfo = &m_op.rResponse.rContactInfoList.prgContactInfo[m_op.rResponse.rContactInfoList.cContactInfo];
  5064. BOOL fWasBound = FALSE;
  5065. hr = XP_BIND_TO_STRUCT(HTTPCONTACTINFO, pwcText, ulLen, pInfo, &fWasBound);
  5066. if (FAILED(hr))
  5067. goto exit;
  5068. if (!fWasBound)
  5069. hr = PropFind_HandleText(pwcText, ulLen);
  5070. exit:
  5071. return hr;
  5072. }
  5073. // --------------------------------------------------------------------------------
  5074. // CHTTPMailTransport::ContactInfo_EndChildren
  5075. // --------------------------------------------------------------------------------
  5076. HRESULT CHTTPMailTransport::ContactInfo_EndChildren()
  5077. {
  5078. HRESULT hr = S_OK;
  5079. // if we are popping a propstat node with a bad status code,
  5080. // free any data associated with the node
  5081. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  5082. {
  5083. // grab a pointer to the contact id we are accumulating
  5084. LPHTTPCONTACTINFO pInfo = &m_op.rResponse.rContactInfoList.prgContactInfo[m_op.rResponse.rContactInfoList.cContactInfo];
  5085. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  5086. XP_FREE_STRUCT(HTTPCONTACTINFO, pInfo, &m_op.dwPropFlags);
  5087. m_op.fFoundStatus = FALSE;
  5088. m_op.dwPropFlags = NOFLAGS;
  5089. }
  5090. else if (StackTop(HMELE_DAV_RESPONSE) && VALIDSTACK(c_rgPropFindResponseStack))
  5091. {
  5092. // increment the list count and, if we've hit the max, send the notification
  5093. if (CONTACTINFO_MAXRESPONSES == ++m_op.rResponse.rContactInfoList.cContactInfo)
  5094. {
  5095. if (FAILED(hr = _HrThunkResponse(FALSE)))
  5096. goto exit;
  5097. FreeContactInfoList();
  5098. }
  5099. }
  5100. hr = EndChildren();
  5101. exit:
  5102. return hr;
  5103. }
  5104. // --------------------------------------------------------------------------------
  5105. // CHTTPMailTransport::PostOrPatchContact_HandleText
  5106. // --------------------------------------------------------------------------------
  5107. HRESULT CHTTPMailTransport::PostOrPatchContact_HandleText(const WCHAR *pwcText, ULONG ulLen)
  5108. {
  5109. HRESULT hr = S_OK;
  5110. LPHTTPCONTACTID pId = NULL;
  5111. BOOL fWasBound = FALSE;
  5112. if (HTTPMAIL_POSTCONTACT == m_op.rResponse.command)
  5113. pId = &m_op.rResponse.rPostContactInfo;
  5114. else if (HTTPMAIL_PATCHCONTACT == m_op.rResponse.command)
  5115. pId = &m_op.rResponse.rPatchContactInfo;
  5116. IxpAssert(pId);
  5117. hr = XP_BIND_TO_STRUCT(HTTPCONTACTID, pwcText, ulLen, pId, &fWasBound);
  5118. if (FAILED(hr))
  5119. goto exit;
  5120. if (!fWasBound)
  5121. hr = PropFind_HandleText(pwcText, ulLen);
  5122. exit:
  5123. return hr;
  5124. }
  5125. // --------------------------------------------------------------------------------
  5126. // CHTTPMailTransport::PostOrPatchContact_EndChildren
  5127. // --------------------------------------------------------------------------------
  5128. HRESULT CHTTPMailTransport::PostOrPatchContact_EndChildren(void)
  5129. {
  5130. HRESULT hr = S_OK;
  5131. // if we are popping a propstat node with a bad status code,
  5132. // free any data associated with the node
  5133. if (StackTop(HMELE_DAV_PROPSTAT) && VALIDSTACK(c_rgPropFindPropStatStack))
  5134. {
  5135. // grab a pointer to the contact id we are accumulating
  5136. LPHTTPCONTACTID pId = NULL;
  5137. if (HTTPMAIL_POSTCONTACT == m_op.rResponse.command)
  5138. pId = &m_op.rResponse.rPostContactInfo;
  5139. else if (HTTPMAIL_PATCHCONTACT == m_op.rResponse.command)
  5140. pId = &m_op.rResponse.rPatchContactInfo;
  5141. IxpAssert(pId);
  5142. if (!m_op.fFoundStatus || m_op.dwStatus != 200)
  5143. XP_FREE_STRUCT(HTTPCONTACTID, pId, &m_op.dwPropFlags);
  5144. m_op.fFoundStatus = FALSE;
  5145. m_op.dwPropFlags = NOFLAGS;
  5146. }
  5147. hr = EndChildren();
  5148. return hr;
  5149. }
  5150. // --------------------------------------------------------------------------------
  5151. // CHTTPMailTransport::_MemberInfo2
  5152. // --------------------------------------------------------------------------------
  5153. HRESULT CHTTPMailTransport::_MemberInfo2(LPCSTR pszPath,
  5154. MEMBERINFOFLAGS flags,
  5155. DWORD dwDepth,
  5156. BOOL fIncludeRoot,
  5157. DWORD dwContext,
  5158. LPHTTPQUEUEDOP *ppOp)
  5159. {
  5160. HRESULT hr = S_OK;
  5161. LPHTTPQUEUEDOP pOp = NULL;
  5162. if (!ppOp)
  5163. {
  5164. IF_FAILEXIT(hr = E_INVALIDARG);
  5165. }
  5166. if (NULL == pszPath)
  5167. return TrapError(E_INVALIDARG);
  5168. FAIL_CREATEWND;
  5169. #pragma prefast(suppress:11, "noise")
  5170. *ppOp = NULL;
  5171. if (FAILED(hr = AllocQueuedOperation(pszPath, NULL, 0, &pOp)))
  5172. goto exit;
  5173. pOp->command = HTTPMAIL_MEMBERINFO;
  5174. pOp->dwMIFlags = flags;
  5175. pOp->dwDepth = dwDepth;
  5176. pOp->dwContext = dwContext;
  5177. pOp->pfnState = c_rgpfnMemberInfo;
  5178. pOp->cState = ARRAYSIZE(c_rgpfnMemberInfo);
  5179. pOp->pParseFuncs = c_rgpfnMemberInfoParse;
  5180. pOp->dwRHFlags = (RH_BRIEF | RH_XMLCONTENTTYPE);
  5181. if (!fIncludeRoot)
  5182. pOp->dwRHFlags |= RH_NOROOT;
  5183. exit:
  5184. if (SUCCEEDED(hr))
  5185. {
  5186. #pragma prefast(suppress:11, "noise")
  5187. *ppOp = pOp;
  5188. }
  5189. return hr;
  5190. }
  5191. // --------------------------------------------------------------------------------
  5192. // CHTTPMailTransport::RootMemberInfo
  5193. // --------------------------------------------------------------------------------
  5194. STDMETHODIMP CHTTPMailTransport::RootMemberInfo(LPCSTR pszPath,
  5195. MEMBERINFOFLAGS flags,
  5196. DWORD dwDepth,
  5197. BOOL fIncludeRoot,
  5198. DWORD dwContext,
  5199. LPSTR pszRootTimeStamp,
  5200. LPSTR pszInboxTimeStamp)
  5201. {
  5202. HRESULT hr = S_OK;
  5203. LPHTTPQUEUEDOP pOp;
  5204. IF_FAILEXIT(hr = _MemberInfo2(pszPath, flags, dwDepth, fIncludeRoot, dwContext, &pOp));
  5205. pOp->dwRHFlags |= RH_ROOTTIMESTAMP | RH_ADDCHARSET;
  5206. pOp->pszRootTimeStamp = PszDupA(pszRootTimeStamp);
  5207. pOp->pszFolderTimeStamp = PszDupA(pszInboxTimeStamp);
  5208. QueueOperation(pOp);
  5209. exit:
  5210. return hr;
  5211. }
  5212. // --------------------------------------------------------------------------------
  5213. // CHTTPMailTransport::FolderMemberInfo
  5214. // --------------------------------------------------------------------------------
  5215. STDMETHODIMP CHTTPMailTransport::FolderMemberInfo(LPCSTR pszPath,
  5216. MEMBERINFOFLAGS flags,
  5217. DWORD dwDepth,
  5218. BOOL fIncludeRoot,
  5219. DWORD dwContext,
  5220. LPSTR pszFolderTimeStamp,
  5221. LPSTR pszFolderName)
  5222. {
  5223. HRESULT hr = S_OK;
  5224. LPHTTPQUEUEDOP pOp;
  5225. IF_FAILEXIT(hr = _MemberInfo2(pszPath, flags, dwDepth, fIncludeRoot, dwContext, &pOp));
  5226. pOp->dwRHFlags |= RH_FOLDERTIMESTAMP | RH_ADDCHARSET;
  5227. pOp->pszFolderTimeStamp = PszDupA(pszFolderTimeStamp);
  5228. // To be used when we do timestamping on every folder. Right now the default is inbox
  5229. //pOp->pszFolderName = PszDupA(pszFolderName);
  5230. QueueOperation(pOp);
  5231. exit:
  5232. return hr;
  5233. }
  5234. HRESULT CHTTPMailTransport::_HrParseAndCopy(LPCSTR pszToken, LPSTR *ppszDest, LPSTR lpszSrc)
  5235. {
  5236. LPSTR lpszBeginning = lpszSrc;
  5237. LPSTR lpszEnd;
  5238. DWORD dwCount = 0;
  5239. HRESULT hr = E_FAIL;
  5240. int cchSize;
  5241. lpszBeginning = StrStr(lpszSrc, pszToken);
  5242. if (!lpszBeginning)
  5243. goto exit;
  5244. lpszBeginning = StrChr(lpszBeginning, '=');
  5245. if (!lpszBeginning)
  5246. goto exit;
  5247. // Skip the equal sign
  5248. ++lpszBeginning;
  5249. SkipWhitespace(lpszBeginning, &dwCount);
  5250. lpszBeginning += dwCount;
  5251. lpszEnd = StrChr(lpszBeginning, ',');
  5252. if (!lpszEnd)
  5253. {
  5254. //Its possible that this token is at the end. So use the remaining string.
  5255. //Lets take a look at the length and make sure that it doesn't fall off the deep end.
  5256. lpszEnd = lpszBeginning + strlen(lpszBeginning);
  5257. }
  5258. AssertSz(((lpszEnd - lpszBeginning + 1) < 20), "This number looks awfully long, please make sure that this is correct")
  5259. cchSize = (int)(lpszEnd - lpszBeginning + 2);
  5260. if (!MemAlloc((void**)ppszDest, cchSize))
  5261. goto exit;
  5262. cchSize = (int)(lpszEnd - lpszBeginning + 1);
  5263. StrCpyN(*ppszDest, lpszBeginning, cchSize);
  5264. // Null terminate it
  5265. *(*ppszDest + (lpszEnd - lpszBeginning + 1)) = 0;
  5266. hr = S_OK;
  5267. exit:
  5268. return hr;
  5269. }
  5270. // --------------------------------------------------------------------------------
  5271. // CHTTPMailTransport::_GetTimestampHeader
  5272. // --------------------------------------------------------------------------------
  5273. HRESULT CHTTPMailTransport::_HrGetTimestampHeader(LPSTR *ppszHeader)
  5274. {
  5275. HRESULT hr = S_OK;
  5276. DWORD dwSize = MAX_PATH;
  5277. LPSTR pszHeader = NULL;
  5278. Assert(NULL != ppszHeader);
  5279. *ppszHeader = NULL;
  5280. retry:
  5281. if (!MemAlloc((void **)&pszHeader, dwSize))
  5282. {
  5283. hr = E_OUTOFMEMORY;
  5284. goto exit;
  5285. }
  5286. StrCpyN(pszHeader, c_szXTimestamp, dwSize);
  5287. if (!HttpQueryInfo(m_op.hRequest, HTTP_QUERY_RAW_HEADERS | HTTP_QUERY_CUSTOM, pszHeader, &dwSize, NULL))
  5288. {
  5289. if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
  5290. {
  5291. hr = E_FAIL;
  5292. goto exit;
  5293. }
  5294. SafeMemFree(pszHeader);
  5295. goto retry;
  5296. }
  5297. *ppszHeader = pszHeader;
  5298. pszHeader = NULL;
  5299. exit:
  5300. SafeMemFree(pszHeader);
  5301. return hr;
  5302. }