Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

918 lines
22 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-2001 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. #ifndef __ATLSPRIV_H__
  11. #define __ATLSPRIV_H__
  12. #pragma once
  13. #ifndef _WINSOCKAPI_
  14. #include <winsock2.h>
  15. #endif
  16. #ifndef _WINSOCK2API_
  17. #error Winsock2.h has to be included before including windows.h or use atlbase.h instead of windows.h
  18. #endif
  19. #ifndef _ATL_NO_DEFAULT_LIBS
  20. #pragma comment(lib, "ws2_32.lib")
  21. #endif // !_ATL_NO_DEFAULT_LIBS
  22. #include <svcguid.h>
  23. #include <atlcoll.h>
  24. #include <mlang.h>
  25. #include <atlutil.h>
  26. // ATL_SOCK_TIMEOUT defines the amount of time
  27. // this socket will block the calling thread waiting
  28. // for the socket before the call times out.
  29. #ifndef ATL_SOCK_TIMEOUT
  30. #define ATL_SOCK_TIMEOUT 10000
  31. #endif
  32. #define ATL_WINSOCK_VER MAKELONG(2,0)
  33. // This file contains unsupported code used in ATL implementation files. Most of
  34. // this code is support code for various ATL Server functions.
  35. namespace ATL{
  36. // One of these objects can be created globally to turn
  37. // on the socket stuff at CRT startup and shut it down
  38. // on CRT term.
  39. class _AtlWSAInit
  40. {
  41. public:
  42. _AtlWSAInit() throw()
  43. {
  44. m_dwErr = WSAEFAULT;
  45. }
  46. bool Init()
  47. {
  48. if (!IsStarted())
  49. m_dwErr = WSAStartup(ATL_WINSOCK_VER, &m_stData);
  50. return m_dwErr == 0;
  51. }
  52. bool IsStarted(){ return m_dwErr == 0; }
  53. ~_AtlWSAInit() throw()
  54. {
  55. if (!m_dwErr)
  56. WSACleanup();
  57. }
  58. WSADATA m_stData;
  59. DWORD m_dwErr;
  60. };
  61. #ifndef _ATL_NO_GLOBAL_SOCKET_STARTUP
  62. __declspec(selectany)_AtlWSAInit g_HttpInit;
  63. #endif
  64. class ZEvtSyncSocket
  65. {
  66. public:
  67. ZEvtSyncSocket() throw();
  68. ~ZEvtSyncSocket() throw();
  69. operator SOCKET() throw();
  70. void Close() throw();
  71. void Term() throw();
  72. bool Create(WORD wFlags=0) throw();
  73. bool Create(short af, short st, short proto, WORD wFlags=0) throw();
  74. bool Connect(LPCTSTR szAddr, unsigned short nPort) throw();
  75. bool Connect(const SOCKADDR* psa) throw();
  76. bool Write(WSABUF *pBuffers, int nCount, DWORD *pdwSize) throw();
  77. bool Write(const unsigned char *pBuffIn, DWORD *pdwSize) throw();
  78. bool Read(const unsigned char *pBuff, DWORD *pdwSize) throw();
  79. bool Init(SOCKET hSocket, void * /*pData=NULL*/) throw();
  80. DWORD GetSocketTimeout();
  81. DWORD SetSocketTimeout(DWORD dwNewTimeout);
  82. bool SupportsScheme(ATL_URL_SCHEME scheme);
  83. protected:
  84. DWORD m_dwCreateFlags;
  85. WSAEVENT m_hEventRead;
  86. WSAEVENT m_hEventWrite;
  87. WSAEVENT m_hEventConnect;
  88. CComAutoCriticalSection m_csRead;
  89. CComAutoCriticalSection m_csWrite;
  90. SOCKET m_socket;
  91. bool m_bConnected;
  92. DWORD m_dwLastError;
  93. DWORD m_dwSocketTimeout;
  94. };
  95. #define ATL_MAX_QUERYSET (sizeof(WSAQUERYSET) + 4096)
  96. class CTCPAddrLookup
  97. {
  98. public:
  99. CTCPAddrLookup() throw();
  100. ~CTCPAddrLookup() throw();
  101. // properties for this class
  102. __declspec(property(get=GetSockAddr)) const SOCKADDR* Addr;
  103. __declspec(property(get=GetSockAddrSize)) int AddrSize;
  104. // Takes a string that identifies a TCP service
  105. // to look up. The szName parameter is either the name
  106. // of a server (eg microsoft.com) or the dotted IP address
  107. // of a server (eg 157.24.34.205). This function must succeed
  108. // before accessing the Addr and AddrSize parameters.
  109. // This function returns normal socket errors on failure
  110. int GetRemoteAddr(LPCTSTR szName, short nPort) throw();
  111. const SOCKADDR* GetSockAddr();
  112. int GetSockAddrSize();
  113. protected:
  114. SOCKADDR *m_pAddr;
  115. int m_nAddrSize;
  116. sockaddr_in m_saIn;
  117. WSAQUERYSET *m_pQuerySet;
  118. };
  119. // MIME helper functions
  120. extern __declspec(selectany) const DWORD ATL_MIME_DEFAULT_CP = 28591;
  121. // This function is used to create an CSMTPConnection-compatible recipient string
  122. // from a recipient string that is in a CMimeMessage object.
  123. inline BOOL AtlMimeMakeRecipientsString(LPCSTR szNames, LPSTR szRecipients, LPDWORD pdwLen = NULL) throw()
  124. {
  125. ATLASSERT(szNames != NULL);
  126. ATLASSERT(szRecipients != NULL);
  127. char ch;
  128. DWORD dwLen = 0;
  129. while ((ch = *szNames++) != '\0')
  130. {
  131. // Skip everything that is in double quotes
  132. if (ch == '"')
  133. {
  134. while (*szNames && *szNames++ != '"');
  135. }
  136. if (ch == '<')
  137. {
  138. // Extract the address from within the <>
  139. while (*szNames && *szNames != '>')
  140. {
  141. *szRecipients++ = *szNames++;
  142. dwLen++;
  143. }
  144. // End it with a comma
  145. *szRecipients++ = ',';
  146. dwLen++;
  147. }
  148. if (ch == '=')
  149. {
  150. // Skip any BEncoded or QEncoded parts
  151. while (*szNames)
  152. {
  153. if (*szNames == '?' && *(szNames+1) == '=')
  154. {
  155. szNames+=2;
  156. break;
  157. }
  158. szNames++;
  159. }
  160. }
  161. szNames++;
  162. }
  163. if (dwLen != 0)
  164. {
  165. szRecipients--;
  166. dwLen--;
  167. }
  168. *szRecipients = '\0';
  169. if (pdwLen)
  170. *pdwLen = dwLen;
  171. return TRUE;
  172. }
  173. // AtlMimeCharsetFromCodePage, AtlMimeConvertString
  174. // are MIME multilanguage support functions.
  175. // Get the MIME character set of the of the code page. The character set is copied
  176. // into szCharset.
  177. #ifndef ATLSMTP_DEFAULT_CSET
  178. #define ATLSMTP_DEFAULT_CSET "iso-8859-1"
  179. #endif
  180. inline BOOL AtlMimeCharsetFromCodePage(LPSTR szCharset, UINT uiCodePage, IMultiLanguage* pMultiLanguage) throw()
  181. {
  182. ATLASSERT(szCharset != NULL);
  183. if (!pMultiLanguage)
  184. {
  185. if ((uiCodePage == 0) || (uiCodePage == ATL_MIME_DEFAULT_CP))
  186. {
  187. strcpy(szCharset, ATLSMTP_DEFAULT_CSET);
  188. }
  189. else
  190. {
  191. return FALSE;
  192. }
  193. }
  194. else
  195. {
  196. if (uiCodePage == 0)
  197. uiCodePage = GetACP();
  198. HRESULT hr;
  199. MIMECPINFO cpInfo;
  200. memset(&cpInfo, 0x00, sizeof(cpInfo));
  201. #ifdef __IMultiLanguage2_INTERFACE_DEFINED__
  202. // if IMultiLanguage2 is available, use it
  203. CComPtr<IMultiLanguage2> spMultiLanguage2;
  204. hr = pMultiLanguage->QueryInterface(__uuidof(IMultiLanguage2), (void **)&spMultiLanguage2);
  205. if (FAILED(hr) || !spMultiLanguage2.p)
  206. hr = pMultiLanguage->GetCodePageInfo(uiCodePage, &cpInfo);
  207. else
  208. hr = spMultiLanguage2->GetCodePageInfo(uiCodePage,
  209. LANGIDFROMLCID(GetThreadLocale()), &cpInfo);
  210. #else // __IMultiLanguage2_INTERFACE_DEFINED__
  211. hr = pMultiLanguage->GetCodePageInfo(uiCodePage, &cpInfo);
  212. #endif // __IMultiLanguage2_INTERFACE_DEFINED__
  213. if (hr != S_OK)
  214. return FALSE;
  215. _ATLTRY
  216. {
  217. strcpy(szCharset, CW2A(cpInfo.wszWebCharset));
  218. }
  219. _ATLCATCHALL()
  220. {
  221. return FALSE;
  222. }
  223. }
  224. return TRUE;
  225. }
  226. inline BOOL AtlMimeConvertStringW(
  227. IMultiLanguage *pMultiLanguage,
  228. UINT uiCodePage,
  229. LPCWSTR wszIn,
  230. LPSTR *ppszOut,
  231. UINT *pnLen) throw()
  232. {
  233. ATLASSERT( pMultiLanguage != NULL );
  234. ATLASSERT( wszIn != NULL );
  235. ATLASSERT( ppszOut != NULL );
  236. ATLASSERT( pnLen != NULL );
  237. *ppszOut = NULL;
  238. *pnLen = 0;
  239. if (uiCodePage == 0)
  240. {
  241. uiCodePage = GetACP();
  242. }
  243. DWORD dwMode = 0;
  244. CHeapPtr<char> pszOut;
  245. // get the length
  246. HRESULT hr = pMultiLanguage->ConvertStringFromUnicode(&dwMode, uiCodePage, const_cast<LPWSTR>(wszIn), NULL, NULL, pnLen);
  247. if (SUCCEEDED(hr))
  248. {
  249. // allocate the buffer
  250. if (pszOut.Allocate(*pnLen))
  251. {
  252. dwMode = 0;
  253. // do the conversion
  254. hr = pMultiLanguage->ConvertStringFromUnicode(&dwMode, uiCodePage, const_cast<LPWSTR>(wszIn), NULL, pszOut, pnLen);
  255. if (SUCCEEDED(hr))
  256. {
  257. *ppszOut = pszOut.Detach();
  258. return TRUE;
  259. }
  260. }
  261. }
  262. return FALSE;
  263. }
  264. inline BOOL AtlMimeConvertStringA(
  265. IMultiLanguage *pMultiLanguage,
  266. UINT uiCodePage,
  267. LPCSTR szIn,
  268. LPSTR *ppszOut,
  269. UINT *pnLen) throw()
  270. {
  271. _ATLTRY
  272. {
  273. return AtlMimeConvertStringW(pMultiLanguage, uiCodePage, CA2W(szIn), ppszOut, pnLen);
  274. }
  275. _ATLCATCHALL()
  276. {
  277. return FALSE;
  278. }
  279. }
  280. #ifdef _UNICODE
  281. #define AtlMimeConvertString AtlMimeConvertStringW
  282. #else
  283. #define AtlMimeConvertString AtlMimeConvertStringA
  284. #endif
  285. // SOAP helpers
  286. extern __declspec(selectany) const char * s_szAtlsWSDLSrf =
  287. "<?xml version=\"1.0\"?>\r\n"
  288. "<!-- ATL Server generated Web Service Description -->\r\n"
  289. "<definitions \r\n"
  290. " xmlns:s=\"http://www.w3.org/2000/10/XMLSchema\" \r\n"
  291. " xmlns:http=\"http://schemas.xmlsoap.org/wsdl/http/\" \r\n"
  292. " xmlns:mime=\"http://schemas.xmlsoap.org/wsdl/mime/\" \r\n"
  293. " xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\" \r\n"
  294. " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" \r\n"
  295. " xmlns:s0=\"{{GetNamespace}}\" \r\n"
  296. " xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\"\r\n"
  297. " targetNamespace=\"{{GetNamespace}}\" \r\n"
  298. " xmlns=\"http://schemas.xmlsoap.org/wsdl/\"\r\n"
  299. ">\r\n"
  300. " <types>\r\n"
  301. " <s:schema targetNamespace=\"{{GetNamespace}}\" attributeFormDefault=\"qualified\" elementFormDefault=\"qualified\">\r\n"
  302. "{{while GetNextFunction}}\r\n"
  303. " <s:element name=\"{{GetFunctionName}}\">\r\n"
  304. " <s:complexType derivedBy=\"restriction\">\r\n"
  305. " <s:all>\r\n"
  306. "{{while GetNextParameter}}\r\n"
  307. "{{if IsInParameter}}\r\n"
  308. " <s:element name=\"{{GetParameterName}}\" {{if NotIsArrayParameter}}type=\"{{if IsParameterUDT}}s0:{{else}}s:{{endif}}{{GetParameterSoapType}}\"/{{else}}nullable=\"{{if IsParameterDynamicArray}}true{{else}}false{{endif}}\"{{endif}}>\r\n"
  309. "{{if IsArrayParameter}}\r\n"
  310. " <s:complexType derivedBy=\"restriction\">\r\n"
  311. " <s:all>\r\n"
  312. " <s:element name=\"{{GetParameterSoapType}}\" type=\"{{if IsParameterUDT}}s0:{{else}}s:{{endif}}{{GetParameterSoapType}}\" {{if IsParameterDynamicArray}}minOccurs=\"0\" maxOccurs=\"unbounded\"{{else}}{{if IsParameterOneDimensional}}minOccurs=\"{{GetParameterArraySize}}\" maxOccurs=\"{{GetParameterArraySize}}\"{{else}}soap:arrayType=\"{{GetParameterArraySoapDims}}\"{{endif}}{{endif}}/>\r\n"
  313. " </s:all>\r\n"
  314. " </s:complexType>\r\n"
  315. " </s:element>\r\n"
  316. "{{endif}}\r\n"
  317. "{{endif}}\r\n"
  318. "{{endwhile}}\r\n"
  319. " </s:all>\r\n"
  320. " </s:complexType>\r\n"
  321. " </s:element>\r\n"
  322. " <s:element name=\"{{GetFunctionName}}Response\">\r\n"
  323. " <s:complexType derivedBy=\"restriction\">\r\n"
  324. " <s:all>\r\n"
  325. "{{while GetNextParameter}}\r\n"
  326. "{{if IsOutParameter}}\r\n"
  327. " <s:element name=\"{{GetParameterName}}\" {{if NotIsArrayParameter}}type=\"{{if IsParameterUDT}}s0:{{else}}s:{{endif}}{{GetParameterSoapType}}\"/{{else}}nullable=\"{{if IsParameterDynamicArray}}true{{else}}false{{endif}}\"{{endif}}>\r\n"
  328. "{{if IsArrayParameter}}\r\n"
  329. " <s:complexType derivedBy=\"restriction\">\r\n"
  330. " <s:all>\r\n"
  331. " <s:element name=\"{{GetParameterSoapType}}\" type=\"{{if IsParameterUDT}}s0:{{else}}s:{{endif}}{{GetParameterSoapType}}\" {{if IsParameterDynamicArray}}minOccurs=\"0\" maxOccurs=\"unbounded\"{{else}}{{if IsParameterOneDimensional}}minOccurs=\"{{GetParameterArraySize}}\" maxOccurs=\"{{GetParameterArraySize}}\"{{else}}soap:arrayType=\"{{GetParameterArraySoapDims}}\"{{endif}}{{endif}}/>\r\n"
  332. " </s:all>\r\n"
  333. " </s:complexType>\r\n"
  334. " </s:element>\r\n"
  335. "{{endif}}\r\n"
  336. "{{endif}}\r\n"
  337. "{{endwhile}}\r\n"
  338. " </s:all>\r\n"
  339. " </s:complexType>\r\n"
  340. " </s:element>\r\n"
  341. "{{endwhile}}\r\n"
  342. "{{while GetNextEnum}}\r\n"
  343. " <s:simpleType name=\"{{GetEnumName}}\">\r\n"
  344. " <s:restriction base=\"s:string\">\r\n"
  345. "{{while GetNextEnumElement}}\r\n"
  346. " <s:enumeration value=\"{{GetEnumElementName}}\"/>\r\n"
  347. "{{endwhile}}\r\n"
  348. " </s:restriction>\r\n"
  349. " </s:simpleType>\r\n"
  350. "{{endwhile}}\r\n"
  351. " <s:complexType name=\"ATLSOAP_BLOB\">\r\n"
  352. " <s:all>\r\n"
  353. " <s:element name=\"size\" type=\"unsignedLong\"/>\r\n"
  354. " <s:element name=\"data\" nullable=\"false\">\r\n"
  355. " <s:simpleType xmlns:q3=\"http://www.w3.org/2000/10/XMLSchema\" base=\"q3:binary\">\r\n"
  356. " <s:encoding value=\"base64\"/>\r\n"
  357. " </s:simpleType>\r\n"
  358. " </s:element>\r\n"
  359. " </s:all>\r\n"
  360. " </s:complexType>\r\n"
  361. "{{while GetNextStruct}}\r\n"
  362. " <s:complexType name=\"{{GetStructName}}\" derivedBy=\"restriction\">\r\n"
  363. " <s:all>\r\n"
  364. "{{while GetNextStructField}}\r\n"
  365. " <s:element name=\"{{GetStructFieldName}}\" {{if NotIsArrayField}}type=\"{{if IsFieldUDT}}s0:{{else}}s:{{endif}}{{GetStructFieldSoapType}}\"/{{else}}nullable=\"false\"{{endif}}>\r\n"
  366. "{{if IsArrayField}}\r\n"
  367. " <s:complexType derivedBy=\"restriction\">\r\n"
  368. " <s:all>\r\n"
  369. " <s:element name=\"{{GetStructFieldSoapType}}\" type=\"{{if IsFieldUDT}}s0:{{else}}s:{{endif}}{{GetStructFieldSoapType}}\" {{if IsFieldOneDimensional}}minOccurs=\"{{GetFieldArraySize}}\" maxOccurs=\"{{GetFieldArraySize}}\"{{else}}soap:arrayType=\"{{GetFieldArraySoapDims}}\"{{endif}}/>\r\n"
  370. " </s:all>\r\n"
  371. " </s:complexType>\r\n"
  372. " </s:element>\r\n"
  373. "{{endif}}\r\n"
  374. "{{endwhile}}\r\n"
  375. " </s:all>\r\n"
  376. " </s:complexType>\r\n"
  377. "{{endwhile}}\r\n"
  378. "{{while GetNextHeader}}\r\n"
  379. " <s:element name=\"{{GetHeaderName}}\" {{if NotIsArrayHeader}}type=\"{{if IsHeaderUDT}}s0:{{else}}s:{{endif}}{{GetHeaderSoapType}}\"/{{else}}nullable=\"false\"{{endif}}>\r\n"
  380. "{{if IsArrayHeader}}\r\n"
  381. " <s:complexType derivedBy=\"restriction\">\r\n"
  382. " <s:all>\r\n"
  383. " <s:element name=\"{{GetHeaderSoapType}}\" type=\"{{if IsHeaderUDT}}s0:{{else}}s:{{endif}}{{GetHeaderSoapType}}\" {{if IsHeaderOneDimensional}}minOccurs=\"{{GetHeaderArraySize}}\" maxOccurs=\"{{GetHeaderArraySize}}\"{{else}}soap:arrayType=\"{{GetHeaderArraySoapDims}}\"{{endif}}/>\r\n"
  384. " </s:all>\r\n"
  385. " </s:complexType>\r\n"
  386. " </s:element>\r\n"
  387. "{{endif}}\r\n"
  388. "{{endwhile}}\r\n"
  389. " </s:schema>\r\n"
  390. " </types>\r\n"
  391. "{{while GetNextFunction}}\r\n"
  392. " <message name=\"{{GetFunctionName}}In\">\r\n"
  393. " <part name=\"parameters\" element=\"s0:{{GetFunctionName}}\"/>\r\n"
  394. " </message>\r\n"
  395. " <message name=\"{{GetFunctionName}}Out\">\r\n"
  396. " <part name=\"parameters\" element=\"s0:{{GetFunctionName}}Response\"/>\r\n"
  397. " </message>\r\n"
  398. "{{endwhile}}\r\n"
  399. "{{while GetNextHeader}}\r\n"
  400. " <message name=\"{{GetHeaderName}}\">\r\n"
  401. " <part name=\"{{GetHeaderName}}\" element=\"s0:{{GetHeaderName}}\"/>\r\n"
  402. " </message>\r\n"
  403. "{{endwhile}}\r\n"
  404. " <portType name=\"{{GetServiceName}}Soap\">\r\n"
  405. "{{while GetNextFunction}}\r\n"
  406. " <operation name=\"{{GetFunctionName}}\">\r\n"
  407. " <input message=\"s0:{{GetFunctionName}}In\"/>\r\n"
  408. " <output message=\"s0:{{GetFunctionName}}Out\"/>\r\n"
  409. " </operation>\r\n"
  410. "{{endwhile}}\r\n"
  411. " </portType>\r\n"
  412. " <binding name=\"{{GetServiceName}}Soap\" type=\"s0:{{GetServiceName}}Soap\">\r\n"
  413. " <soap:binding transport=\"http://schemas.xmlsoap.org/soap/http\" style=\"document\"/>\r\n"
  414. "{{while GetNextFunction}}\r\n"
  415. " <operation name=\"{{GetFunctionName}}\">\r\n"
  416. " <soap:operation soapAction=\"#{{GetFunctionName}}\" style=\"document\"/>\r\n"
  417. " <input>\r\n"
  418. " <soap:body use=\"literal\"/>\r\n"
  419. "{{while GetNextFunctionHeader}}\r\n"
  420. "{{if IsInHeader}}\r\n"
  421. " <soap:header message=\"s0:{{GetFunctionHeaderName}}\" part=\"{{GetFunctionHeaderName}}\" use=\"literal\"{{if IsRequiredHeader}} wsdl:required=\"true\"{{endif}}/>\r\n"
  422. "{{endif}}\r\n"
  423. "{{endwhile}}\r\n"
  424. " </input>\r\n"
  425. " <output>\r\n"
  426. " <soap:body use=\"literal\"/>\r\n"
  427. "{{while GetNextFunctionHeader}}\r\n"
  428. "{{if IsOutHeader}}\r\n"
  429. " <soap:header message=\"s0:{{GetFunctionHeaderName}}\" part=\"{{GetFunctionHeaderName}}\" use=\"literal\"{{if IsRequiredHeader}} wsdl:required=\"true\"{{endif}}/>\r\n"
  430. "{{endif}}\r\n"
  431. "{{endwhile}}\r\n"
  432. " </output>\r\n"
  433. " </operation>\r\n"
  434. "{{endwhile}}\r\n"
  435. " </binding>\r\n"
  436. " <service name=\"{{GetServiceName}}\">\r\n"
  437. " <port name=\"{{GetServiceName}}Soap\" binding=\"s0:{{GetServiceName}}Soap\">\r\n"
  438. " <soap:address location=\"{{GetURL}}\"/>\r\n"
  439. " </port>\r\n"
  440. " </service>\r\n"
  441. "</definitions>"
  442. "";
  443. extern __declspec(selectany) const size_t s_nAtlsWSDLSrfLen = strlen(s_szAtlsWSDLSrf);
  444. class CStreamOnSequentialStream :
  445. public IStream
  446. {
  447. CComPtr<ISequentialStream> m_spStream;
  448. public:
  449. CStreamOnSequentialStream(ISequentialStream *pStream) throw()
  450. {
  451. ATLASSERT(pStream);
  452. m_spStream = pStream;
  453. }
  454. STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw()
  455. {
  456. if (!m_spStream)
  457. return E_UNEXPECTED;
  458. return m_spStream->Read(pv, cb, pcbRead);
  459. }
  460. STDMETHOD(Write)(const void *pv, ULONG cb, ULONG *pcbWritten) throw()
  461. {
  462. if (!m_spStream)
  463. return E_UNEXPECTED;
  464. return m_spStream->Write(pv, cb, pcbWritten);
  465. }
  466. STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw()
  467. {
  468. return E_NOTIMPL;
  469. }
  470. STDMETHOD(SetSize)(ULARGE_INTEGER ) throw()
  471. {
  472. return E_NOTIMPL;
  473. }
  474. STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *,
  475. ULARGE_INTEGER *) throw()
  476. {
  477. return E_NOTIMPL;
  478. }
  479. STDMETHOD(Commit)(DWORD ) throw()
  480. {
  481. return E_NOTIMPL;
  482. }
  483. STDMETHOD(Revert)( void) throw()
  484. {
  485. return E_NOTIMPL;
  486. }
  487. STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw()
  488. {
  489. return E_NOTIMPL;
  490. }
  491. STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER ,
  492. DWORD ) throw()
  493. {
  494. return E_NOTIMPL;
  495. }
  496. STDMETHOD(Stat)(STATSTG *, DWORD ) throw()
  497. {
  498. return E_NOTIMPL;
  499. }
  500. STDMETHOD(Clone)(IStream **) throw()
  501. {
  502. return E_NOTIMPL;
  503. }
  504. STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw()
  505. {
  506. *ppUnk = NULL;
  507. if (::InlineIsEqualGUID(iid, IID_IUnknown) ||
  508. ::InlineIsEqualGUID(iid, IID_ISequentialStream) ||
  509. ::InlineIsEqualGUID(iid, IID_IStream))
  510. {
  511. *ppUnk = (void*)(IStream*)this;
  512. AddRef();
  513. return S_OK;
  514. }
  515. return E_NOINTERFACE;
  516. }
  517. ULONG STDMETHODCALLTYPE AddRef( void) throw()
  518. {
  519. return (ULONG)1;
  520. }
  521. ULONG STDMETHODCALLTYPE Release( void) throw()
  522. {
  523. return (ULONG)1;
  524. }
  525. };
  526. class CStreamOnByteArray :
  527. public IStream
  528. {
  529. public:
  530. BYTE *m_pArray;
  531. DWORD m_dwRead;
  532. CStreamOnByteArray(BYTE *pBytes) throw()
  533. {
  534. ATLASSERT(pBytes);
  535. m_pArray = pBytes;
  536. m_dwRead = 0;
  537. }
  538. STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw()
  539. {
  540. if (!pv)
  541. return E_INVALIDARG;
  542. if (cb == 0)
  543. return S_OK;
  544. if (!m_pArray)
  545. return E_UNEXPECTED;
  546. BYTE *pCurr = m_pArray;
  547. pCurr += m_dwRead;
  548. memcpy(pv, pCurr, cb);
  549. if (pcbRead)
  550. *pcbRead = cb;
  551. m_dwRead += cb;
  552. return S_OK;
  553. }
  554. STDMETHOD(Write)(const void* , ULONG , ULONG* ) throw()
  555. {
  556. return E_UNEXPECTED;
  557. }
  558. STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw()
  559. {
  560. return E_NOTIMPL;
  561. }
  562. STDMETHOD(SetSize)(ULARGE_INTEGER ) throw()
  563. {
  564. return E_NOTIMPL;
  565. }
  566. STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *,
  567. ULARGE_INTEGER *) throw()
  568. {
  569. return E_NOTIMPL;
  570. }
  571. STDMETHOD(Commit)(DWORD ) throw()
  572. {
  573. return E_NOTIMPL;
  574. }
  575. STDMETHOD(Revert)( void) throw()
  576. {
  577. return E_NOTIMPL;
  578. }
  579. STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw()
  580. {
  581. return E_NOTIMPL;
  582. }
  583. STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER ,
  584. DWORD ) throw()
  585. {
  586. return E_NOTIMPL;
  587. }
  588. STDMETHOD(Stat)(STATSTG *, DWORD ) throw()
  589. {
  590. return E_NOTIMPL;
  591. }
  592. STDMETHOD(Clone)(IStream **) throw()
  593. {
  594. return E_NOTIMPL;
  595. }
  596. STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw()
  597. {
  598. *ppUnk = NULL;
  599. if (::InlineIsEqualGUID(iid, IID_IUnknown) ||
  600. ::InlineIsEqualGUID(iid, IID_ISequentialStream) ||
  601. ::InlineIsEqualGUID(iid, IID_IStream))
  602. {
  603. *ppUnk = (void*)(IStream*)this;
  604. AddRef();
  605. return S_OK;
  606. }
  607. return E_NOINTERFACE;
  608. }
  609. ULONG STDMETHODCALLTYPE AddRef( void) throw()
  610. {
  611. return (ULONG)1;
  612. }
  613. ULONG STDMETHODCALLTYPE Release( void) throw()
  614. {
  615. return (ULONG)1;
  616. }
  617. };
  618. class CVariantStream :
  619. public IStream
  620. {
  621. public:
  622. CVariantStream() throw()
  623. {
  624. m_nCurrRead = 0;
  625. m_nVariantSize = 0;
  626. m_nRef = 1;
  627. }
  628. // input variant is put into contained BYTE array.
  629. HRESULT InsertVariant(const VARIANT *pVarIn) throw()
  630. {
  631. CComVariant vIn;
  632. HRESULT hr = E_FAIL;
  633. m_nCurrRead = 0;
  634. m_nVariantSize = 0;
  635. hr = vIn.Copy(pVarIn);
  636. if (hr == S_OK)
  637. hr = vIn.WriteToStream(static_cast<IStream*>(this));
  638. return hr;
  639. }
  640. // variant is read from contained byte array into
  641. // out variant.
  642. HRESULT RetrieveVariant(VARIANT *pVarOut) throw()
  643. {
  644. CComVariant vOut;
  645. HRESULT hr = vOut.ReadFromStream(static_cast<IStream*>(this));
  646. if (hr == S_OK)
  647. hr = VariantCopy(pVarOut, &vOut);
  648. m_nCurrRead = 0;
  649. return hr;
  650. }
  651. HRESULT LoadFromStream(ISequentialStream *stream) throw()
  652. {
  653. m_nCurrRead = 0;
  654. CStreamOnSequentialStream stm(stream);
  655. CComVariant v;
  656. HRESULT hr = v.ReadFromStream(&stm);
  657. if (hr == S_OK)
  658. hr = v.WriteToStream(static_cast<IStream*>(this));
  659. return hr;
  660. }
  661. ISequentialStream* GetStream() throw()
  662. {
  663. return static_cast<ISequentialStream*>(this);
  664. }
  665. size_t GetVariantSize() throw()
  666. {
  667. return m_nVariantSize;
  668. }
  669. // Implementation
  670. // IStream implementation;
  671. STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead) throw()
  672. {
  673. if (!pv)
  674. return E_INVALIDARG;
  675. if (cb == 0)
  676. return S_OK;
  677. if (pcbRead)
  678. *pcbRead = 0;
  679. if (!m_nVariantSize)
  680. return S_OK; // nothing to do.
  681. size_t nLeft = m_nVariantSize - m_nCurrRead;
  682. if (nLeft > 0)
  683. {
  684. size_t nRead = min(nLeft, cb);
  685. BYTE *pCurr = m_stream;
  686. pCurr += m_nCurrRead;
  687. memcpy(pv,
  688. pCurr,
  689. nRead);
  690. m_nCurrRead += nRead;
  691. if (pcbRead)
  692. *pcbRead = (ULONG)nRead;
  693. }
  694. return S_OK;
  695. }
  696. STDMETHOD(Write)(const void *pv, ULONG cb, ULONG *pcbWritten) throw()
  697. {
  698. HRESULT hr = E_OUTOFMEMORY;
  699. if (!pv)
  700. return E_INVALIDARG;
  701. if (cb == 0)
  702. return S_OK;
  703. if (pcbWritten)
  704. *pcbWritten = 0;
  705. BYTE *pBytes = m_stream.Reallocate(cb);
  706. if (pBytes)
  707. {
  708. pBytes += m_nVariantSize;
  709. memcpy(pBytes, pv, cb);
  710. if (pcbWritten)
  711. *pcbWritten = cb;
  712. m_nVariantSize += cb;
  713. hr = S_OK;
  714. }
  715. return hr;
  716. }
  717. STDMETHOD(Seek)(LARGE_INTEGER , DWORD , ULARGE_INTEGER *) throw()
  718. {
  719. return E_NOTIMPL;
  720. }
  721. STDMETHOD(SetSize)(ULARGE_INTEGER ) throw()
  722. {
  723. return E_NOTIMPL;
  724. }
  725. STDMETHOD(CopyTo)(IStream *, ULARGE_INTEGER , ULARGE_INTEGER *,
  726. ULARGE_INTEGER *) throw()
  727. {
  728. return E_NOTIMPL;
  729. }
  730. STDMETHOD(Commit)(DWORD ) throw()
  731. {
  732. return E_NOTIMPL;
  733. }
  734. STDMETHOD(Revert)( void) throw()
  735. {
  736. return E_NOTIMPL;
  737. }
  738. STDMETHOD(LockRegion)(ULARGE_INTEGER , ULARGE_INTEGER , DWORD ) throw()
  739. {
  740. return E_NOTIMPL;
  741. }
  742. STDMETHOD(UnlockRegion)(ULARGE_INTEGER , ULARGE_INTEGER ,
  743. DWORD ) throw()
  744. {
  745. return E_NOTIMPL;
  746. }
  747. STDMETHOD(Stat)(STATSTG *, DWORD ) throw()
  748. {
  749. return E_NOTIMPL;
  750. }
  751. STDMETHOD(Clone)(IStream **) throw()
  752. {
  753. return E_NOTIMPL;
  754. }
  755. STDMETHOD(QueryInterface)(REFIID iid, void **ppUnk) throw()
  756. {
  757. *ppUnk = NULL;
  758. if (::InlineIsEqualGUID(iid, IID_IUnknown))
  759. {
  760. *ppUnk = (void*)(IUnknown*)this;
  761. }
  762. else if (::InlineIsEqualGUID(iid, IID_ISequentialStream))
  763. {
  764. *ppUnk = (void*)(ISequentialStream*)this;
  765. }
  766. else if (::InlineIsEqualGUID(iid, IID_IStream))
  767. {
  768. *ppUnk = (void*)(IStream*)this;
  769. }
  770. if (*ppUnk)
  771. {
  772. AddRef();
  773. return S_OK;
  774. }
  775. return E_NOINTERFACE;
  776. }
  777. ULONG STDMETHODCALLTYPE AddRef( void) throw()
  778. {
  779. return (ULONG)1;
  780. }
  781. ULONG STDMETHODCALLTYPE Release( void) throw()
  782. {
  783. return (ULONG)1;
  784. }
  785. CTempBuffer<BYTE> m_stream;
  786. size_t m_nVariantSize;
  787. size_t m_nCurrRead;
  788. long m_nRef;
  789. };
  790. #include <atlspriv.inl>
  791. }; // namespace ATL
  792. #endif // __ATLSPRIV_H__