Disable /arch:SSE2.
[xy_vsfilter.git] / include / atl / atlhttp.h
blobe8a4321e6d9692744ae3dfb6f632c605935df4b2
1 // This is a part of the Active Template Library.
2 // Copyright (C) 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.
11 #ifndef __ATLHTTP_H__
12 #define __ATLHTTP_H__
14 #pragma once
15 #ifndef __CPPUNWIND
16 #pragma warning(push)
17 #pragma warning(disable: 4702)
18 #endif
19 #ifndef _WINSOCKAPI_
20 #include <winsock2.h>
21 #endif
22 #include <atlutil.h>
23 #include <atlisapi.h>
24 #include <atlcoll.h>
25 #include <atlfile.h>
26 #define SECURITY_WIN32
27 #include <security.h>
28 #include <atlenc.h>
29 #ifndef _ATL_NO_DEFAULT_LIBS
30 #pragma comment(lib, "ws2_32.lib")
31 #pragma comment(lib, "SECUR32.LIB")
32 #endif // !_ATL_NO_DEFAULT_LIBS
34 #include <atlspriv.h>
36 #pragma warning(push)
37 #pragma warning(disable: 4625) // copy constructor could not be generated because a base class copy constructor is inaccessible
38 #pragma warning(disable: 4626) // assignment operator could not be generated because a base class assignment operator is inaccessible
40 #pragma pack(push,_ATL_PACKING)
41 namespace ATL {
43 template <class TSocketClass>
44 class CAtlHttpClientT;
45 class CAtlBaseAuthObject;
47 enum status_headerparse{
48 ATL_HEADER_PARSE_COMPLETE=0,
49 ATL_HEADER_PARSE_HEADERNOTCOMPLETE,
50 ATL_HEADER_PARSE_HEADERERROR
53 enum readstate{rs_init=0, rs_readheader, rs_scanheader, rs_readbody, rs_complete};
55 #define ATL_HEADER_END "\r\n\r\n"
56 #define ATL_HEADER_END_LEN 4
57 #define ATL_DW_HEADER_END 0x0a0d0a0d
58 #define ATL_FIELDNAME_DELIMITER _T(':')
59 #define ATL_MAX_FIELDNAME_LEN 1024
60 #define ATL_MAX_VALUE_LEN 1024
61 #define ATL_AUTH_HDR_SIZE 1024
62 #define ATL_READ_BUFF_SIZE 2048
63 #define ATL_INVALID_STATUS -1
64 #define ATL_HTTP_HEADER _T(" HTTP/1.1\r\n")
65 #define ATL_HTTP_HEADER_PROXY _T(" HTTP/1.1\r\n")
66 #ifndef ATL_HTTP_USERAGENT
67 #define ATL_HTTP_USERAGENT _T("User-Agent: Microsoft-ATL-Native/") _T(_ATL_VER_RBLD) _T("\r\n")
68 #endif
70 #define ATL_IS_INVALIDCREDHANDLE(x) ((x.dwLower==0xFFFFFFFF) && (x.dwUpper==0xFFFFFFFF))
71 #define ATL_HTTP_AUTHTYPE_NTLM _T("NTLM")
72 #define ATL_HTTP_AUTHTYPE_BASIC _T("BASIC")
73 #define ATL_HTTP_METHOD_GET _T("GET")
74 #define ATL_HTTP_METHOD_POST _T("POST")
76 #ifndef MAX_REALM_LEN
77 #define MAX_REALM_LEN 1024
78 #endif
80 #ifndef _ATL_MAX_AUTH_BUFF
81 #define _ATL_MAX_AUTH_BUFF 512
82 #endif
84 __interface IAuthInfo;
85 typedef bool (WINAPI *PFNATLCHUNKEDCB)(BYTE** ppData, DWORD *pdwSize, DWORD_PTR dwParam);
86 typedef bool (WINAPI *PFNATLSTATUSCALLBACK)(DWORD dwBytesSent, DWORD_PTR dwParam);
88 #define ATL_HTTP_FLAG_AUTO_REDIRECT 0x1
89 #define ATL_HTTP_FLAG_PROCESS_RESULT 0x2
90 #define ATL_HTTP_FLAG_SEND_CALLBACK 0x4
91 #define ATL_HTTP_FLAG_SEND_BLOCKS 0x8
92 #define ATL_HTTP_FLAG_INVALID_FLAGS 0xFFFFFFFF
94 #ifndef ATL_HTTP_DEFAULT_BLOCK_SIZE
95 #define ATL_HTTP_DEFAULT_BLOCK_SIZE 4096
96 #endif
98 #define ATL_HTTP_CLIENT_EMPTY_READ_RETRIES 5
100 struct ATL_NAVIGATE_DATA
102 LPCTSTR szExtraHeaders;
103 LPCTSTR szMethod;
104 LPCTSTR szDataType;
105 DWORD dwDataLen;
106 DWORD dwFlags;
107 DWORD dwTimeout;
108 DWORD dwSendBlockSize;
109 DWORD dwReadBlockSize;
110 DWORD_PTR m_lParamSend;
111 DWORD_PTR m_lParamRead;
112 DWORD_PTR m_lParamChunkCB;
113 short nPort;
114 BYTE *pData;
115 PFNATLCHUNKEDCB pfnChunkCallback;
116 PFNATLSTATUSCALLBACK pfnSendStatusCallback;
117 PFNATLSTATUSCALLBACK pfnReadStatusCallback;
120 class CAtlNavigateData : public ATL_NAVIGATE_DATA
122 public:
123 CAtlNavigateData() throw(); // public construction
124 CAtlNavigateData(const CAtlNavigateData &rhs);
125 CAtlNavigateData(const ATL_NAVIGATE_DATA &rhs);
126 CAtlNavigateData& operator=(const CAtlNavigateData &rhs);
127 CAtlNavigateData& operator=(const ATL_NAVIGATE_DATA &rhs);
128 DWORD SetFlags(DWORD dwNewFlags) throw(); // set all flags
129 DWORD GetFlags() throw(); // get value of flags
130 DWORD AddFlags(DWORD dwFlagsToAdd) throw(); // add one or more flags to existing flags
131 DWORD RemoveFlags(DWORD dwFlagsToRemove) throw(); // remove one or more flags from existing flags
132 LPCTSTR SetExtraHeaders(LPCTSTR szNewHeaders) throw(); // set the extra request headers
133 LPCTSTR GetExtraHeaders() throw(); // get the extra request headers
134 LPCTSTR SetMethod(LPCTSTR szNewMethod) throw(); // set the HTTP request method
135 LPCTSTR GetMethod() throw(); // get the HTTP request method
136 short SetPort(short newPort) throw(); // set the TCP port for this request
137 short GetPort() throw(); // get the TCP port for this request
138 void SetPostData(BYTE *pData, DWORD dwDataLen, LPCTSTR szDataType) throw(); // Set data to be sent as the reqeust entity body
139 DWORD SetSocketTimeout(DWORD dwNewTimeout) throw(); // Set the timeout for this socket
140 DWORD GetSocketTimeout() throw(); // Get the timeout for this socket
141 DWORD SetSendBlockSize(DWORD dwBlockSize) throw(); // Set the size of the blocks used to send data
142 DWORD GetSendBlockSize() throw(); // get the size of the blocks used to send data
143 DWORD SetReadBlockSize(DWORD dwBlockSize) throw(); // Set the size of the blocks used to send data
144 DWORD GetReadBlockSize() throw(); // get the size of the blocks used to send data
145 PFNATLCHUNKEDCB SetChunkCallback(PFNATLCHUNKEDCB pfn, DWORD_PTR dwParam) throw(); // set the callback function used for sending chunked data
146 PFNATLCHUNKEDCB GetChunkCallback() throw(); // get the chunked callback function
147 PFNATLSTATUSCALLBACK SetSendStatusCallback(PFNATLSTATUSCALLBACK pfn, DWORD_PTR dwData) throw(); // sets a function pointer to be called after bytes are sent over the socket
148 PFNATLSTATUSCALLBACK GetSendStatusCallback() throw(); // returns current status callback function
149 PFNATLSTATUSCALLBACK SetReadStatusCallback(PFNATLSTATUSCALLBACK pfn, DWORD_PTR dwData) throw();
150 PFNATLSTATUSCALLBACK GetReadStatusCallback() throw();
153 template <class TSocketClass>
154 class CAtlHttpClientT :
155 private TSocketClass
157 public:
158 CAtlHttpClientT() throw();
159 virtual ~CAtlHttpClientT()
163 // Use these functions to send an HTTP request and retrieve
164 // the response.
165 bool Navigate(
166 const CUrl* pUrl,
167 ATL_NAVIGATE_DATA *pNavData = NULL
168 ) throw(...);
170 bool Navigate(
171 LPCTSTR szServer,
172 LPCTSTR szPath,
173 ATL_NAVIGATE_DATA *pNavData = NULL
174 ) throw(...);
176 bool Navigate(
177 LPCTSTR szURL,
178 ATL_NAVIGATE_DATA *pNavData = NULL
179 ) throw(...);
182 // Performs navigation, sending data with Transfer-Coding: chunked
183 bool NavigateChunked(
184 const CUrl *pUrl,
185 ATL_NAVIGATE_DATA *pData
186 ) throw();
188 bool NavigateChunked(
189 LPCTSTR szServer,
190 LPCTSTR szPath,
191 ATL_NAVIGATE_DATA *pNavData
192 ) throw();
194 bool NavigateChunked(
195 LPCTSTR szURL,
196 ATL_NAVIGATE_DATA *pNavData
197 ) throw();
199 // Use to set/retrieve information about the proxy server used
200 // when making this request via a proxy server.
201 bool SetProxy(LPCTSTR szProxy = NULL, short nProxyPort = 0) throw();
202 void RemoveProxy() throw();
203 LPCTSTR GetProxy() const throw();
204 short GetProxyPort() const throw();
206 // Use these functions to add/remove/find objects that will
207 // be used to authorize request when a 401 Not Authorized response
208 // is received. This class maps these objects by scheme name in map.
209 // Override NegotiateAuth to change the way authorization negotiation occurs.
210 bool AddAuthObj(LPCTSTR szScheme, CAtlBaseAuthObject *pObject, IAuthInfo *pInfo=NULL) throw();
211 const CAtlBaseAuthObject* FindAuthObject(LPCTSTR szScheme) throw();
212 bool RemoveAuthObject(LPCTSTR szScheme) throw();
213 virtual bool NegotiateAuth(bool bProxy) throw();
216 // Retrieve the value of a response header
217 bool GetHeaderValue(LPCTSTR szName, CString& strValue) const throw();
218 bool GetHeaderValue(__in_z LPCTSTR szName, __out_ecount_part_z_opt(*pdwLen, *pdwLen) LPTSTR szBuffer, __inout DWORD *pdwLen) const throw();
220 DWORD GetResponseLength() throw(); // Get the number of bytes in the response
221 const BYTE* GetResponse() throw(); // Get the entire response
222 DWORD GetBodyLength() const throw(); // Get the length of the body of the response (everything after the \r\n\r\n)
223 const BYTE* GetBody() throw(); // Get the body of the response (length is determined by GetBodyLength())
224 DWORD GetRawResponseHeaderLength() throw(); // Get the length of the raw request headers
225 bool GetRawResponseHeader(LPBYTE szBuffer, DWORD *pdwLen) throw(); // Get the raw request headers
226 LPCURL GetCurrentUrl() const throw(); // Get a pointer to the current URL for this request
227 DWORD GetFlags() const throw(); // Retrieve flags used for processing this request
228 int GetStatus() throw(); // Get the HTTP status code that resulted from making this request
229 LPCTSTR GetMethod() throw(); // Get the HTTP method used for making this request
230 BYTE* GetPostData() throw(); // Get a pointer to raw data being sent with this request
231 DWORD GetPostDataLen() throw(); // Get the length of the raw data sent with this request
232 LPCTSTR GetPostDataType() throw(); // Get the data type (sent as Content-Type header) for this request
233 DWORD GetLastError() throw(); // Retrieves errors from the underlying socket
234 const SOCKET& GetSocket() throw(); // Retrieves the underlying socket. Be careful!
235 void Close() throw(); // Close the connection
236 DWORD SetSocketTimeout(DWORD dwNewTimeout) throw(); // Sets a new socket timeout, returns the old timeout.
237 DWORD GetSocketTimeout() throw(); // retrieves the current socket timeout
238 void AuthProtocolFailed(LPCTSTR szProto) throw(); // notifies us of failure to connect with the named protocol
239 const ATL_NAVIGATE_DATA* GetCurrentNavdata();
240 enum HTTP_RESPONSE_READ_STATUS
242 RR_OK = 0, // response was successfully processed
243 RR_FAIL, // an unknown error occurred reading the HTTP response
244 RR_STATUS_INVALID, // could not parse the status line
245 RR_PARSEHEADERS_FAILED, // failed to parse HTTP response headers
246 RR_READSOCKET_FAILED, // failed to read response data from socket
247 RR_READBODY_FAILED, // failed to successfully read the entity body of the HTTP response
248 RR_READCHUNKEDBODY_FAILED, // failed to read a 'Transfer-Encoding: chunked' response body
249 RR_NOT_READ // we haven't started reading the response.
251 HTTP_RESPONSE_READ_STATUS GetResponseStatus();
254 // Implementation
255 HTTP_RESPONSE_READ_STATUS ReadHttpResponse() throw();
256 void ResetConnection() throw();
257 bool ProcessStatus(DWORD dwFlags) throw();
258 bool BuildRequest(/*out*/CString *pstrRequest,
259 LPCTSTR szDataType=NULL,
260 LPCTSTR szExtraHeaders=NULL) throw();
262 void SetSilentLogonOk(bool bSet)
264 m_bSilentLogonOk = bSet;
266 protected:
267 DWORD WriteWithNoData(LPCSTR pRequest, DWORD dwRequestLen);
268 DWORD WriteWithCallback(LPCSTR pRequest, DWORD dwRequestLen);
269 DWORD WriteWithChunks(LPCSTR pRequest, DWORD dwRequestLen);
270 DWORD WriteWithData(LPCSTR pRequest, DWORD dwRequestLen);
271 bool SetDefaultUrl(LPCTSTR szUrl, short nPortNumber=ATL_URL_DEFAULT_HTTP_PORT) throw();
272 bool SetDefaultUrl(LPCURL pUrl, short nPortNumber=ATL_URL_DEFAULT_HTTP_PORT) throw();
273 bool SetDefaultMethod(LPCTSTR szMethod) throw();
274 void InitializeObject() throw();
275 void ResetRequest() throw();
276 bool ReadSocket() throw();
277 unsigned char* FindHeaderEnd(unsigned char** ppBegin) throw();
278 bool LookupRegProxy() throw();
279 bool DisconnectIfRequired() throw();
280 bool ConnectSocket() throw();
282 long GetContentLength() throw();
283 LPCSTR NextLine(BYTE* pCurr) throw();
284 bool IsMsgBodyChunked() throw();
285 LPCSTR FindEndOfHeader(LPCSTR pszStart) throw();
286 bool DecodeHeader(LPCSTR pHeaderStart, LPCSTR pHeaderEnd) throw();
287 virtual void OnSetCookie(LPCTSTR /*szCookie*/) throw();
288 LPCSTR ParseStatusLine(BYTE* pBuffer) throw();
289 int CrackResponseHeader(LPCSTR pBuffer, /*out*/ LPCSTR *pEnd) throw();
290 bool ReadBody(int nContentLen, int nCurrentBodyLen) throw();
291 bool ReadChunkedBody() throw();
292 bool ReconnectIfRequired() throw();
293 bool CompleteURL(CString& strURL) throw();
294 bool ProcessObjectMoved() throw();
295 bool _SetDefaultUrl(LPCTSTR szURL, short nPort) throw();
297 enum CHUNK_STATE{
298 READ_CHUNK_SIZE, // need to read the size of a chunk.
299 READ_CHUNK_SIZE_FOOTER,
300 READ_CHUNK_DATA, // need to read the actual data
301 READ_CHUNK_DATA_FOOTER, // need to read the chunk footer.
302 READ_CHUNK_TRAILER, // Read the trailer headers at the end of the chunk data
303 READ_CHUNK_TRAILER_FOOTER, // read the final crlf
304 CHUNK_READ_DATA_COMPLETE, // done reading chunk data.
307 enum CHUNK_LEX_RESULT{
308 LEX_OK,
309 LEX_OUTOFDATA,
310 LEX_ERROR,
311 LEX_TRAILER_COMPLETE
314 CHUNK_LEX_RESULT get_chunked_size(__deref_inout char *&pBuffStart, __deref_inout char *&pBuffEnd, __inout long* pnChunkSize) throw();
315 bool move_leftover_bytes(__in_ecount(nLen) char *pBufferStart, __in int nLen, __deref_inout char *&pBuffStart, __deref_inout char *&pBuffEnd) throw();
316 CHUNK_LEX_RESULT get_chunked_data(__deref_inout char *&pBufferStart, __deref_inout char *&pBufferEnd, long nChunkSize,
317 __deref_out_ecount_part(*pnDataLen, *pnDataLen) char **ppDataStart, __inout long *pnDataLen) throw();
318 CHUNK_LEX_RESULT consume_chunk_trailer(__deref_inout char *&pBufferStart, __deref_inout char *pBufferEnd) throw();
319 CHUNK_LEX_RESULT consume_chunk_footer(__deref_inout char *&pBufferStart, __deref_inout char *&pBufferEnd) throw();
321 typedef CAtlMap<
322 CString,
323 CString,
324 CStringElementTraitsI<CString>,
325 CStringElementTraitsI<CString>
326 > HeaderMapType;
328 typedef CAtlMap <
329 CString,
330 CAtlBaseAuthObject*,
331 CStringElementTraitsI<CString>
332 > AuthMapType;
334 typedef CAtlArray<
335 CString,
336 CStringElementTraitsI<CString>
337 > AuthListType;
339 HeaderMapType m_HeaderMap; // Map of response headers
340 AuthMapType m_AuthMap; // Map of pointers to authorization objects.
341 AuthListType m_AuthTypes; // list of authorization types the server is willing to use.
342 BOOL m_bSilentLogonOk;
343 CAtlIsapiBuffer<> m_current; // The entire response
344 CUrl m_urlCurrent; // URL of current request
346 CString m_strMethod; // Current request method.
347 CString m_strProxy; // Path to current proxy server.
349 long m_nStatus; // Current response status (from status line)
350 short m_nProxyPort; // Port used on current proxy server
351 DWORD m_dwBodyLen; // Length of body
352 DWORD m_dwHeaderLen; // Length of current raw headers
353 DWORD m_dwHeaderStart;
354 BYTE *m_pCurrent;
355 BYTE *m_pEnd; // the end of the data we've read fromt he socket;
356 ATL_NAVIGATE_DATA *m_pNavData;
357 HTTP_RESPONSE_READ_STATUS m_LastResponseParseError;
358 }; //CAtlHttpClientT
359 typedef CAtlHttpClientT<ZEvtSyncSocket> CAtlHttpClient;
362 // Interface used to acquire authentication information from clients
363 __interface IAuthInfo
365 HRESULT GetPassword(__out_ecount_part_z_opt(*pdwBuffSize, *pdwBuffSize) LPTSTR szPwd, __inout DWORD *pdwBuffSize);
366 HRESULT GetUsername(__out_ecount_part_z_opt(*pdwBuffSize, *pdwBuffSize) LPTSTR szUid, __inout DWORD *pdwBuffSize);
367 HRESULT GetDomain(__out_ecount_part_z_opt(*pdwBuffSize, *pdwBuffSize) LPTSTR szDomain, __inout DWORD *pdwBuffSize);
369 typedef HRESULT (IAuthInfo::*PFNAUTHFUNC)(LPTSTR szPwd, DWORD *pdwSize);
371 // pure virtual class that describes required functions for authoriztion
372 // objects
373 class CAtlBaseAuthObject
375 public:
376 CAtlBaseAuthObject();
377 virtual bool Authenticate(LPCTSTR szAuthTypes, bool bProxy) = 0;
378 virtual void Init(CAtlHttpClient *pSocket, IAuthInfo *pAuthInfo) = 0;
379 bool m_bFailed;
382 // strings used for authentication.
383 extern __declspec(selectany)const TCHAR * const g_pszWWWAuthenticate = _T("www-authenticate");
384 extern __declspec(selectany)const TCHAR * const g_pszProxyAuthenticate = _T("proxy-authenticate");
386 // Performs NTLM authentication
387 class CNTLMAuthObject :
388 public CAtlBaseAuthObject
390 public:
391 virtual ~CNTLMAuthObject() throw();
392 CNTLMAuthObject() throw();
393 CNTLMAuthObject(IAuthInfo *pAuthInfo) throw();
394 void SetAuthInfo(IAuthInfo *pAuthInfo) throw();
395 bool GetCredentialNames(CString& theName);
397 // Implementation
398 // Called by the CAtlHttpClient class to authenticate a user.
399 virtual void Init(CAtlHttpClient *pSocket, IAuthInfo *pAuthInfo=NULL) throw();
401 // Called by the CAtlHttpClient class to initialize this authentication object.
402 virtual bool Authenticate(LPCTSTR szAuthTypes, bool bProxy) throw();
403 protected:
404 bool AcquireCredHandle() throw();
405 // This function creates an NTML Authorization header
406 // and sends it to the HTTP server.
407 bool SendSecurityInfo(SecBuffer *pSecBuffer, LPSTR *pszBuffer) throw();
408 bool DoNTLMAuthenticate() throw();
410 IAuthInfo *m_pAuthInfo;
411 CAtlHttpClient *m_pSocket;
412 CredHandle m_hCredentials;
413 int m_nMaxTokenSize;
414 TimeStamp m_ts;
415 bool m_bProxy;
416 static const char * const m_pszFmtWWW;
417 static const char * const m_pszFmtProxy;
418 CAtlNavigateData m_CurrentRequestData;
420 }; // CNTLMAuthObject
422 // Performs BASIC authentication for an CAtlHttpClient
423 // object. Caller must implement an IAuthInfo interface
424 // and pass it to this object before this object attempts
425 // to authenticate or authentication will fail.
426 class CBasicAuthObject :
427 public CAtlBaseAuthObject
429 public:
430 CBasicAuthObject() throw();
431 CBasicAuthObject(IAuthInfo *pAuthInfo) throw();
432 void SetAuthInfo(IAuthInfo *pAuthInfo) throw();
433 LPCTSTR GetRealm() throw(); // Retrieve's the realm being used.
435 // Implementation
436 // Called by the CAtlHttpClient class to authenticate a user.
437 virtual bool Authenticate(LPCTSTR szAuthTypes, bool bProxy) throw();
439 // Called by the CAtlHttpClient class to initialize this authentication object.
440 virtual void Init(CAtlHttpClient *pSocket, IAuthInfo *pAuthInfo=NULL) throw();
441 protected:
442 bool DoBasicAuthenticate() throw();
443 bool CrackRealm(LPCTSTR szHeader) throw();
445 IAuthInfo *m_pAuthInfo;
446 CAtlHttpClient *m_pClient;
447 TCHAR m_szRealm[MAX_REALM_LEN];
448 bool m_bProxy;
449 static const char * const m_pszFmtWWW;
450 static const char * const m_pszFmtProxy;
451 }; // CBasicAuthObject
453 __declspec(selectany)const char * const CBasicAuthObject::m_pszFmtWWW = "Authorization: Basic ";
454 __declspec(selectany)const char * const CBasicAuthObject::m_pszFmtProxy = "Proxy-Authorization: Basic ";
455 __declspec(selectany)const char * const CNTLMAuthObject::m_pszFmtWWW = "Authorization: NTLM %s\r\n";
456 __declspec(selectany)const char * const CNTLMAuthObject::m_pszFmtProxy = "Proxy-Authorization: NTLM %s\r\n";
458 typedef CTempBuffer<TCHAR, _ATL_MAX_AUTH_BUFF> CAuthInfoBuffType;
459 inline bool _AtlGetAuthInfoHelper(IAuthInfo *pObj, PFNAUTHFUNC pFunc, CAuthInfoBuffType& buff, DWORD *dwLen) throw()
461 ATLENSURE_RETURN_VAL(pObj, false);
462 ATLENSURE_RETURN_VAL(pFunc, false);
463 DWORD dwSize = _ATL_MAX_AUTH_BUFF;
464 bool bRet = true;
465 TCHAR *szValue = NULL;
466 _ATLTRY
468 szValue = buff.Allocate(_ATL_MAX_AUTH_BUFF);
469 HRESULT hr = E_FAIL;
470 if (szValue)
472 hr = (pObj->*pFunc)(szValue, &dwSize);
473 if (hr != S_OK)
475 if (hr == E_OUTOFMEMORY)
477 // buffer not big enough, try to allocate
478 szValue = buff.Reallocate(dwSize);
479 if (szValue)
481 // retry the call
482 if (S_OK != (pObj->*pFunc)(szValue, &dwSize))
483 bRet = false;
485 else
486 bRet = false;
488 else
489 bRet = false;
492 else
493 bRet = false;
496 _ATLCATCHALL()
498 bRet = false;
500 if (bRet)
501 *dwLen = (DWORD)_tcslen(szValue);
502 else
503 *dwLen = 0;
504 return bRet;
508 // Security Service Provider Interface (sspi) Helper classes
509 // These classes are used as helpers for structures used in
510 // SSPI functions.
512 class CSecAuthIdentity : public SEC_WINNT_AUTH_IDENTITY_EX
514 public:
515 CSecAuthIdentity() throw()
517 Version = SEC_WINNT_AUTH_IDENTITY_VERSION;
518 Length = sizeof(SEC_WINNT_AUTH_IDENTITY_EX);
519 #ifdef _UNICODE
520 Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
521 #else
522 Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
523 #endif
527 bool Init(IAuthInfo *pAuthInfo) throw()
529 if (!pAuthInfo)
530 return false;
532 if (!_AtlGetAuthInfoHelper(pAuthInfo, &IAuthInfo::GetUsername, buffUserName, &UserLength))
533 return false;
535 if (!_AtlGetAuthInfoHelper(pAuthInfo, &IAuthInfo::GetPassword, buffPassword, &PasswordLength))
536 return false;
538 if (!_AtlGetAuthInfoHelper(pAuthInfo, &IAuthInfo::GetDomain, buffDomain, &DomainLength))
539 return false;
541 #ifndef _UNICODE
542 User = (unsigned char*)(char*)buffUserName;
543 Domain = DomainLength > 0 ? (unsigned char*)(char*)buffDomain : 0;
544 Password = PasswordLength > 0 ? (unsigned char*)(char*)buffPassword : 0;
545 #else
546 // have to cast to unsigned short *, because SEC_WINNT_AUTH_IDENTITY_EXW
547 // uses unsigned short instead of wchar_t
548 User = (unsigned short *)(wchar_t*)buffUserName;
549 Domain = DomainLength > 0 ? (unsigned short *)(wchar_t*)buffDomain : 0;
550 Password = PasswordLength > 0 ? (unsigned short *)(wchar_t*)buffPassword : 0;
551 #endif
552 return true;
555 protected:
556 CAuthInfoBuffType buffUserName;
557 CAuthInfoBuffType buffPassword;
558 CAuthInfoBuffType buffDomain;
559 }; // CSecAuthIdentity
561 class CSecBuffer : public SecBuffer
563 public:
564 CSecBuffer() throw()
566 cbBuffer = 0;
567 BufferType = 0;
568 pvBuffer = NULL;
569 m_cbAlloc = 0;
572 ~CSecBuffer() throw()
574 delete [] static_cast<unsigned char*>(pvBuffer);
577 bool SetSize(unsigned long nSize) throw()
579 if (!nSize)
580 return false;
582 if (pvBuffer)
584 delete [] static_cast<unsigned char*>(pvBuffer);
585 pvBuffer = NULL;
586 cbBuffer = 0;
587 m_cbAlloc = 0;
590 ATLTRY(pvBuffer = static_cast<void*>(new unsigned char[nSize]));
591 if (pvBuffer)
593 cbBuffer = nSize;
594 BufferType = SECBUFFER_TOKEN;
595 m_cbAlloc = cbBuffer;
596 return true;
598 return false;
601 bool ClearBuffer(unsigned long nSize) throw()
603 if(nSize > m_cbAlloc)
604 return false;
606 ZeroMemory(pvBuffer, nSize);
607 cbBuffer = nSize;
608 return true;
611 unsigned long Size()
613 return cbBuffer;
616 unsigned char *Buffer() throw()
618 return static_cast<unsigned char*>(pvBuffer);
621 operator SecBuffer*() throw()
623 return (SecBuffer*)this;
626 protected:
627 unsigned long m_cbAlloc;
629 }; // CSecBuffer
631 class CSecBufferDesc : public SecBufferDesc
633 public:
634 CSecBufferDesc() throw()
636 ulVersion = SECBUFFER_VERSION;
637 cBuffers = 0;
638 pBuffers = NULL;
641 ~CSecBufferDesc() throw()
643 cBuffers = 0;
645 if (pBuffers)
647 CSecBuffer *psb = (CSecBuffer*)pBuffers;
648 delete [] psb;
652 // index is 0 based
653 CSecBuffer* Buffers(unsigned int i) throw()
655 if (i < cBuffers)
657 return (CSecBuffer*)(&pBuffers[i]);
660 return NULL;
663 bool AddBuffers(unsigned int nCount, unsigned int nBufferSize) throw()
665 if (!nCount)
666 return true;
668 if (cBuffers == 0)
670 CSecBuffer *pSecBuffer = NULL;
671 ATLTRY(pSecBuffer = new CSecBuffer[nCount]);
672 if (!pSecBuffer)
673 return false;
674 CAutoVectorPtr<CSecBuffer> spSecBuffer(pSecBuffer);
676 for (unsigned int i=0; i<nCount; i++)
678 if (!pSecBuffer[i].SetSize(nBufferSize))
679 return false;
681 cBuffers = nCount;
682 pBuffers = (SecBuffer*)spSecBuffer.Detach();
684 else // realloc
686 CSecBuffer *pSecBuffer = NULL;
687 ATLTRY(pSecBuffer = new CSecBuffer[nCount + cBuffers]);
688 if (!pSecBuffer)
689 return false;
690 CAutoVectorPtr<CSecBuffer> spSecBuffer(pSecBuffer);
691 Checked::memcpy_s(pSecBuffer, (nCount + cBuffers)*sizeof(CSecBuffer), pBuffers, cBuffers*sizeof(CSecBuffer));
692 delete [] pBuffers;
693 pBuffers=NULL;
695 // initialize new buffers
696 for (unsigned int i=0; i<nCount; i++)
698 if (!pSecBuffer[cBuffers+i].SetSize(nBufferSize))
699 return false;
701 pBuffers = spSecBuffer.Detach();
702 cBuffers += nCount;
704 return true;
707 operator PSecBufferDesc() throw()
709 return static_cast<PSecBufferDesc>(this);
711 }; // CSecBufferDesc
713 } // namespace ATL
716 #include <atlhttp.inl>
718 #pragma pack(pop)
719 #pragma warning(pop)
721 #ifndef __CPPUNWIND
722 #pragma warning(pop)
723 #endif
725 #endif // __ATLHTTP_H__