mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 10:45:24 +00:00
[URLMON]
- Sync to WINE 1.3.4 [WININET] - Add a forgotten change to the diff [WINHTTP] - Sync to WINE 1.3.4 - Sync the inet_ntop.c change from wininet - Update the diff svn path=/trunk/; revision=49083
This commit is contained in:
parent
efe34232b4
commit
411c11b801
|
@ -1077,8 +1077,11 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
|
|||
}
|
||||
|
||||
if(This->to_object) {
|
||||
if(!(This->state & BINDING_OBJAVAIL))
|
||||
if(!(This->state & BINDING_OBJAVAIL)) {
|
||||
IBinding_AddRef(BINDING(This));
|
||||
create_object(This);
|
||||
IBinding_Release(BINDING(This));
|
||||
}
|
||||
}else {
|
||||
STGMEDIUM stgmed;
|
||||
HRESULT hres;
|
||||
|
@ -1519,7 +1522,7 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I
|
|||
}
|
||||
|
||||
if(binding_ctx) {
|
||||
set_binding_sink(binding->protocol, PROTSINK(binding));
|
||||
set_binding_sink(binding->protocol, PROTSINK(binding), BINDINF(binding));
|
||||
if(binding_ctx->redirect_url)
|
||||
IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url);
|
||||
report_data(binding, 0, 0, 0);
|
||||
|
|
|
@ -382,7 +382,7 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
|
|||
if(This->filter_proxy)
|
||||
IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
|
||||
|
||||
set_binding_sink(PROTOCOL(This), NULL);
|
||||
set_binding_sink(PROTOCOL(This), NULL, NULL);
|
||||
|
||||
if(This->notif_hwnd)
|
||||
release_notif_hwnd(This->notif_hwnd);
|
||||
|
@ -488,7 +488,7 @@ static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocol *iface)
|
|||
return IInternetProtocol_UnlockRequest(This->protocol_handler);
|
||||
}
|
||||
|
||||
void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink)
|
||||
void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
|
||||
{
|
||||
BindProtocol *This = PROTOCOL_THIS(bind_protocol);
|
||||
IInternetProtocolSink *prev_sink;
|
||||
|
@ -505,6 +505,12 @@ void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *s
|
|||
service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
|
||||
if(service_provider)
|
||||
IServiceProvider_Release(service_provider);
|
||||
|
||||
if(bind_info)
|
||||
IInternetBindInfo_AddRef(bind_info);
|
||||
bind_info = InterlockedExchangePointer((void**)&This->bind_info, bind_info);
|
||||
if(bind_info)
|
||||
IInternetBindInfo_Release(bind_info);
|
||||
}
|
||||
|
||||
IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
|
||||
|
@ -619,10 +625,7 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz
|
|||
if(urlmon_protocol)
|
||||
IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
|
||||
|
||||
IInternetBindInfo_AddRef(pOIBindInfo);
|
||||
This->bind_info = pOIBindInfo;
|
||||
|
||||
set_binding_sink(PROTOCOL(This), pOIProtSink);
|
||||
set_binding_sink(PROTOCOL(This), pOIProtSink, pOIBindInfo);
|
||||
|
||||
hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
|
||||
if(SUCCEEDED(hres)) {
|
||||
|
@ -670,7 +673,7 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD
|
|||
This->filter_proxy = NULL;
|
||||
}
|
||||
|
||||
set_binding_sink(PROTOCOL(This), NULL);
|
||||
set_binding_sink(PROTOCOL(This), NULL, NULL);
|
||||
|
||||
if(This->bind_info) {
|
||||
IInternetBindInfo_Release(This->bind_info);
|
||||
|
|
|
@ -119,22 +119,22 @@ static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWOR
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static void on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text)
|
||||
static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
if(!This->callback)
|
||||
return;
|
||||
return S_OK;
|
||||
|
||||
hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
|
||||
if(FAILED(hres))
|
||||
FIXME("OnProgress failed: %08x\n", hres);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
|
||||
ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
|
||||
{
|
||||
DownloadBSC *This = STATUSCLB_THIS(iface);
|
||||
HRESULT hres = S_OK;
|
||||
|
||||
TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
|
||||
debugstr_w(szStatusText));
|
||||
|
@ -146,11 +146,11 @@ static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG u
|
|||
case BINDSTATUS_ENDDOWNLOADDATA:
|
||||
case BINDSTATUS_SENDINGREQUEST:
|
||||
case BINDSTATUS_MIMETYPEAVAILABLE:
|
||||
on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||
hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||
break;
|
||||
|
||||
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
|
||||
on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||
hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||
This->cache_file = heap_strdupW(szStatusText);
|
||||
break;
|
||||
|
||||
|
@ -161,7 +161,7 @@ static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG u
|
|||
FIXME("Unsupported status %u\n", ulStatusCode);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
|
||||
|
|
|
@ -17,38 +17,46 @@
|
|||
*/
|
||||
|
||||
#include "urlmon_main.h"
|
||||
#include "winreg.h"
|
||||
#include "shlwapi.h"
|
||||
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
||||
|
||||
typedef struct {
|
||||
const IInternetProtocolVtbl *lpIInternetProtocolVtbl;
|
||||
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
||||
const IInternetProtocolExVtbl *lpIInternetProtocolExVtbl;
|
||||
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
||||
|
||||
HANDLE file;
|
||||
ULONG size;
|
||||
LONG priority;
|
||||
|
||||
LONG ref;
|
||||
} FileProtocol;
|
||||
|
||||
#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
|
||||
#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
|
||||
#define PROTOCOLEX(x) ((IInternetProtocolEx*) &(x)->lpIInternetProtocolExVtbl)
|
||||
|
||||
#define PROTOCOL_THIS(iface) DEFINE_THIS(FileProtocol, IInternetProtocol, iface)
|
||||
#define PROTOCOL_THIS(iface) DEFINE_THIS(FileProtocol, IInternetProtocolEx, iface)
|
||||
|
||||
static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
|
||||
static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
*ppv = NULL;
|
||||
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
||||
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
||||
*ppv = PROTOCOL(This);
|
||||
*ppv = PROTOCOLEX(This);
|
||||
}else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
|
||||
TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
|
||||
*ppv = PROTOCOL(This);
|
||||
*ppv = PROTOCOLEX(This);
|
||||
}else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
|
||||
TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
|
||||
*ppv = PROTOCOL(This);
|
||||
*ppv = PROTOCOLEX(This);
|
||||
}else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
|
||||
TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
|
||||
*ppv = PROTOCOLEX(This);
|
||||
}else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
|
||||
TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
|
||||
*ppv = PRIORITY(This);
|
||||
|
@ -63,7 +71,7 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocol *iface, REFI
|
|||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static ULONG WINAPI FileProtocol_AddRef(IInternetProtocol *iface)
|
||||
static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
LONG ref = InterlockedIncrement(&This->ref);
|
||||
|
@ -71,7 +79,7 @@ static ULONG WINAPI FileProtocol_AddRef(IInternetProtocol *iface)
|
|||
return ref;
|
||||
}
|
||||
|
||||
static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
||||
static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
LONG ref = InterlockedDecrement(&This->ref);
|
||||
|
@ -79,7 +87,7 @@ static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
|||
TRACE("(%p) ref=%d\n", This, ref);
|
||||
|
||||
if(!ref) {
|
||||
if(This->file)
|
||||
if(This->file != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(This->file);
|
||||
heap_free(This);
|
||||
|
||||
|
@ -89,27 +97,168 @@ static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
|||
return ref;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
||||
static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
|
||||
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
|
||||
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
BINDINFO bindinfo;
|
||||
DWORD grfBINDF = 0;
|
||||
LARGE_INTEGER size;
|
||||
DWORD len;
|
||||
LPWSTR url, mime = NULL, file_name;
|
||||
WCHAR null_char = 0;
|
||||
BOOL first_call = FALSE;
|
||||
IUri *uri;
|
||||
HRESULT hres;
|
||||
|
||||
static const WCHAR wszFile[] = {'f','i','l','e',':'};
|
||||
|
||||
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
||||
pOIBindInfo, grfPI, dwReserved);
|
||||
|
||||
if(!szUrl || strlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR)
|
||||
|| memcmp(szUrl, wszFile, sizeof(wszFile)))
|
||||
hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = IInternetProtocolEx_StartEx(PROTOCOLEX(This), uri, pOIProtSink, pOIBindInfo,
|
||||
grfPI, (HANDLE*)dwReserved);
|
||||
|
||||
IUri_Release(uri);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%p)\n", This, pProtocolData);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
|
||||
DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)->(%08x)\n", This, dwOptions);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Suspend(IInternetProtocolEx *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Resume(IInternetProtocolEx *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Read(IInternetProtocolEx *iface, void *pv,
|
||||
ULONG cb, ULONG *pcbRead)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
DWORD read = 0;
|
||||
|
||||
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
|
||||
|
||||
if (pcbRead)
|
||||
*pcbRead = 0;
|
||||
|
||||
if(This->file == INVALID_HANDLE_VALUE)
|
||||
return INET_E_DATA_NOT_AVAILABLE;
|
||||
|
||||
if (!ReadFile(This->file, pv, cb, &read, NULL))
|
||||
return INET_E_DOWNLOAD_FAILURE;
|
||||
|
||||
if(pcbRead)
|
||||
*pcbRead = read;
|
||||
|
||||
return cb == read ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
|
||||
DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)->(%08x)\n", This, dwOptions);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_UnlockRequest(IInternetProtocolEx *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static inline HRESULT report_result(IInternetProtocolSink *protocol_sink, HRESULT hres, DWORD res)
|
||||
{
|
||||
IInternetProtocolSink_ReportResult(protocol_sink, hres, res, NULL);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT open_file(FileProtocol *This, const WCHAR *path, IInternetProtocolSink *protocol_sink)
|
||||
{
|
||||
LARGE_INTEGER size;
|
||||
HANDLE file;
|
||||
|
||||
file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(file == INVALID_HANDLE_VALUE)
|
||||
return report_result(protocol_sink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
|
||||
|
||||
if(!GetFileSizeEx(file, &size)) {
|
||||
CloseHandle(file);
|
||||
return report_result(protocol_sink, INET_E_RESOURCE_NOT_FOUND, GetLastError());
|
||||
}
|
||||
|
||||
This->file = file;
|
||||
This->size = size.u.LowPart;
|
||||
|
||||
IInternetProtocolSink_ReportProgress(protocol_sink,
|
||||
BINDSTATUS_CACHEFILENAMEAVAILABLE, path);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
|
||||
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
|
||||
DWORD grfPI, HANDLE *dwReserved)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
BINDINFO bindinfo;
|
||||
DWORD grfBINDF = 0;
|
||||
DWORD scheme;
|
||||
LPWSTR mime = NULL;
|
||||
WCHAR null_char = 0;
|
||||
BSTR path, url;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
|
||||
pOIBindInfo, grfPI, dwReserved);
|
||||
|
||||
if(!pUri)
|
||||
return E_INVALIDARG;
|
||||
|
||||
scheme = 0;
|
||||
hres = IUri_GetScheme(pUri, &scheme);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(scheme != URL_SCHEME_FILE)
|
||||
return E_INVALIDARG;
|
||||
|
||||
memset(&bindinfo, 0, sizeof(bindinfo));
|
||||
|
@ -122,170 +271,52 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
|||
|
||||
ReleaseBindInfo(&bindinfo);
|
||||
|
||||
len = lstrlenW(szUrl)+16;
|
||||
url = heap_alloc(len*sizeof(WCHAR));
|
||||
hres = CoInternetParseUrl(szUrl, PARSE_ENCODE, 0, url, len, &len, 0);
|
||||
if(FAILED(hres)) {
|
||||
heap_free(url);
|
||||
return hres;
|
||||
}
|
||||
|
||||
if(!(grfBINDF & BINDF_FROMURLMON))
|
||||
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL);
|
||||
|
||||
if(!This->file) {
|
||||
WCHAR *ptr;
|
||||
if(This->file != INVALID_HANDLE_VALUE) {
|
||||
IInternetProtocolSink_ReportData(pOIProtSink,
|
||||
BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
|
||||
This->size, This->size);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
first_call = TRUE;
|
||||
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char);
|
||||
|
||||
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, &null_char);
|
||||
hres = IUri_GetPath(pUri, &path);
|
||||
if(FAILED(hres)) {
|
||||
ERR("GetPath failed: %08x\n", hres);
|
||||
return report_result(pOIProtSink, hres, 0);
|
||||
}
|
||||
|
||||
file_name = url+sizeof(wszFile)/sizeof(WCHAR);
|
||||
|
||||
/* Strip both forward and back slashes */
|
||||
if( (file_name[0] == '/' && file_name[1] == '/') ||
|
||||
(file_name[0] == '\\' && file_name[1] == '\\'))
|
||||
file_name += 2;
|
||||
if(*file_name == '/')
|
||||
file_name++;
|
||||
|
||||
for(ptr = file_name; *ptr; ptr++) {
|
||||
if(*ptr == '?' || *ptr == '#') {
|
||||
*ptr = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(file_name[1] == '|')
|
||||
file_name[1] = ':';
|
||||
|
||||
This->file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if(This->file == INVALID_HANDLE_VALUE) {
|
||||
This->file = NULL;
|
||||
IInternetProtocolSink_ReportResult(pOIProtSink, INET_E_RESOURCE_NOT_FOUND,
|
||||
GetLastError(), NULL);
|
||||
heap_free(url);
|
||||
return INET_E_RESOURCE_NOT_FOUND;
|
||||
}
|
||||
|
||||
IInternetProtocolSink_ReportProgress(pOIProtSink,
|
||||
BINDSTATUS_CACHEFILENAMEAVAILABLE, file_name);
|
||||
hres = open_file(This, path, pOIProtSink);
|
||||
SysFreeString(path);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = IUri_GetDisplayUri(pUri, &url);
|
||||
if(hres == S_OK) {
|
||||
hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0);
|
||||
SysFreeString(url);
|
||||
if(SUCCEEDED(hres)) {
|
||||
IInternetProtocolSink_ReportProgress(pOIProtSink,
|
||||
(grfBINDF & BINDF_FROMURLMON) ?
|
||||
BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
|
||||
BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
|
||||
mime);
|
||||
CoTaskMemFree(mime);
|
||||
}
|
||||
}
|
||||
|
||||
heap_free(url);
|
||||
IInternetProtocolSink_ReportData(pOIProtSink,
|
||||
BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
|
||||
This->size, This->size);
|
||||
|
||||
if(GetFileSizeEx(This->file, &size))
|
||||
IInternetProtocolSink_ReportData(pOIProtSink,
|
||||
BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
|
||||
size.u.LowPart, size.u.LowPart);
|
||||
|
||||
if(first_call)
|
||||
IInternetProtocolSink_ReportResult(pOIProtSink, S_OK, 0, NULL);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%p)\n", This, pProtocolData);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
|
||||
DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)->(%08x)\n", This, dwOptions);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Suspend(IInternetProtocol *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Resume(IInternetProtocol *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)\n", This);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Read(IInternetProtocol *iface, void *pv,
|
||||
ULONG cb, ULONG *pcbRead)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
DWORD read = 0;
|
||||
|
||||
TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
|
||||
|
||||
if (pcbRead)
|
||||
*pcbRead = 0;
|
||||
|
||||
if(!This->file)
|
||||
return INET_E_DATA_NOT_AVAILABLE;
|
||||
|
||||
if (!ReadFile(This->file, pv, cb, &read, NULL))
|
||||
return INET_E_DOWNLOAD_FAILURE;
|
||||
|
||||
if(pcbRead)
|
||||
*pcbRead = read;
|
||||
|
||||
return cb == read ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
|
||||
DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)->(%08x)\n", This, dwOptions);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FileProtocol_UnlockRequest(IInternetProtocol *iface)
|
||||
{
|
||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||
|
||||
TRACE("(%p)\n", This);
|
||||
|
||||
return S_OK;
|
||||
return report_result(pOIProtSink, S_OK, 0);
|
||||
}
|
||||
|
||||
#undef PROTOCOL_THIS
|
||||
|
||||
static const IInternetProtocolVtbl FileProtocolVtbl = {
|
||||
static const IInternetProtocolExVtbl FileProtocolExVtbl = {
|
||||
FileProtocol_QueryInterface,
|
||||
FileProtocol_AddRef,
|
||||
FileProtocol_Release,
|
||||
|
@ -298,7 +329,8 @@ static const IInternetProtocolVtbl FileProtocolVtbl = {
|
|||
FileProtocol_Read,
|
||||
FileProtocol_Seek,
|
||||
FileProtocol_LockRequest,
|
||||
FileProtocol_UnlockRequest
|
||||
FileProtocol_UnlockRequest,
|
||||
FileProtocol_StartEx
|
||||
};
|
||||
|
||||
#define PRIORITY_THIS(iface) DEFINE_THIS(FileProtocol, InternetPriority, iface)
|
||||
|
@ -307,19 +339,19 @@ static HRESULT WINAPI FilePriority_QueryInterface(IInternetPriority *iface,
|
|||
REFIID riid, void **ppv)
|
||||
{
|
||||
FileProtocol *This = PRIORITY_THIS(iface);
|
||||
return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
|
||||
return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
|
||||
}
|
||||
|
||||
static ULONG WINAPI FilePriority_AddRef(IInternetPriority *iface)
|
||||
{
|
||||
FileProtocol *This = PRIORITY_THIS(iface);
|
||||
return IInternetProtocol_AddRef(PROTOCOL(This));
|
||||
return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
|
||||
}
|
||||
|
||||
static ULONG WINAPI FilePriority_Release(IInternetPriority *iface)
|
||||
{
|
||||
FileProtocol *This = PRIORITY_THIS(iface);
|
||||
return IInternetProtocol_Release(PROTOCOL(This));
|
||||
return IInternetProtocolEx_Release(PROTOCOLEX(This));
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FilePriority_SetPriority(IInternetPriority *iface, LONG nPriority)
|
||||
|
@ -362,13 +394,12 @@ HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
|
|||
|
||||
ret = heap_alloc(sizeof(FileProtocol));
|
||||
|
||||
ret->lpIInternetProtocolVtbl = &FileProtocolVtbl;
|
||||
ret->lpIInternetProtocolExVtbl = &FileProtocolExVtbl;
|
||||
ret->lpInternetPriorityVtbl = &FilePriorityVtbl;
|
||||
ret->file = NULL;
|
||||
ret->file = INVALID_HANDLE_VALUE;
|
||||
ret->priority = 0;
|
||||
ret->ref = 1;
|
||||
|
||||
*ppobj = PROTOCOL(ret);
|
||||
|
||||
*ppobj = PROTOCOLEX(ret);
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -36,14 +36,21 @@ typedef struct {
|
|||
|
||||
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface)
|
||||
|
||||
static HRESULT FtpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
|
||||
static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
|
||||
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||
{
|
||||
FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
||||
BSTR url;
|
||||
HRESULT hres;
|
||||
|
||||
hres = IUri_GetAbsoluteUri(uri, &url);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
|
||||
request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
|
||||
(DWORD_PTR)&This->base);
|
||||
SysFreeString(url);
|
||||
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
||||
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
||||
return INET_E_RESOURCE_NOT_FOUND;
|
||||
|
@ -145,6 +152,8 @@ static HRESULT WINAPI FtpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
|||
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||
{
|
||||
FtpProtocol *This = PROTOCOL_THIS(iface);
|
||||
IUri *uri;
|
||||
HRESULT hres;
|
||||
|
||||
static const WCHAR ftpW[] = {'f','t','p',':'};
|
||||
|
||||
|
@ -154,7 +163,14 @@ static HRESULT WINAPI FtpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
|||
if(strncmpW(szUrl, ftpW, sizeof(ftpW)/sizeof(WCHAR)))
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
return protocol_start(&This->base, PROTOCOL(This), szUrl, pOIProtSink, pOIBindInfo);
|
||||
hres = CreateUri(szUrl, 0, 0, &uri);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo);
|
||||
|
||||
IUri_Release(uri);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||
|
|
|
@ -34,13 +34,20 @@ typedef struct {
|
|||
|
||||
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(GopherProtocol, base, iface)
|
||||
|
||||
static HRESULT GopherProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
|
||||
static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
|
||||
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||
{
|
||||
GopherProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
||||
BSTR url;
|
||||
HRESULT hres;
|
||||
|
||||
hres = IUri_GetAbsoluteUri(uri, &url);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
|
||||
request_flags, (DWORD_PTR)&This->base);
|
||||
SysFreeString(url);
|
||||
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
||||
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
||||
return INET_E_RESOURCE_NOT_FOUND;
|
||||
|
@ -125,11 +132,20 @@ static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szU
|
|||
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||
{
|
||||
GopherProtocol *This = PROTOCOL_THIS(iface);
|
||||
IUri *uri;
|
||||
HRESULT hres;
|
||||
|
||||
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
||||
pOIBindInfo, grfPI, dwReserved);
|
||||
|
||||
return protocol_start(&This->base, PROTOCOL(This), szUrl, pOIProtSink, pOIBindInfo);
|
||||
hres = CreateUri(szUrl, 0, 0, &uri);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo);
|
||||
|
||||
IUri_Release(uri);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI GopherProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||
|
|
|
@ -67,18 +67,18 @@ static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
|
|||
|
||||
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(HttpProtocol, base, iface)
|
||||
|
||||
static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD request_flags,
|
||||
static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
|
||||
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||
{
|
||||
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
||||
LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL;
|
||||
IServiceProvider *service_provider = NULL;
|
||||
IHttpNegotiate2 *http_negotiate2 = NULL;
|
||||
LPWSTR host, user, pass, path;
|
||||
BSTR url, host, user, pass, path;
|
||||
LPOLESTR accept_mimes[257];
|
||||
URL_COMPONENTSW url_comp;
|
||||
const WCHAR **accept_types;
|
||||
BYTE security_id[512];
|
||||
DWORD len = 0;
|
||||
DWORD len = 0, port;
|
||||
ULONG num;
|
||||
BOOL res, b;
|
||||
HRESULT hres;
|
||||
|
@ -88,24 +88,28 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
|
|||
{'P','O','S','T',0},
|
||||
{'P','U','T',0}};
|
||||
|
||||
memset(&url_comp, 0, sizeof(url_comp));
|
||||
url_comp.dwStructSize = sizeof(url_comp);
|
||||
url_comp.dwSchemeLength = url_comp.dwHostNameLength = url_comp.dwUrlPathLength = url_comp.dwExtraInfoLength =
|
||||
url_comp.dwUserNameLength = url_comp.dwPasswordLength = 1;
|
||||
if (!InternetCrackUrlW(url, 0, 0, &url_comp))
|
||||
return MK_E_SYNTAX;
|
||||
hres = IUri_GetPort(uri, &port);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
if(!url_comp.nPort)
|
||||
url_comp.nPort = This->https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT;
|
||||
hres = IUri_GetHost(uri, &host);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
host = heap_strndupW(url_comp.lpszHostName, url_comp.dwHostNameLength);
|
||||
user = heap_strndupW(url_comp.lpszUserName, url_comp.dwUserNameLength);
|
||||
pass = heap_strndupW(url_comp.lpszPassword, url_comp.dwPasswordLength);
|
||||
This->base.connection = InternetConnectW(internet_session, host, url_comp.nPort, user, pass,
|
||||
INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base);
|
||||
heap_free(pass);
|
||||
heap_free(user);
|
||||
heap_free(host);
|
||||
hres = IUri_GetUserName(uri, &user);
|
||||
if(SUCCEEDED(hres)) {
|
||||
hres = IUri_GetPassword(uri, &pass);
|
||||
|
||||
if(SUCCEEDED(hres)) {
|
||||
This->base.connection = InternetConnectW(internet_session, host, port, user, pass,
|
||||
INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base);
|
||||
SysFreeString(pass);
|
||||
}
|
||||
SysFreeString(user);
|
||||
}
|
||||
SysFreeString(host);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if(!This->base.connection) {
|
||||
WARN("InternetConnect failed: %d\n", GetLastError());
|
||||
return INET_E_CANNOT_CONNECT;
|
||||
|
@ -113,27 +117,35 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
|
|||
|
||||
num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1;
|
||||
hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num);
|
||||
if(hres != S_OK) {
|
||||
if(hres == INET_E_USE_DEFAULT_SETTING) {
|
||||
static const WCHAR default_accept_mimeW[] = {'*','/','*',0};
|
||||
static const WCHAR *default_accept_mimes[] = {default_accept_mimeW, NULL};
|
||||
|
||||
accept_types = default_accept_mimes;
|
||||
num = 0;
|
||||
}else if(hres == S_OK) {
|
||||
accept_types = (const WCHAR**)accept_mimes;
|
||||
}else {
|
||||
WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres);
|
||||
return INET_E_NO_VALID_MEDIA;
|
||||
}
|
||||
accept_mimes[num] = 0;
|
||||
|
||||
path = heap_alloc((url_comp.dwUrlPathLength+url_comp.dwExtraInfoLength+1)*sizeof(WCHAR));
|
||||
if(url_comp.dwUrlPathLength)
|
||||
memcpy(path, url_comp.lpszUrlPath, url_comp.dwUrlPathLength*sizeof(WCHAR));
|
||||
if(url_comp.dwExtraInfoLength)
|
||||
memcpy(path+url_comp.dwUrlPathLength, url_comp.lpszExtraInfo, url_comp.dwExtraInfoLength*sizeof(WCHAR));
|
||||
path[url_comp.dwUrlPathLength+url_comp.dwExtraInfoLength] = 0;
|
||||
if(This->https)
|
||||
request_flags |= INTERNET_FLAG_SECURE;
|
||||
This->base.request = HttpOpenRequestW(This->base.connection,
|
||||
This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM
|
||||
? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb,
|
||||
path, NULL, NULL, (LPCWSTR *)accept_mimes, request_flags, (DWORD_PTR)&This->base);
|
||||
heap_free(path);
|
||||
|
||||
hres = IUri_GetPathAndQuery(uri, &path);
|
||||
if(SUCCEEDED(hres)) {
|
||||
This->base.request = HttpOpenRequestW(This->base.connection,
|
||||
This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM
|
||||
? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb,
|
||||
path, NULL, NULL, accept_types, request_flags, (DWORD_PTR)&This->base);
|
||||
SysFreeString(path);
|
||||
}
|
||||
while(num--)
|
||||
CoTaskMemFree(accept_mimes[num]);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
if (!This->base.request) {
|
||||
WARN("HttpOpenRequest failed: %d\n", GetLastError());
|
||||
return INET_E_RESOURCE_NOT_FOUND;
|
||||
|
@ -153,8 +165,15 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
|
|||
return hres;
|
||||
}
|
||||
|
||||
hres = IUri_GetAbsoluteUri(uri, &url);
|
||||
if(FAILED(hres)) {
|
||||
IServiceProvider_Release(service_provider);
|
||||
return hres;
|
||||
}
|
||||
|
||||
hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, wszHeaders,
|
||||
0, &addl_header);
|
||||
SysFreeString(url);
|
||||
if(hres != S_OK) {
|
||||
WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres);
|
||||
IServiceProvider_Release(service_provider);
|
||||
|
@ -382,6 +401,8 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
|||
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||
{
|
||||
HttpProtocol *This = PROTOCOL_THIS(iface);
|
||||
IUri *uri;
|
||||
HRESULT hres;
|
||||
|
||||
static const WCHAR httpW[] = {'h','t','t','p',':'};
|
||||
static const WCHAR httpsW[] = {'h','t','t','p','s',':'};
|
||||
|
@ -394,7 +415,14 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
|||
: strncmpW(szUrl, httpW, sizeof(httpW)/sizeof(WCHAR)))
|
||||
return MK_E_SYNTAX;
|
||||
|
||||
return protocol_start(&This->base, PROTOCOL(This), szUrl, pOIProtSink, pOIBindInfo);
|
||||
hres = CreateUri(szUrl, 0, 0, &uri);
|
||||
if(FAILED(hres))
|
||||
return hres;
|
||||
|
||||
hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo);
|
||||
|
||||
IUri_Release(uri);
|
||||
return hres;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||
|
|
|
@ -234,7 +234,7 @@ HINTERNET get_internet_session(IInternetBindInfo *bind_info)
|
|||
return internet_session;
|
||||
}
|
||||
|
||||
HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
|
||||
HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, IUri *uri,
|
||||
IInternetProtocolSink *protocol_sink, IInternetBindInfo *bind_info)
|
||||
{
|
||||
DWORD request_flags;
|
||||
|
@ -265,7 +265,7 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
|
|||
if(protocol->bindf & BINDF_NEEDFILE)
|
||||
request_flags |= INTERNET_FLAG_NEED_FILE;
|
||||
|
||||
hres = protocol->vtbl->open_request(protocol, url, request_flags, internet_session, bind_info);
|
||||
hres = protocol->vtbl->open_request(protocol, uri, request_flags, internet_session, bind_info);
|
||||
if(FAILED(hres)) {
|
||||
protocol_close_connection(protocol);
|
||||
return report_result(protocol, hres);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,6 +29,7 @@
|
|||
@ stdcall CreateFormatEnumerator(long ptr ptr)
|
||||
@ stdcall CreateIUriBuilder(ptr long long ptr)
|
||||
@ stdcall CreateUri(wstr long long ptr)
|
||||
@ stdcall CreateUriWithFragment(wstr wstr long long ptr)
|
||||
@ stdcall CreateURLMoniker(ptr wstr ptr)
|
||||
@ stdcall CreateURLMonikerEx(ptr wstr ptr long)
|
||||
@ stdcall -private DllCanUnloadNow()
|
||||
|
|
|
@ -78,7 +78,7 @@ HRESULT bind_to_storage(LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
|
|||
HRESULT bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
|
||||
|
||||
HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol);
|
||||
void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink);
|
||||
void set_binding_sink(IInternetProtocol *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info);
|
||||
IWinInetInfo *get_wininet_info(IInternetProtocol*);
|
||||
|
||||
typedef struct ProtocolVtbl ProtocolVtbl;
|
||||
|
@ -105,12 +105,12 @@ typedef struct {
|
|||
} Protocol;
|
||||
|
||||
struct ProtocolVtbl {
|
||||
HRESULT (*open_request)(Protocol*,LPCWSTR,DWORD,HINTERNET,IInternetBindInfo*);
|
||||
HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*);
|
||||
HRESULT (*start_downloading)(Protocol*);
|
||||
void (*close_connection)(Protocol*);
|
||||
};
|
||||
|
||||
HRESULT protocol_start(Protocol*,IInternetProtocol*,LPCWSTR,IInternetProtocolSink*,IInternetBindInfo*);
|
||||
HRESULT protocol_start(Protocol*,IInternetProtocol*,IUri*,IInternetProtocolSink*,IInternetBindInfo*);
|
||||
HRESULT protocol_continue(Protocol*,PROTOCOLDATA*);
|
||||
HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*);
|
||||
HRESULT protocol_lock_request(Protocol*);
|
||||
|
|
|
@ -39,7 +39,7 @@ static domain_t *add_domain( session_t *session, WCHAR *name )
|
|||
list_init( &domain->entry );
|
||||
list_init( &domain->cookies );
|
||||
|
||||
domain->name = name;
|
||||
domain->name = strdupW( name );
|
||||
list_add_tail( &session->cookie_cache, &domain->entry );
|
||||
|
||||
TRACE("%s\n", debugstr_w(domain->name));
|
||||
|
@ -120,7 +120,7 @@ static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name
|
|||
}
|
||||
else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie );
|
||||
|
||||
cookie->path = path;
|
||||
cookie->path = strdupW( path );
|
||||
list_add_tail( &domain->cookies, &cookie->entry );
|
||||
|
||||
TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
|
||||
|
@ -230,12 +230,9 @@ BOOL set_cookies( request_t *request, const WCHAR *cookies )
|
|||
ret = add_cookie( session, cookie, cookie_domain, cookie_path );
|
||||
|
||||
end:
|
||||
if (!ret)
|
||||
{
|
||||
free_cookie( cookie );
|
||||
heap_free( cookie_domain );
|
||||
heap_free( cookie_path );
|
||||
}
|
||||
if (!ret) free_cookie( cookie );
|
||||
heap_free( cookie_domain );
|
||||
heap_free( cookie_path );
|
||||
heap_free( buffer );
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#define ENOSPC 28
|
||||
#define EAFNOSUPPORT 52
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef IN6ADDRSZ
|
||||
#define IN6ADDRSZ 16
|
||||
|
@ -64,7 +63,7 @@ inet_ntop(int af, const void *src, char *dst, size_t size)
|
|||
return (inet_ntop6(src, dst, size));
|
||||
#endif
|
||||
default:
|
||||
errno = EAFNOSUPPORT;
|
||||
WSASetLastError(WSAEAFNOSUPPORT);
|
||||
return (NULL);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
|
@ -88,7 +87,7 @@ inet_ntop4(const u_char *src, char *dst, size_t size)
|
|||
char tmp[sizeof "255.255.255.255"];
|
||||
|
||||
if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
|
||||
errno = ENOSPC;
|
||||
WSASetLastError(WSAEINVAL);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
|
@ -182,7 +181,7 @@ inet_ntop6(const u_char *src, char *dst, size_t size)
|
|||
* Check for overflow, copy, and we're done.
|
||||
*/
|
||||
if ((size_t)(tp - tmp) > size) {
|
||||
errno = ENOSPC;
|
||||
WSASetLastError(WSAEINVAL);
|
||||
return (NULL);
|
||||
}
|
||||
strcpy(dst, tmp);
|
||||
|
|
|
@ -42,6 +42,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
|||
DisableThreadLibraryCalls(hInstDLL);
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
netconn_unload();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
|
@ -61,7 +62,6 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
|||
*/
|
||||
HRESULT WINAPI DllCanUnloadNow(void)
|
||||
{
|
||||
FIXME("()\n");
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,10 +38,13 @@
|
|||
#endif
|
||||
#ifdef HAVE_OPENSSL_SSL_H
|
||||
# include <openssl/ssl.h>
|
||||
# include <openssl/opensslv.h>
|
||||
#undef FAR
|
||||
#undef DSA
|
||||
#endif
|
||||
|
||||
#define NONAMELESSUNION
|
||||
|
||||
#include "wine/debug.h"
|
||||
#include "wine/library.h"
|
||||
|
||||
|
@ -58,10 +61,6 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
||||
|
||||
#define DEFAULT_SEND_TIMEOUT 30
|
||||
#define DEFAULT_RECEIVE_TIMEOUT 30
|
||||
#define RESPONSE_TIMEOUT 30
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
|
||||
/* critical section to protect non-reentrant gethostbyname() */
|
||||
|
@ -80,17 +79,35 @@ static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
|
|||
|
||||
#include <openssl/err.h>
|
||||
|
||||
static CRITICAL_SECTION init_ssl_cs;
|
||||
static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
|
||||
{
|
||||
0, 0, &init_ssl_cs,
|
||||
{ &init_ssl_cs_debug.ProcessLocksList,
|
||||
&init_ssl_cs_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
|
||||
};
|
||||
static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static void *libssl_handle;
|
||||
static void *libcrypto_handle;
|
||||
|
||||
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER> 0x1000000)
|
||||
static const SSL_METHOD *method;
|
||||
#else
|
||||
static SSL_METHOD *method;
|
||||
#endif
|
||||
static SSL_CTX *ctx;
|
||||
static int hostname_idx;
|
||||
static int error_idx;
|
||||
static int conn_idx;
|
||||
|
||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||
|
||||
MAKE_FUNCPTR( SSL_library_init );
|
||||
MAKE_FUNCPTR( SSL_load_error_strings );
|
||||
MAKE_FUNCPTR( SSLv23_method );
|
||||
MAKE_FUNCPTR( SSL_CTX_free );
|
||||
MAKE_FUNCPTR( SSL_CTX_new );
|
||||
MAKE_FUNCPTR( SSL_new );
|
||||
MAKE_FUNCPTR( SSL_free );
|
||||
|
@ -99,21 +116,49 @@ MAKE_FUNCPTR( SSL_connect );
|
|||
MAKE_FUNCPTR( SSL_shutdown );
|
||||
MAKE_FUNCPTR( SSL_write );
|
||||
MAKE_FUNCPTR( SSL_read );
|
||||
MAKE_FUNCPTR( SSL_get_verify_result );
|
||||
MAKE_FUNCPTR( SSL_get_error );
|
||||
MAKE_FUNCPTR( SSL_get_ex_new_index );
|
||||
MAKE_FUNCPTR( SSL_get_ex_data );
|
||||
MAKE_FUNCPTR( SSL_set_ex_data );
|
||||
MAKE_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx );
|
||||
MAKE_FUNCPTR( SSL_get_peer_certificate );
|
||||
MAKE_FUNCPTR( SSL_CTX_get_timeout );
|
||||
MAKE_FUNCPTR( SSL_CTX_set_timeout );
|
||||
MAKE_FUNCPTR( SSL_CTX_set_default_verify_paths );
|
||||
MAKE_FUNCPTR( SSL_CTX_set_verify );
|
||||
MAKE_FUNCPTR( SSL_get_current_cipher );
|
||||
MAKE_FUNCPTR( SSL_CIPHER_get_bits );
|
||||
|
||||
MAKE_FUNCPTR( BIO_new_fp );
|
||||
MAKE_FUNCPTR( CRYPTO_num_locks );
|
||||
MAKE_FUNCPTR( CRYPTO_set_id_callback );
|
||||
MAKE_FUNCPTR( CRYPTO_set_locking_callback );
|
||||
MAKE_FUNCPTR( ERR_free_strings );
|
||||
MAKE_FUNCPTR( ERR_get_error );
|
||||
MAKE_FUNCPTR( ERR_error_string );
|
||||
MAKE_FUNCPTR( X509_STORE_CTX_get_ex_data );
|
||||
MAKE_FUNCPTR( i2d_X509 );
|
||||
MAKE_FUNCPTR( sk_value );
|
||||
MAKE_FUNCPTR( sk_num );
|
||||
#undef MAKE_FUNCPTR
|
||||
|
||||
static CRITICAL_SECTION *ssl_locks;
|
||||
static unsigned int num_ssl_locks;
|
||||
|
||||
static unsigned long ssl_thread_id(void)
|
||||
{
|
||||
return GetCurrentThreadId();
|
||||
}
|
||||
|
||||
static void ssl_lock_callback(int mode, int type, const char *file, int line)
|
||||
{
|
||||
if (mode & CRYPTO_LOCK)
|
||||
EnterCriticalSection( &ssl_locks[type] );
|
||||
else
|
||||
LeaveCriticalSection( &ssl_locks[type] );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* translate a unix error code into a winsock error code */
|
||||
#if 0
|
||||
static int sock_get_error( int err )
|
||||
{
|
||||
#if !defined(__MINGW32__) && !defined (_MSC_VER)
|
||||
|
@ -179,24 +224,222 @@ static int sock_get_error( int err )
|
|||
#endif
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
#define sock_get_error(x) WSAGetLastError()
|
||||
#endif
|
||||
|
||||
#ifdef SONAME_LIBSSL
|
||||
static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
|
||||
{
|
||||
unsigned char *buffer, *p;
|
||||
int len;
|
||||
BOOL malloc = FALSE;
|
||||
PCCERT_CONTEXT ret;
|
||||
|
||||
p = NULL;
|
||||
if ((len = pi2d_X509( cert, &p )) < 0) return NULL;
|
||||
/*
|
||||
* SSL 0.9.7 and above malloc the buffer if it is null.
|
||||
* however earlier version do not and so we would need to alloc the buffer.
|
||||
*
|
||||
* see the i2d_X509 man page for more details.
|
||||
*/
|
||||
if (!p)
|
||||
{
|
||||
if (!(buffer = heap_alloc( len ))) return NULL;
|
||||
p = buffer;
|
||||
len = pi2d_X509( cert, &p );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = p;
|
||||
malloc = TRUE;
|
||||
}
|
||||
|
||||
ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len );
|
||||
|
||||
if (malloc) free( buffer );
|
||||
else heap_free( buffer );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, HCERTSTORE store,
|
||||
WCHAR *server, DWORD security_flags )
|
||||
{
|
||||
BOOL ret;
|
||||
CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
|
||||
PCCERT_CHAIN_CONTEXT chain;
|
||||
char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
|
||||
char *server_auth[] = { oid_server_auth };
|
||||
DWORD err = ERROR_SUCCESS;
|
||||
|
||||
TRACE("verifying %s\n", debugstr_w( server ));
|
||||
chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
|
||||
chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
|
||||
if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara, 0,
|
||||
NULL, &chain )))
|
||||
{
|
||||
if (chain->TrustStatus.dwErrorStatus)
|
||||
{
|
||||
static const DWORD supportedErrors =
|
||||
CERT_TRUST_IS_NOT_TIME_VALID |
|
||||
CERT_TRUST_IS_UNTRUSTED_ROOT |
|
||||
CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
|
||||
|
||||
if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
|
||||
{
|
||||
if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID))
|
||||
err = ERROR_WINHTTP_SECURE_CERT_DATE_INVALID;
|
||||
}
|
||||
else if (chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_UNTRUSTED_ROOT)
|
||||
{
|
||||
if (!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
|
||||
err = ERROR_WINHTTP_SECURE_INVALID_CA;
|
||||
}
|
||||
else if ((chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_OFFLINE_REVOCATION) ||
|
||||
(chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
|
||||
err = ERROR_WINHTTP_SECURE_CERT_REV_FAILED;
|
||||
else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
|
||||
err = ERROR_WINHTTP_SECURE_CERT_REVOKED;
|
||||
else if (chain->TrustStatus.dwErrorStatus &
|
||||
CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
|
||||
{
|
||||
if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE))
|
||||
err = ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE;
|
||||
}
|
||||
else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
|
||||
err = ERROR_WINHTTP_SECURE_INVALID_CERT;
|
||||
}
|
||||
if (!err)
|
||||
{
|
||||
CERT_CHAIN_POLICY_PARA policyPara;
|
||||
SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
|
||||
CERT_CHAIN_POLICY_STATUS policyStatus;
|
||||
CERT_CHAIN_CONTEXT chainCopy;
|
||||
|
||||
/* Clear chain->TrustStatus.dwErrorStatus so
|
||||
* CertVerifyCertificateChainPolicy will verify additional checks
|
||||
* rather than stopping with an existing, ignored error.
|
||||
*/
|
||||
memcpy(&chainCopy, chain, sizeof(chainCopy));
|
||||
chainCopy.TrustStatus.dwErrorStatus = 0;
|
||||
sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
|
||||
sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
|
||||
sslExtraPolicyPara.pwszServerName = server;
|
||||
policyPara.cbSize = sizeof(policyPara);
|
||||
policyPara.dwFlags = 0;
|
||||
policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
|
||||
ret = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL,
|
||||
&chainCopy, &policyPara,
|
||||
&policyStatus );
|
||||
/* Any error in the policy status indicates that the
|
||||
* policy couldn't be verified.
|
||||
*/
|
||||
if (ret && policyStatus.dwError)
|
||||
{
|
||||
if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
|
||||
{
|
||||
if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_CN_INVALID))
|
||||
err = ERROR_WINHTTP_SECURE_CERT_CN_INVALID;
|
||||
}
|
||||
else
|
||||
err = ERROR_WINHTTP_SECURE_INVALID_CERT;
|
||||
}
|
||||
}
|
||||
CertFreeCertificateChain( chain );
|
||||
}
|
||||
else
|
||||
err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
|
||||
TRACE("returning %08x\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int netconn_secure_verify( int preverify_ok, X509_STORE_CTX *ctx )
|
||||
{
|
||||
SSL *ssl;
|
||||
WCHAR *server;
|
||||
BOOL ret = FALSE;
|
||||
netconn_t *conn;
|
||||
HCERTSTORE store = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL );
|
||||
|
||||
ssl = pX509_STORE_CTX_get_ex_data( ctx, pSSL_get_ex_data_X509_STORE_CTX_idx() );
|
||||
server = pSSL_get_ex_data( ssl, hostname_idx );
|
||||
conn = pSSL_get_ex_data( ssl, conn_idx );
|
||||
if (store)
|
||||
{
|
||||
X509 *cert;
|
||||
int i;
|
||||
PCCERT_CONTEXT endCert = NULL;
|
||||
|
||||
ret = TRUE;
|
||||
for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
|
||||
{
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
|
||||
if ((context = X509_to_cert_context( cert )))
|
||||
{
|
||||
if (i == 0)
|
||||
ret = CertAddCertificateContextToStore( store, context,
|
||||
CERT_STORE_ADD_ALWAYS, &endCert );
|
||||
else
|
||||
ret = CertAddCertificateContextToStore( store, context,
|
||||
CERT_STORE_ADD_ALWAYS, NULL );
|
||||
CertFreeCertificateContext( context );
|
||||
}
|
||||
}
|
||||
if (!endCert) ret = FALSE;
|
||||
if (ret)
|
||||
{
|
||||
DWORD_PTR err = netconn_verify_cert( endCert, store, server,
|
||||
conn->security_flags );
|
||||
|
||||
if (err)
|
||||
{
|
||||
pSSL_set_ex_data( ssl, error_idx, (void *)err );
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
CertFreeCertificateContext( endCert );
|
||||
CertCloseStore( store, 0 );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||
{
|
||||
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
||||
int i;
|
||||
#endif
|
||||
|
||||
conn->socket = -1;
|
||||
if (!secure) return TRUE;
|
||||
|
||||
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
||||
if (libssl_handle) return TRUE;
|
||||
EnterCriticalSection( &init_ssl_cs );
|
||||
if (libssl_handle)
|
||||
{
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return TRUE;
|
||||
}
|
||||
if (!(libssl_handle = wine_dlopen( SONAME_LIBSSL, RTLD_NOW, NULL, 0 )))
|
||||
{
|
||||
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 )))
|
||||
{
|
||||
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
#define LOAD_FUNCPTR(x) \
|
||||
|
@ -204,11 +447,13 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
|||
{ \
|
||||
ERR("Failed to load symbol %s\n", #x); \
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||
LeaveCriticalSection( &init_ssl_cs ); \
|
||||
return FALSE; \
|
||||
}
|
||||
LOAD_FUNCPTR( SSL_library_init );
|
||||
LOAD_FUNCPTR( SSL_load_error_strings );
|
||||
LOAD_FUNCPTR( SSLv23_method );
|
||||
LOAD_FUNCPTR( SSL_CTX_free );
|
||||
LOAD_FUNCPTR( SSL_CTX_new );
|
||||
LOAD_FUNCPTR( SSL_new );
|
||||
LOAD_FUNCPTR( SSL_free );
|
||||
|
@ -217,11 +462,16 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
|||
LOAD_FUNCPTR( SSL_shutdown );
|
||||
LOAD_FUNCPTR( SSL_write );
|
||||
LOAD_FUNCPTR( SSL_read );
|
||||
LOAD_FUNCPTR( SSL_get_verify_result );
|
||||
LOAD_FUNCPTR( SSL_get_error );
|
||||
LOAD_FUNCPTR( SSL_get_ex_new_index );
|
||||
LOAD_FUNCPTR( SSL_get_ex_data );
|
||||
LOAD_FUNCPTR( SSL_set_ex_data );
|
||||
LOAD_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx );
|
||||
LOAD_FUNCPTR( SSL_get_peer_certificate );
|
||||
LOAD_FUNCPTR( SSL_CTX_get_timeout );
|
||||
LOAD_FUNCPTR( SSL_CTX_set_timeout );
|
||||
LOAD_FUNCPTR( SSL_CTX_set_default_verify_paths );
|
||||
LOAD_FUNCPTR( SSL_CTX_set_verify );
|
||||
LOAD_FUNCPTR( SSL_get_current_cipher );
|
||||
LOAD_FUNCPTR( SSL_CIPHER_get_bits );
|
||||
#undef LOAD_FUNCPTR
|
||||
|
||||
#define LOAD_FUNCPTR(x) \
|
||||
|
@ -229,19 +479,72 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
|||
{ \
|
||||
ERR("Failed to load symbol %s\n", #x); \
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||
LeaveCriticalSection( &init_ssl_cs ); \
|
||||
return FALSE; \
|
||||
}
|
||||
LOAD_FUNCPTR( BIO_new_fp );
|
||||
LOAD_FUNCPTR( CRYPTO_num_locks );
|
||||
LOAD_FUNCPTR( CRYPTO_set_id_callback );
|
||||
LOAD_FUNCPTR( CRYPTO_set_locking_callback );
|
||||
LOAD_FUNCPTR( ERR_free_strings );
|
||||
LOAD_FUNCPTR( ERR_get_error );
|
||||
LOAD_FUNCPTR( ERR_error_string );
|
||||
LOAD_FUNCPTR( X509_STORE_CTX_get_ex_data );
|
||||
LOAD_FUNCPTR( i2d_X509 );
|
||||
LOAD_FUNCPTR( sk_value );
|
||||
LOAD_FUNCPTR( sk_num );
|
||||
#undef LOAD_FUNCPTR
|
||||
|
||||
pSSL_library_init();
|
||||
pSSL_load_error_strings();
|
||||
pBIO_new_fp( stderr, BIO_NOCLOSE );
|
||||
|
||||
method = pSSLv23_method();
|
||||
ctx = pSSL_CTX_new( method );
|
||||
if (!pSSL_CTX_set_default_verify_paths( ctx ))
|
||||
{
|
||||
ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
hostname_idx = pSSL_get_ex_new_index( 0, (void *)"hostname index", NULL, NULL, NULL );
|
||||
if (hostname_idx == -1)
|
||||
{
|
||||
ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
error_idx = pSSL_get_ex_new_index( 0, (void *)"error index", NULL, NULL, NULL );
|
||||
if (error_idx == -1)
|
||||
{
|
||||
ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
conn_idx = pSSL_get_ex_new_index( 0, (void *)"netconn index", NULL, NULL, NULL );
|
||||
if (conn_idx == -1)
|
||||
{
|
||||
ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
pSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, netconn_secure_verify );
|
||||
|
||||
pCRYPTO_set_id_callback(ssl_thread_id);
|
||||
num_ssl_locks = pCRYPTO_num_locks();
|
||||
ssl_locks = HeapAlloc(GetProcessHeap(), 0, num_ssl_locks * sizeof(CRITICAL_SECTION));
|
||||
if (!ssl_locks)
|
||||
{
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
return FALSE;
|
||||
}
|
||||
for (i = 0; i < num_ssl_locks; i++) InitializeCriticalSection( &ssl_locks[i] );
|
||||
pCRYPTO_set_locking_callback(ssl_lock_callback);
|
||||
|
||||
LeaveCriticalSection( &init_ssl_cs );
|
||||
#else
|
||||
WARN("SSL support not compiled in.\n");
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
|
@ -250,6 +553,29 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void netconn_unload( void )
|
||||
{
|
||||
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
||||
if (libcrypto_handle)
|
||||
{
|
||||
pERR_free_strings();
|
||||
wine_dlclose( libcrypto_handle, NULL, 0 );
|
||||
}
|
||||
if (libssl_handle)
|
||||
{
|
||||
if (ctx)
|
||||
pSSL_CTX_free( ctx );
|
||||
wine_dlclose( libssl_handle, NULL, 0 );
|
||||
}
|
||||
if (ssl_locks)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_ssl_locks; i++) DeleteCriticalSection( &ssl_locks[i] );
|
||||
HeapFree( GetProcessHeap(), 0, ssl_locks );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOL netconn_connected( netconn_t *conn )
|
||||
{
|
||||
return (conn->socket != -1);
|
||||
|
@ -295,36 +621,72 @@ BOOL netconn_close( netconn_t *conn )
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len )
|
||||
BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout )
|
||||
{
|
||||
if (connect( conn->socket, sockaddr, addr_len ) == -1)
|
||||
BOOL ret = FALSE;
|
||||
int res = 0, state;
|
||||
|
||||
if (timeout > 0)
|
||||
{
|
||||
WARN("unable to connect to host (%s)\n", strerror(errno));
|
||||
set_last_error( sock_get_error( errno ) );
|
||||
return FALSE;
|
||||
state = 1;
|
||||
ioctlsocket( conn->socket, FIONBIO, &state );
|
||||
}
|
||||
return TRUE;
|
||||
if (connect( conn->socket, sockaddr, addr_len ) < 0)
|
||||
{
|
||||
res = sock_get_error( errno );
|
||||
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
|
||||
{
|
||||
fd_set outfd;
|
||||
struct timeval tv;
|
||||
|
||||
FD_ZERO(&outfd);
|
||||
FD_SET(conn->socket, &outfd);
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = timeout * 1000;
|
||||
|
||||
if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
|
||||
ret = TRUE;
|
||||
else
|
||||
res = sock_get_error( errno );
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = TRUE;
|
||||
if (timeout > 0)
|
||||
{
|
||||
state = 0;
|
||||
ioctlsocket( conn->socket, FIONBIO, &state );
|
||||
}
|
||||
if (!ret)
|
||||
{
|
||||
WARN("unable to connect to host (%d)\n", res);
|
||||
set_last_error( res );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL netconn_secure_connect( netconn_t *conn )
|
||||
BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
|
||||
{
|
||||
#ifdef SONAME_LIBSSL
|
||||
X509 *cert;
|
||||
long res;
|
||||
|
||||
ctx = pSSL_CTX_new( method );
|
||||
if (!pSSL_CTX_set_default_verify_paths( ctx ))
|
||||
{
|
||||
ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(conn->ssl_conn = pSSL_new( ctx )))
|
||||
{
|
||||
ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
goto fail;
|
||||
}
|
||||
if (!pSSL_set_ex_data( conn->ssl_conn, hostname_idx, hostname ))
|
||||
{
|
||||
ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
goto fail;
|
||||
}
|
||||
if (!pSSL_set_ex_data( conn->ssl_conn, conn_idx, conn ))
|
||||
{
|
||||
ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
return FALSE;
|
||||
}
|
||||
if (!pSSL_set_fd( conn->ssl_conn, conn->socket ))
|
||||
{
|
||||
ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
|
@ -333,21 +695,14 @@ BOOL netconn_secure_connect( netconn_t *conn )
|
|||
}
|
||||
if (pSSL_connect( conn->ssl_conn ) <= 0)
|
||||
{
|
||||
ERR("SSL_connect failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
DWORD err;
|
||||
|
||||
err = (DWORD_PTR)pSSL_get_ex_data( conn->ssl_conn, error_idx );
|
||||
if (!err) err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
|
||||
ERR("couldn't verify server certificate (%d)\n", err);
|
||||
set_last_error( err );
|
||||
goto fail;
|
||||
}
|
||||
if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn )))
|
||||
{
|
||||
ERR("No certificate for server: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||
goto fail;
|
||||
}
|
||||
if ((res = pSSL_get_verify_result( conn->ssl_conn )) != X509_V_OK)
|
||||
{
|
||||
/* FIXME: we should set an error and return, but we only print an error at the moment */
|
||||
ERR("couldn't verify server certificate (%ld)\n", res);
|
||||
}
|
||||
TRACE("established SSL connection\n");
|
||||
conn->secure = TRUE;
|
||||
return TRUE;
|
||||
|
@ -387,6 +742,8 @@ BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int
|
|||
|
||||
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
|
||||
{
|
||||
int ret;
|
||||
|
||||
*recvd = 0;
|
||||
if (!netconn_connected( conn )) return FALSE;
|
||||
if (!len) return TRUE;
|
||||
|
@ -425,19 +782,29 @@ BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd
|
|||
/* check if we have enough data from the peek buffer */
|
||||
if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
|
||||
}
|
||||
*recvd += pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd );
|
||||
ret = pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd );
|
||||
if (ret < 0)
|
||||
return FALSE;
|
||||
|
||||
/* check if EOF was received */
|
||||
if (!ret && (pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_ZERO_RETURN ||
|
||||
pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_SYSCALL ))
|
||||
{
|
||||
netconn_close( conn );
|
||||
return TRUE;
|
||||
}
|
||||
if (flags & MSG_PEEK) /* must copy into buffer */
|
||||
{
|
||||
conn->peek_len = *recvd;
|
||||
if (!*recvd)
|
||||
conn->peek_len = ret;
|
||||
if (!ret)
|
||||
{
|
||||
heap_free( conn->peek_msg_mem );
|
||||
conn->peek_msg_mem = NULL;
|
||||
conn->peek_msg = NULL;
|
||||
}
|
||||
else memcpy( conn->peek_msg, buf, *recvd );
|
||||
else memcpy( conn->peek_msg, buf, ret );
|
||||
}
|
||||
if (*recvd < 1 && len) return FALSE;
|
||||
*recvd = ret;
|
||||
return TRUE;
|
||||
#else
|
||||
return FALSE;
|
||||
|
@ -474,7 +841,6 @@ BOOL netconn_query_data_available( netconn_t *conn, DWORD *available )
|
|||
|
||||
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||
{
|
||||
struct timeval tv;
|
||||
fd_set infd;
|
||||
BOOL ret = FALSE;
|
||||
DWORD recvd = 0;
|
||||
|
@ -484,11 +850,6 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
|||
if (conn->secure)
|
||||
{
|
||||
#ifdef SONAME_LIBSSL
|
||||
long timeout;
|
||||
|
||||
timeout = pSSL_CTX_get_timeout( ctx );
|
||||
pSSL_CTX_set_timeout( ctx, DEFAULT_RECEIVE_TIMEOUT );
|
||||
|
||||
while (recvd < *buflen)
|
||||
{
|
||||
int dummy;
|
||||
|
@ -504,7 +865,6 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
|||
}
|
||||
if (buffer[recvd] != '\r') recvd++;
|
||||
}
|
||||
pSSL_CTX_set_timeout( ctx, timeout );
|
||||
if (ret)
|
||||
{
|
||||
buffer[recvd++] = 0;
|
||||
|
@ -516,16 +876,23 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
|||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FD_ZERO(&infd);
|
||||
FD_SET(conn->socket, &infd);
|
||||
tv.tv_sec=RESPONSE_TIMEOUT;
|
||||
tv.tv_usec=0;
|
||||
|
||||
while (recvd < *buflen)
|
||||
{
|
||||
if (select(conn->socket+1,&infd,NULL,NULL,&tv) > 0)
|
||||
int res;
|
||||
struct timeval tv, *ptv;
|
||||
socklen_t len = sizeof(tv);
|
||||
|
||||
if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1))
|
||||
ptv = &tv;
|
||||
else
|
||||
ptv = NULL;
|
||||
|
||||
if (select( 0, &infd, NULL, NULL, ptv ) > 0)
|
||||
{
|
||||
int res;
|
||||
if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
|
||||
{
|
||||
if (res == -1) set_last_error( sock_get_error( errno ) );
|
||||
|
@ -570,7 +937,7 @@ DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
BOOL netconn_resolve( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_in *sa )
|
||||
static DWORD resolve_hostname( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len )
|
||||
{
|
||||
char *hostname;
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
|
@ -578,27 +945,53 @@ BOOL netconn_resolve( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_in *
|
|||
int ret;
|
||||
#else
|
||||
struct hostent *he;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
#endif
|
||||
|
||||
if (!(hostname = strdupWA( hostnameW ))) return FALSE;
|
||||
if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY;
|
||||
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
memset( &hints, 0, sizeof(struct addrinfo) );
|
||||
/* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on
|
||||
* their IPv6 addresses even though they have IPv6 addresses in the DNS.
|
||||
*/
|
||||
hints.ai_family = AF_INET;
|
||||
|
||||
ret = getaddrinfo( hostname, NULL, &hints, &res );
|
||||
heap_free( hostname );
|
||||
if (ret != 0)
|
||||
{
|
||||
TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
|
||||
return FALSE;
|
||||
TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret));
|
||||
hints.ai_family = AF_INET6;
|
||||
ret = getaddrinfo( hostname, NULL, &hints, &res );
|
||||
if (ret != 0)
|
||||
{
|
||||
TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
|
||||
heap_free( hostname );
|
||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
||||
}
|
||||
}
|
||||
heap_free( hostname );
|
||||
if (*sa_len < res->ai_addrlen)
|
||||
{
|
||||
WARN("address too small\n");
|
||||
freeaddrinfo( res );
|
||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
||||
}
|
||||
*sa_len = res->ai_addrlen;
|
||||
memcpy( sa, res->ai_addr, res->ai_addrlen );
|
||||
/* Copy port */
|
||||
switch (res->ai_family)
|
||||
{
|
||||
case AF_INET:
|
||||
((struct sockaddr_in *)sa)->sin_port = htons( port );
|
||||
break;
|
||||
case AF_INET6:
|
||||
((struct sockaddr_in6 *)sa)->sin6_port = htons( port );
|
||||
break;
|
||||
}
|
||||
memset( sa, 0, sizeof(struct sockaddr_in) );
|
||||
memcpy( &sa->sin_addr, &((struct sockaddr_in *)res->ai_addr)->sin_addr, sizeof(struct in_addr) );
|
||||
sa->sin_family = res->ai_family;
|
||||
sa->sin_port = htons( port );
|
||||
|
||||
freeaddrinfo( res );
|
||||
return ERROR_SUCCESS;
|
||||
#else
|
||||
EnterCriticalSection( &cs_gethostbyname );
|
||||
|
||||
|
@ -608,15 +1001,69 @@ BOOL netconn_resolve( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_in *
|
|||
{
|
||||
TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
|
||||
LeaveCriticalSection( &cs_gethostbyname );
|
||||
return FALSE;
|
||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
||||
}
|
||||
if (*sa_len < sizeof(struct sockaddr_in))
|
||||
{
|
||||
WARN("address too small\n");
|
||||
LeaveCriticalSection( &cs_gethostbyname );
|
||||
return ERROR_WINHTTP_NAME_NOT_RESOLVED;
|
||||
}
|
||||
*sa_len = sizeof(struct sockaddr_in);
|
||||
memset( sa, 0, sizeof(struct sockaddr_in) );
|
||||
memcpy( &sa->sin_addr, he->h_addr, he->h_length );
|
||||
sa->sin_family = he->h_addrtype;
|
||||
sa->sin_port = htons( port );
|
||||
memcpy( &sin->sin_addr, he->h_addr, he->h_length );
|
||||
sin->sin_family = he->h_addrtype;
|
||||
sin->sin_port = htons( port );
|
||||
|
||||
LeaveCriticalSection( &cs_gethostbyname );
|
||||
return ERROR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct resolve_args
|
||||
{
|
||||
WCHAR *hostname;
|
||||
INTERNET_PORT port;
|
||||
struct sockaddr *sa;
|
||||
socklen_t *sa_len;
|
||||
};
|
||||
|
||||
static DWORD CALLBACK resolve_proc( LPVOID arg )
|
||||
{
|
||||
struct resolve_args *ra = arg;
|
||||
return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len );
|
||||
}
|
||||
|
||||
BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len, int timeout )
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
DWORD status;
|
||||
HANDLE thread;
|
||||
struct resolve_args ra;
|
||||
|
||||
ra.hostname = hostname;
|
||||
ra.port = port;
|
||||
ra.sa = sa;
|
||||
ra.sa_len = sa_len;
|
||||
|
||||
thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
|
||||
if (!thread) return FALSE;
|
||||
|
||||
status = WaitForSingleObject( thread, timeout );
|
||||
if (status == WAIT_OBJECT_0) GetExitCodeThread( thread, &ret );
|
||||
else ret = ERROR_WINHTTP_TIMEOUT;
|
||||
CloseHandle( thread );
|
||||
}
|
||||
else ret = resolve_hostname( hostname, port, sa, sa_len );
|
||||
|
||||
if (ret)
|
||||
{
|
||||
set_last_error( ret );
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -624,41 +1071,29 @@ const void *netconn_get_certificate( netconn_t *conn )
|
|||
{
|
||||
#ifdef SONAME_LIBSSL
|
||||
X509 *cert;
|
||||
unsigned char *buffer, *p;
|
||||
int len;
|
||||
BOOL malloc = FALSE;
|
||||
const CERT_CONTEXT *ret;
|
||||
|
||||
if (!conn->secure) return NULL;
|
||||
|
||||
if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
|
||||
p = NULL;
|
||||
if ((len = pi2d_X509( cert, &p )) < 0) return NULL;
|
||||
/*
|
||||
* SSL 0.9.7 and above malloc the buffer if it is null.
|
||||
* however earlier version do not and so we would need to alloc the buffer.
|
||||
*
|
||||
* see the i2d_X509 man page for more details.
|
||||
*/
|
||||
if (!p)
|
||||
{
|
||||
if (!(buffer = heap_alloc( len ))) return NULL;
|
||||
p = buffer;
|
||||
len = pi2d_X509( cert, &p );
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer = p;
|
||||
malloc = TRUE;
|
||||
}
|
||||
|
||||
ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len );
|
||||
|
||||
if (malloc) free( buffer );
|
||||
else heap_free( buffer );
|
||||
|
||||
ret = X509_to_cert_context( cert );
|
||||
return ret;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
int netconn_get_cipher_strength( netconn_t *conn )
|
||||
{
|
||||
#ifdef SONAME_LIBSSL
|
||||
SSL_CIPHER *cipher;
|
||||
int bits = 0;
|
||||
|
||||
if (!conn->secure) return 0;
|
||||
if (!(cipher = pSSL_get_current_cipher( conn->ssl_conn ))) return 0;
|
||||
pSSL_CIPHER_get_bits( cipher, &bits );
|
||||
return bits;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -21,16 +21,26 @@
|
|||
#include "wine/debug.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winhttp.h"
|
||||
#include "wincrypt.h"
|
||||
#include "winreg.h"
|
||||
|
||||
#include "winhttp_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
||||
|
||||
#define DEFAULT_RESOLVE_TIMEOUT 0
|
||||
#define DEFAULT_CONNECT_TIMEOUT 20000
|
||||
#define DEFAULT_SEND_TIMEOUT 30000
|
||||
#define DEFAULT_RECEIVE_TIMEOUT 30000
|
||||
|
||||
/* FIXME */
|
||||
#define CP_UNIXCP CP_ACP
|
||||
|
||||
void set_last_error( DWORD error )
|
||||
{
|
||||
/* FIXME */
|
||||
|
@ -85,6 +95,8 @@ static void session_destroy( object_header_t *hdr )
|
|||
|
||||
static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
|
||||
{
|
||||
session_t *session = (session_t *)hdr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WINHTTP_OPTION_REDIRECT_POLICY:
|
||||
|
@ -100,6 +112,22 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||
*(DWORD *)buffer = session->resolve_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
||||
*(DWORD *)buffer = session->connect_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_SEND_TIMEOUT:
|
||||
*(DWORD *)buffer = session->send_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
||||
*(DWORD *)buffer = session->recv_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
default:
|
||||
FIXME("unimplemented option %u\n", option);
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
|
@ -109,6 +137,8 @@ static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
|
||||
static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
|
||||
{
|
||||
session_t *session = (session_t *)hdr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WINHTTP_OPTION_PROXY:
|
||||
|
@ -136,6 +166,18 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
|
|||
case WINHTTP_OPTION_DISABLE_FEATURE:
|
||||
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
|
||||
return FALSE;
|
||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||
session->resolve_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
||||
session->connect_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_SEND_TIMEOUT:
|
||||
session->send_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
||||
session->recv_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
default:
|
||||
FIXME("unimplemented option %u\n", option);
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
|
@ -166,13 +208,39 @@ HINTERNET WINAPI WinHttpOpen( LPCWSTR agent, DWORD access, LPCWSTR proxy, LPCWST
|
|||
session->hdr.vtbl = &session_vtbl;
|
||||
session->hdr.flags = flags;
|
||||
session->hdr.refs = 1;
|
||||
session->access = access;
|
||||
session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
|
||||
session->resolve_timeout = DEFAULT_RESOLVE_TIMEOUT;
|
||||
session->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
session->send_timeout = DEFAULT_SEND_TIMEOUT;
|
||||
session->recv_timeout = DEFAULT_RECEIVE_TIMEOUT;
|
||||
list_init( &session->cookie_cache );
|
||||
|
||||
if (agent && !(session->agent = strdupW( agent ))) goto end;
|
||||
if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
|
||||
if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
|
||||
if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
|
||||
{
|
||||
WINHTTP_PROXY_INFO info;
|
||||
|
||||
WinHttpGetDefaultProxyConfiguration( &info );
|
||||
session->access = info.dwAccessType;
|
||||
if (info.lpszProxy && !(session->proxy_server = strdupW( info.lpszProxy )))
|
||||
{
|
||||
GlobalFree( (LPWSTR)info.lpszProxy );
|
||||
GlobalFree( (LPWSTR)info.lpszProxyBypass );
|
||||
goto end;
|
||||
}
|
||||
if (info.lpszProxyBypass && !(session->proxy_bypass = strdupW( info.lpszProxyBypass )))
|
||||
{
|
||||
GlobalFree( (LPWSTR)info.lpszProxy );
|
||||
GlobalFree( (LPWSTR)info.lpszProxyBypass );
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
else if (access == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
|
||||
{
|
||||
session->access = access;
|
||||
if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
|
||||
if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
|
||||
}
|
||||
|
||||
if (!(handle = alloc_handle( &session->hdr ))) goto end;
|
||||
session->hdr.handle = handle;
|
||||
|
@ -201,13 +269,199 @@ static void connect_destroy( object_header_t *hdr )
|
|||
heap_free( connect );
|
||||
}
|
||||
|
||||
static BOOL connect_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
|
||||
{
|
||||
connect_t *connect = (connect_t *)hdr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WINHTTP_OPTION_PARENT_HANDLE:
|
||||
{
|
||||
if (!buffer || *buflen < sizeof(HINTERNET))
|
||||
{
|
||||
*buflen = sizeof(HINTERNET);
|
||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*(HINTERNET *)buffer = ((object_header_t *)connect->session)->handle;
|
||||
*buflen = sizeof(HINTERNET);
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||
*(DWORD *)buffer = connect->session->resolve_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
||||
*(DWORD *)buffer = connect->session->connect_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_SEND_TIMEOUT:
|
||||
*(DWORD *)buffer = connect->session->send_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
||||
*(DWORD *)buffer = connect->session->recv_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
default:
|
||||
FIXME("unimplemented option %u\n", option);
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const object_vtbl_t connect_vtbl =
|
||||
{
|
||||
connect_destroy,
|
||||
NULL,
|
||||
connect_query_option,
|
||||
NULL
|
||||
};
|
||||
|
||||
static BOOL domain_matches(LPCWSTR server, LPCWSTR domain)
|
||||
{
|
||||
static const WCHAR localW[] = { '<','l','o','c','a','l','>',0 };
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!strcmpiW( domain, localW ) && !strchrW( server, '.' ))
|
||||
ret = TRUE;
|
||||
else if (*domain == '*')
|
||||
{
|
||||
if (domain[1] == '.')
|
||||
{
|
||||
LPCWSTR dot;
|
||||
|
||||
/* For a hostname to match a wildcard, the last domain must match
|
||||
* the wildcard exactly. E.g. if the wildcard is *.a.b, and the
|
||||
* hostname is www.foo.a.b, it matches, but a.b does not.
|
||||
*/
|
||||
dot = strchrW( server, '.' );
|
||||
if (dot)
|
||||
{
|
||||
int len = strlenW( dot + 1 );
|
||||
|
||||
if (len > strlenW( domain + 2 ))
|
||||
{
|
||||
LPCWSTR ptr;
|
||||
|
||||
/* The server's domain is longer than the wildcard, so it
|
||||
* could be a subdomain. Compare the last portion of the
|
||||
* server's domain.
|
||||
*/
|
||||
ptr = dot + len + 1 - strlenW( domain + 2 );
|
||||
if (!strcmpiW( ptr, domain + 2 ))
|
||||
{
|
||||
/* This is only a match if the preceding character is
|
||||
* a '.', i.e. that it is a matching domain. E.g.
|
||||
* if domain is '*.b.c' and server is 'www.ab.c' they
|
||||
* do not match.
|
||||
*/
|
||||
ret = *(ptr - 1) == '.';
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = !strcmpiW( dot + 1, domain + 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = !strcmpiW( server, domain );
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Matches INTERNET_MAX_HOST_NAME_LENGTH in wininet.h, also RFC 1035 */
|
||||
#define MAX_HOST_NAME_LENGTH 256
|
||||
|
||||
static BOOL should_bypass_proxy(session_t *session, LPCWSTR server)
|
||||
{
|
||||
LPCWSTR ptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if (!session->proxy_bypass) return FALSE;
|
||||
ptr = session->proxy_bypass;
|
||||
do {
|
||||
LPCWSTR tmp = ptr;
|
||||
|
||||
ptr = strchrW( ptr, ';' );
|
||||
if (!ptr)
|
||||
ptr = strchrW( tmp, ' ' );
|
||||
if (ptr)
|
||||
{
|
||||
if (ptr - tmp < MAX_HOST_NAME_LENGTH)
|
||||
{
|
||||
WCHAR domain[MAX_HOST_NAME_LENGTH];
|
||||
|
||||
memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) );
|
||||
domain[ptr - tmp] = 0;
|
||||
ret = domain_matches( server, domain );
|
||||
}
|
||||
ptr += 1;
|
||||
}
|
||||
else if (*tmp)
|
||||
ret = domain_matches( server, tmp );
|
||||
} while (ptr && !ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port )
|
||||
{
|
||||
session_t *session = connect->session;
|
||||
BOOL ret = TRUE;
|
||||
|
||||
if (session->proxy_server && !should_bypass_proxy(session, server))
|
||||
{
|
||||
LPCWSTR colon;
|
||||
|
||||
if ((colon = strchrW( session->proxy_server, ':' )))
|
||||
{
|
||||
if (!connect->servername || strncmpiW( connect->servername,
|
||||
session->proxy_server, colon - session->proxy_server - 1 ))
|
||||
{
|
||||
heap_free( connect->servername );
|
||||
if (!(connect->servername = heap_alloc(
|
||||
(colon - session->proxy_server + 1) * sizeof(WCHAR) )))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto end;
|
||||
}
|
||||
memcpy( connect->servername, session->proxy_server,
|
||||
(colon - session->proxy_server) * sizeof(WCHAR) );
|
||||
connect->servername[colon - session->proxy_server] = 0;
|
||||
if (*(colon + 1))
|
||||
connect->serverport = atoiW( colon + 1 );
|
||||
else
|
||||
connect->serverport = INTERNET_DEFAULT_PORT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!connect->servername || strcmpiW( connect->servername,
|
||||
session->proxy_server ))
|
||||
{
|
||||
heap_free( connect->servername );
|
||||
if (!(connect->servername = strdupW( session->proxy_server )))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto end;
|
||||
}
|
||||
connect->serverport = INTERNET_DEFAULT_PORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (server)
|
||||
{
|
||||
heap_free( connect->servername );
|
||||
if (!(connect->servername = strdupW( server )))
|
||||
{
|
||||
ret = FALSE;
|
||||
goto end;
|
||||
}
|
||||
connect->serverport = port;
|
||||
}
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WinHttpConnect (winhttp.@)
|
||||
*/
|
||||
|
@ -252,11 +506,11 @@ HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PO
|
|||
connect->session = session;
|
||||
list_add_head( &session->hdr.children, &connect->hdr.entry );
|
||||
|
||||
if (server && !(connect->hostname = strdupW( server ))) goto end;
|
||||
if (!(connect->hostname = strdupW( server ))) goto end;
|
||||
connect->hostport = port;
|
||||
|
||||
if (server && !(connect->servername = strdupW( server ))) goto end;
|
||||
connect->serverport = port;
|
||||
if (!set_server_for_hostname( connect, server, port ))
|
||||
goto end;
|
||||
|
||||
if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
|
||||
connect->hdr.handle = hconnect;
|
||||
|
@ -296,13 +550,40 @@ static void request_destroy( object_header_t *hdr )
|
|||
heap_free( request );
|
||||
}
|
||||
|
||||
static void str_to_buffer( WCHAR *buffer, const WCHAR *str, LPDWORD buflen )
|
||||
{
|
||||
int len = 0;
|
||||
if (str) len = strlenW( str );
|
||||
if (buffer && *buflen > len)
|
||||
{
|
||||
memcpy( buffer, str, len * sizeof(WCHAR) );
|
||||
buffer[len] = 0;
|
||||
}
|
||||
*buflen = len * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
static WCHAR *blob_to_str( DWORD encoding, CERT_NAME_BLOB *blob )
|
||||
{
|
||||
WCHAR *ret;
|
||||
DWORD size, format = CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG;
|
||||
|
||||
size = CertNameToStrW( encoding, blob, format, NULL, 0 );
|
||||
if ((ret = LocalAlloc( 0, size * sizeof(WCHAR) )))
|
||||
CertNameToStrW( encoding, blob, format, ret, size );
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
|
||||
{
|
||||
request_t *request = (request_t *)hdr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WINHTTP_OPTION_SECURITY_FLAGS:
|
||||
{
|
||||
DWORD flags;
|
||||
int bits;
|
||||
|
||||
if (!buffer || *buflen < sizeof(flags))
|
||||
{
|
||||
|
@ -313,6 +594,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
|
||||
flags = 0;
|
||||
if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
|
||||
flags |= request->netconn.security_flags;
|
||||
bits = netconn_get_cipher_strength( &request->netconn );
|
||||
if (bits >= 128)
|
||||
flags |= SECURITY_FLAG_STRENGTH_STRONG;
|
||||
else if (bits >= 56)
|
||||
flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
|
||||
else
|
||||
flags |= SECURITY_FLAG_STRENGTH_WEAK;
|
||||
*(DWORD *)buffer = flags;
|
||||
*buflen = sizeof(flags);
|
||||
return TRUE;
|
||||
|
@ -320,7 +609,6 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
|
||||
{
|
||||
const CERT_CONTEXT *cert;
|
||||
request_t *request = (request_t *)hdr;
|
||||
|
||||
if (!buffer || *buflen < sizeof(cert))
|
||||
{
|
||||
|
@ -334,6 +622,41 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
*buflen = sizeof(cert);
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_SECURITY_CERTIFICATE_STRUCT:
|
||||
{
|
||||
const CERT_CONTEXT *cert;
|
||||
const CRYPT_OID_INFO *oidInfo;
|
||||
WINHTTP_CERTIFICATE_INFO *ci = buffer;
|
||||
|
||||
FIXME("partial stub\n");
|
||||
|
||||
if (!buffer || *buflen < sizeof(*ci))
|
||||
{
|
||||
*buflen = sizeof(*ci);
|
||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||
return FALSE;
|
||||
}
|
||||
if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE;
|
||||
|
||||
ci->ftExpiry = cert->pCertInfo->NotAfter;
|
||||
ci->ftStart = cert->pCertInfo->NotBefore;
|
||||
ci->lpszSubjectInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Subject );
|
||||
ci->lpszIssuerInfo = blob_to_str( cert->dwCertEncodingType, &cert->pCertInfo->Issuer );
|
||||
ci->lpszProtocolName = NULL;
|
||||
oidInfo = CryptFindOIDInfo( CRYPT_OID_INFO_OID_KEY,
|
||||
cert->pCertInfo->SignatureAlgorithm.pszObjId,
|
||||
0 );
|
||||
if (oidInfo)
|
||||
ci->lpszSignatureAlgName = (LPWSTR)oidInfo->pwszName;
|
||||
else
|
||||
ci->lpszSignatureAlgName = NULL;
|
||||
ci->lpszEncryptionAlgName = NULL;
|
||||
ci->dwKeySize = netconn_get_cipher_strength( &request->netconn );
|
||||
|
||||
CertFreeCertificateContext( cert );
|
||||
*buflen = sizeof(*ci);
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
|
||||
{
|
||||
if (!buffer || *buflen < sizeof(DWORD))
|
||||
|
@ -343,10 +666,43 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
*(DWORD *)buffer = 128; /* FIXME */
|
||||
*(DWORD *)buffer = netconn_get_cipher_strength( &request->netconn );
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||
*(DWORD *)buffer = request->resolve_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
||||
*(DWORD *)buffer = request->connect_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_SEND_TIMEOUT:
|
||||
*(DWORD *)buffer = request->send_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
||||
*(DWORD *)buffer = request->recv_timeout;
|
||||
*buflen = sizeof(DWORD);
|
||||
return TRUE;
|
||||
|
||||
case WINHTTP_OPTION_USERNAME:
|
||||
str_to_buffer( buffer, request->connect->username, buflen );
|
||||
return TRUE;
|
||||
|
||||
case WINHTTP_OPTION_PASSWORD:
|
||||
str_to_buffer( buffer, request->connect->password, buflen );
|
||||
return TRUE;
|
||||
|
||||
case WINHTTP_OPTION_PROXY_USERNAME:
|
||||
str_to_buffer( buffer, request->connect->session->proxy_username, buflen );
|
||||
return TRUE;
|
||||
|
||||
case WINHTTP_OPTION_PROXY_PASSWORD:
|
||||
str_to_buffer( buffer, request->connect->session->proxy_password, buflen );
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
FIXME("unimplemented option %u\n", option);
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
|
@ -354,8 +710,23 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
|||
}
|
||||
}
|
||||
|
||||
static WCHAR *buffer_to_str( WCHAR *buffer, DWORD buflen )
|
||||
{
|
||||
WCHAR *ret;
|
||||
if ((ret = heap_alloc( (buflen + 1) * sizeof(WCHAR))))
|
||||
{
|
||||
memcpy( ret, buffer, buflen * sizeof(WCHAR) );
|
||||
ret[buflen] = 0;
|
||||
return ret;
|
||||
}
|
||||
set_last_error( ERROR_OUTOFMEMORY );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
|
||||
{
|
||||
request_t *request = (request_t *)hdr;
|
||||
|
||||
switch (option)
|
||||
{
|
||||
case WINHTTP_OPTION_PROXY:
|
||||
|
@ -410,6 +781,73 @@ static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffe
|
|||
hdr->redirect_policy = policy;
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_SECURITY_FLAGS:
|
||||
{
|
||||
DWORD flags;
|
||||
|
||||
if (buflen < sizeof(DWORD))
|
||||
{
|
||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||
return FALSE;
|
||||
}
|
||||
flags = *(DWORD *)buffer;
|
||||
TRACE("0x%x\n", flags);
|
||||
if (!(flags & (SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
|
||||
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID |
|
||||
SECURITY_FLAG_IGNORE_UNKNOWN_CA |
|
||||
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)))
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
request->netconn.security_flags = flags;
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_RESOLVE_TIMEOUT:
|
||||
request->resolve_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_CONNECT_TIMEOUT:
|
||||
request->connect_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_SEND_TIMEOUT:
|
||||
request->send_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
case WINHTTP_OPTION_RECEIVE_TIMEOUT:
|
||||
request->recv_timeout = *(DWORD *)buffer;
|
||||
return TRUE;
|
||||
|
||||
case WINHTTP_OPTION_USERNAME:
|
||||
{
|
||||
connect_t *connect = request->connect;
|
||||
|
||||
heap_free( connect->username );
|
||||
if (!(connect->username = buffer_to_str( buffer, buflen ))) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_PASSWORD:
|
||||
{
|
||||
connect_t *connect = request->connect;
|
||||
|
||||
heap_free( connect->password );
|
||||
if (!(connect->password = buffer_to_str( buffer, buflen ))) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_PROXY_USERNAME:
|
||||
{
|
||||
session_t *session = request->connect->session;
|
||||
|
||||
heap_free( session->proxy_username );
|
||||
if (!(session->proxy_username = buffer_to_str( buffer, buflen ))) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
case WINHTTP_OPTION_PROXY_PASSWORD:
|
||||
{
|
||||
session_t *session = request->connect->session;
|
||||
|
||||
heap_free( session->proxy_password );
|
||||
if (!(session->proxy_password = buffer_to_str( buffer, buflen ))) return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
default:
|
||||
FIXME("unimplemented option %u\n", option);
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
|
@ -466,6 +904,10 @@ HINTERNET WINAPI WinHttpOpenRequest( HINTERNET hconnect, LPCWSTR verb, LPCWSTR o
|
|||
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
||||
|
||||
if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
|
||||
request->resolve_timeout = connect->session->resolve_timeout;
|
||||
request->connect_timeout = connect->session->connect_timeout;
|
||||
request->send_timeout = connect->session->send_timeout;
|
||||
request->recv_timeout = connect->session->recv_timeout;
|
||||
|
||||
if (!verb || !verb[0]) verb = getW;
|
||||
if (!(request->verb = strdupW( verb ))) goto end;
|
||||
|
@ -648,17 +1090,167 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static const WCHAR Connections[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\',
|
||||
'W','i','n','d','o','w','s','\\',
|
||||
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
|
||||
'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
|
||||
'C','o','n','n','e','c','t','i','o','n','s',0 };
|
||||
static const WCHAR WinHttpSettings[] = {
|
||||
'W','i','n','H','t','t','p','S','e','t','t','i','n','g','s',0 };
|
||||
static const DWORD WINHTTPSETTINGS_MAGIC = 0x18;
|
||||
static const DWORD WINHTTP_PROXY_TYPE_DIRECT = 1;
|
||||
static const DWORD WINHTTP_PROXY_TYPE_PROXY = 2;
|
||||
|
||||
struct winhttp_settings_header
|
||||
{
|
||||
DWORD magic;
|
||||
DWORD unknown; /* always zero? */
|
||||
DWORD flags; /* one of WINHTTP_PROXY_TYPE_* */
|
||||
};
|
||||
|
||||
static inline void copy_char_to_wchar_sz(const BYTE *src, DWORD len, WCHAR *dst)
|
||||
{
|
||||
const BYTE *begin;
|
||||
|
||||
for (begin = src; src - begin < len; src++, dst++)
|
||||
*dst = *src;
|
||||
*dst = 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WinHttpGetDefaultProxyConfiguration (winhttp.@)
|
||||
*/
|
||||
BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
|
||||
{
|
||||
FIXME("%p\n", info);
|
||||
LONG l;
|
||||
HKEY key;
|
||||
BOOL got_from_reg = FALSE, direct = TRUE;
|
||||
char *envproxy;
|
||||
|
||||
info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
|
||||
info->lpszProxy = NULL;
|
||||
info->lpszProxyBypass = NULL;
|
||||
TRACE("%p\n", info);
|
||||
|
||||
l = RegOpenKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, KEY_READ, &key );
|
||||
if (!l)
|
||||
{
|
||||
DWORD type, size = 0;
|
||||
|
||||
l = RegQueryValueExW( key, WinHttpSettings, NULL, &type, NULL, &size );
|
||||
if (!l && type == REG_BINARY &&
|
||||
size >= sizeof(struct winhttp_settings_header) + 2 * sizeof(DWORD))
|
||||
{
|
||||
BYTE *buf = heap_alloc( size );
|
||||
|
||||
if (buf)
|
||||
{
|
||||
struct winhttp_settings_header *hdr =
|
||||
(struct winhttp_settings_header *)buf;
|
||||
DWORD *len = (DWORD *)(hdr + 1);
|
||||
|
||||
l = RegQueryValueExW( key, WinHttpSettings, NULL, NULL, buf,
|
||||
&size );
|
||||
if (!l && hdr->magic == WINHTTPSETTINGS_MAGIC &&
|
||||
hdr->unknown == 0)
|
||||
{
|
||||
if (hdr->flags & WINHTTP_PROXY_TYPE_PROXY)
|
||||
{
|
||||
BOOL sane = FALSE;
|
||||
LPWSTR proxy = NULL;
|
||||
LPWSTR proxy_bypass = NULL;
|
||||
|
||||
/* Sanity-check length of proxy string */
|
||||
if ((BYTE *)len - buf + *len <= size)
|
||||
{
|
||||
sane = TRUE;
|
||||
proxy = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
|
||||
if (proxy)
|
||||
copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy );
|
||||
len = (DWORD *)((BYTE *)(len + 1) + *len);
|
||||
}
|
||||
if (sane)
|
||||
{
|
||||
/* Sanity-check length of proxy bypass string */
|
||||
if ((BYTE *)len - buf + *len <= size)
|
||||
{
|
||||
proxy_bypass = GlobalAlloc( 0, (*len + 1) * sizeof(WCHAR) );
|
||||
if (proxy_bypass)
|
||||
copy_char_to_wchar_sz( (BYTE *)(len + 1), *len, proxy_bypass );
|
||||
}
|
||||
else
|
||||
{
|
||||
sane = FALSE;
|
||||
GlobalFree( proxy );
|
||||
proxy = NULL;
|
||||
}
|
||||
}
|
||||
info->lpszProxy = proxy;
|
||||
info->lpszProxyBypass = proxy_bypass;
|
||||
if (sane)
|
||||
{
|
||||
got_from_reg = TRUE;
|
||||
direct = FALSE;
|
||||
info->dwAccessType =
|
||||
WINHTTP_ACCESS_TYPE_NAMED_PROXY;
|
||||
TRACE("http proxy (from registry) = %s, bypass = %s\n",
|
||||
debugstr_w(info->lpszProxy),
|
||||
debugstr_w(info->lpszProxyBypass));
|
||||
}
|
||||
}
|
||||
}
|
||||
heap_free( buf );
|
||||
}
|
||||
}
|
||||
RegCloseKey( key );
|
||||
}
|
||||
if (!got_from_reg && (envproxy = getenv( "http_proxy" )))
|
||||
{
|
||||
char *colon, *http_proxy;
|
||||
|
||||
if ((colon = strchr( envproxy, ':' )))
|
||||
{
|
||||
if (*(colon + 1) == '/' && *(colon + 2) == '/')
|
||||
{
|
||||
static const char http[] = "http://";
|
||||
|
||||
/* It's a scheme, check that it's http */
|
||||
if (!strncmp( envproxy, http, strlen( http ) ))
|
||||
http_proxy = envproxy + strlen( http );
|
||||
else
|
||||
{
|
||||
WARN("unsupported scheme in $http_proxy: %s\n", envproxy);
|
||||
http_proxy = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
http_proxy = envproxy;
|
||||
}
|
||||
else
|
||||
http_proxy = envproxy;
|
||||
if (http_proxy)
|
||||
{
|
||||
WCHAR *http_proxyW;
|
||||
int len;
|
||||
|
||||
len = MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, NULL, 0 );
|
||||
if ((http_proxyW = GlobalAlloc( 0, len * sizeof(WCHAR))))
|
||||
{
|
||||
MultiByteToWideChar( CP_UNIXCP, 0, http_proxy, -1, http_proxyW, len );
|
||||
direct = FALSE;
|
||||
info->dwAccessType = WINHTTP_ACCESS_TYPE_NAMED_PROXY;
|
||||
info->lpszProxy = http_proxyW;
|
||||
info->lpszProxyBypass = NULL;
|
||||
TRACE("http proxy (from environment) = %s\n",
|
||||
debugstr_w(info->lpszProxy));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (direct)
|
||||
{
|
||||
info->dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
|
||||
info->lpszProxy = NULL;
|
||||
info->lpszProxyBypass = NULL;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -703,9 +1295,106 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO
|
|||
*/
|
||||
BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
|
||||
{
|
||||
FIXME("%p [%u, %s, %s]\n", info, info->dwAccessType, debugstr_w(info->lpszProxy),
|
||||
debugstr_w(info->lpszProxyBypass));
|
||||
return TRUE;
|
||||
LONG l;
|
||||
HKEY key;
|
||||
BOOL ret = FALSE;
|
||||
const WCHAR *src;
|
||||
|
||||
TRACE("%p\n", info);
|
||||
|
||||
if (!info)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
switch (info->dwAccessType)
|
||||
{
|
||||
case WINHTTP_ACCESS_TYPE_NO_PROXY:
|
||||
break;
|
||||
case WINHTTP_ACCESS_TYPE_NAMED_PROXY:
|
||||
if (!info->lpszProxy)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
/* Only ASCII characters are allowed */
|
||||
for (src = info->lpszProxy; *src; src++)
|
||||
if (*src > 0x7f)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
if (info->lpszProxyBypass)
|
||||
{
|
||||
for (src = info->lpszProxyBypass; *src; src++)
|
||||
if (*src > 0x7f)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
l = RegCreateKeyExW( HKEY_LOCAL_MACHINE, Connections, 0, NULL, 0,
|
||||
KEY_WRITE, NULL, &key, NULL );
|
||||
if (!l)
|
||||
{
|
||||
DWORD size = sizeof(struct winhttp_settings_header) + 2 * sizeof(DWORD);
|
||||
BYTE *buf;
|
||||
|
||||
if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
|
||||
{
|
||||
size += strlenW( info->lpszProxy );
|
||||
if (info->lpszProxyBypass)
|
||||
size += strlenW( info->lpszProxyBypass );
|
||||
}
|
||||
buf = heap_alloc( size );
|
||||
if (buf)
|
||||
{
|
||||
struct winhttp_settings_header *hdr =
|
||||
(struct winhttp_settings_header *)buf;
|
||||
DWORD *len = (DWORD *)(hdr + 1);
|
||||
|
||||
hdr->magic = WINHTTPSETTINGS_MAGIC;
|
||||
hdr->unknown = 0;
|
||||
if (info->dwAccessType == WINHTTP_ACCESS_TYPE_NAMED_PROXY)
|
||||
{
|
||||
BYTE *dst;
|
||||
|
||||
hdr->flags = WINHTTP_PROXY_TYPE_PROXY;
|
||||
*len++ = strlenW( info->lpszProxy );
|
||||
for (dst = (BYTE *)len, src = info->lpszProxy; *src;
|
||||
src++, dst++)
|
||||
*dst = *src;
|
||||
len = (DWORD *)dst;
|
||||
if (info->lpszProxyBypass)
|
||||
{
|
||||
*len++ = strlenW( info->lpszProxyBypass );
|
||||
for (dst = (BYTE *)len, src = info->lpszProxyBypass; *src;
|
||||
src++, dst++)
|
||||
*dst = *src;
|
||||
}
|
||||
else
|
||||
*len++ = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdr->flags = WINHTTP_PROXY_TYPE_DIRECT;
|
||||
*len++ = 0;
|
||||
*len++ = 0;
|
||||
}
|
||||
l = RegSetValueExW( key, WinHttpSettings, 0, REG_BINARY, buf, size );
|
||||
if (!l)
|
||||
ret = TRUE;
|
||||
heap_free( buf );
|
||||
}
|
||||
RegCloseKey( key );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -737,8 +1426,69 @@ WINHTTP_STATUS_CALLBACK WINAPI WinHttpSetStatusCallback( HINTERNET handle, WINHT
|
|||
*/
|
||||
BOOL WINAPI WinHttpSetTimeouts( HINTERNET handle, int resolve, int connect, int send, int receive )
|
||||
{
|
||||
FIXME("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
|
||||
return TRUE;
|
||||
BOOL ret = TRUE;
|
||||
object_header_t *hdr;
|
||||
request_t *request;
|
||||
session_t *session;
|
||||
|
||||
TRACE("%p, %d, %d, %d, %d\n", handle, resolve, connect, send, receive);
|
||||
|
||||
if (resolve < -1 || connect < -1 || send < -1 || receive < -1)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(hdr = grab_object( handle )))
|
||||
{
|
||||
set_last_error( ERROR_INVALID_HANDLE );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch(hdr->type)
|
||||
{
|
||||
case WINHTTP_HANDLE_TYPE_REQUEST:
|
||||
request = (request_t *)hdr;
|
||||
request->connect_timeout = connect;
|
||||
|
||||
if (resolve < 0) resolve = 0;
|
||||
request->resolve_timeout = resolve;
|
||||
|
||||
if (send < 0) send = 0;
|
||||
request->send_timeout = send;
|
||||
|
||||
if (receive < 0) receive = 0;
|
||||
request->recv_timeout = receive;
|
||||
|
||||
if (netconn_connected( &request->netconn ))
|
||||
{
|
||||
if (netconn_set_timeout( &request->netconn, TRUE, send )) ret = FALSE;
|
||||
if (netconn_set_timeout( &request->netconn, FALSE, receive )) ret = FALSE;
|
||||
}
|
||||
|
||||
release_object( &request->hdr );
|
||||
break;
|
||||
|
||||
case WINHTTP_HANDLE_TYPE_SESSION:
|
||||
session = (session_t *)hdr;
|
||||
session->connect_timeout = connect;
|
||||
|
||||
if (resolve < 0) resolve = 0;
|
||||
session->resolve_timeout = resolve;
|
||||
|
||||
if (send < 0) send = 0;
|
||||
session->send_timeout = send;
|
||||
|
||||
if (receive < 0) receive = 0;
|
||||
session->recv_timeout = receive;
|
||||
break;
|
||||
|
||||
default:
|
||||
release_object( hdr );
|
||||
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
|
||||
return FALSE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const WCHAR wkday[7][4] =
|
||||
|
|
|
@ -133,7 +133,7 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN
|
|||
p += 2;
|
||||
|
||||
if (!p[0]) goto exit;
|
||||
if ((q = memchrW( p, '@', len - (p - url) )))
|
||||
if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
|
||||
{
|
||||
if ((r = memchrW( p, ':', q - p )))
|
||||
{
|
||||
|
@ -368,7 +368,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
|
|||
|
||||
TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
|
||||
|
||||
if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
|
||||
if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required || !url)
|
||||
{
|
||||
set_last_error( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
|
@ -376,7 +376,7 @@ BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDW
|
|||
|
||||
if (!calc_length( uc, flags, &len )) return FALSE;
|
||||
|
||||
if (!url || *required < len)
|
||||
if (*required < len)
|
||||
{
|
||||
*required = len + 1;
|
||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
<file>session.c</file>
|
||||
<file>url.c</file>
|
||||
<library>wine</library>
|
||||
<library>advapi32</library>
|
||||
<library>crypt32</library>
|
||||
<library>shlwapi</library>
|
||||
<library>wininet</library>
|
||||
<library>ws2_32</library>
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "wine/unicode.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef HAVE_SYS_SOCKET_H
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
#ifdef HAVE_NETINET_IN_H
|
||||
# include <netinet/in.h>
|
||||
#endif
|
||||
|
@ -93,6 +96,10 @@ typedef struct
|
|||
object_header_t hdr;
|
||||
LPWSTR agent;
|
||||
DWORD access;
|
||||
int resolve_timeout;
|
||||
int connect_timeout;
|
||||
int send_timeout;
|
||||
int recv_timeout;
|
||||
LPWSTR proxy_server;
|
||||
LPWSTR proxy_bypass;
|
||||
LPWSTR proxy_username;
|
||||
|
@ -110,7 +117,7 @@ typedef struct
|
|||
LPWSTR password;
|
||||
INTERNET_PORT hostport;
|
||||
INTERNET_PORT serverport;
|
||||
struct sockaddr_in sockaddr;
|
||||
struct sockaddr_storage sockaddr;
|
||||
} connect_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -121,6 +128,7 @@ typedef struct
|
|||
char *peek_msg;
|
||||
char *peek_msg_mem;
|
||||
size_t peek_len;
|
||||
DWORD security_flags;
|
||||
} netconn_t;
|
||||
|
||||
typedef struct
|
||||
|
@ -139,6 +147,10 @@ typedef struct
|
|||
LPWSTR version;
|
||||
LPWSTR raw_headers;
|
||||
netconn_t netconn;
|
||||
int resolve_timeout;
|
||||
int connect_timeout;
|
||||
int send_timeout;
|
||||
int recv_timeout;
|
||||
LPWSTR status_text;
|
||||
DWORD content_length; /* total number of bytes to be read (per chunk) */
|
||||
DWORD content_read; /* bytes read so far */
|
||||
|
@ -204,22 +216,26 @@ void send_callback( object_header_t *, DWORD, LPVOID, DWORD );
|
|||
void close_connection( request_t * );
|
||||
|
||||
BOOL netconn_close( netconn_t * );
|
||||
BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int );
|
||||
BOOL netconn_connect( netconn_t *, const struct sockaddr *, unsigned int, int );
|
||||
BOOL netconn_connected( netconn_t * );
|
||||
BOOL netconn_create( netconn_t *, int, int, int );
|
||||
BOOL netconn_get_next_line( netconn_t *, char *, DWORD * );
|
||||
BOOL netconn_init( netconn_t *, BOOL );
|
||||
void netconn_unload( void );
|
||||
BOOL netconn_query_data_available( netconn_t *, DWORD * );
|
||||
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * );
|
||||
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * );
|
||||
BOOL netconn_secure_connect( netconn_t * );
|
||||
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, int );
|
||||
BOOL netconn_secure_connect( netconn_t *, WCHAR * );
|
||||
BOOL netconn_send( netconn_t *, const void *, size_t, int, int * );
|
||||
DWORD netconn_set_timeout( netconn_t *, BOOL, int );
|
||||
const void *netconn_get_certificate( netconn_t * );
|
||||
int netconn_get_cipher_strength( netconn_t * );
|
||||
|
||||
BOOL set_cookies( request_t *, const WCHAR * );
|
||||
BOOL add_cookie_headers( request_t * );
|
||||
BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD );
|
||||
void delete_domain( domain_t * );
|
||||
BOOL set_server_for_hostname( connect_t *connect, LPCWSTR server, INTERNET_PORT port );
|
||||
|
||||
static inline void *heap_alloc( SIZE_T size )
|
||||
{
|
||||
|
|
|
@ -1,111 +1,104 @@
|
|||
--- net.c Wed Sep 03 14:46:10 2008
|
||||
+++ net.c Sun Sep 07 10:54:26 2008
|
||||
@@ -59,6 +59,7 @@
|
||||
|
||||
#define DEFAULT_SEND_TIMEOUT 30
|
||||
#define DEFAULT_RECEIVE_TIMEOUT 30
|
||||
+#define RESPONSE_TIMEOUT 30
|
||||
|
||||
#ifndef HAVE_GETADDRINFO
|
||||
|
||||
@@ -110,6 +111,7 @@
|
||||
|
||||
--- wine-1.3.4/dlls/winhttp/net.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/winhttp/net.c 2010-10-09 17:04:11.000000000 -0400
|
||||
@@ -158,6 +158,7 @@
|
||||
#endif
|
||||
|
||||
+#if 0
|
||||
/* translate a unix error code into a winsock error code */
|
||||
+#if 0
|
||||
static int sock_get_error( int err )
|
||||
{
|
||||
@@ -174,6 +176,9 @@
|
||||
}
|
||||
#if !defined(__MINGW32__) && !defined (_MSC_VER)
|
||||
@@ -223,6 +224,9 @@
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
+#else
|
||||
+#define sock_get_error(x) WSAGetLastError()
|
||||
+#endif
|
||||
|
||||
BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||
{
|
||||
@@ -282,7 +287,7 @@
|
||||
conn->secure = FALSE;
|
||||
}
|
||||
#endif
|
||||
- res = close( conn->socket );
|
||||
+ res = closesocket( conn->socket );
|
||||
conn->socket = -1;
|
||||
if (res == -1)
|
||||
{
|
||||
@@ -463,7 +468,7 @@
|
||||
return TRUE;
|
||||
}
|
||||
#ifdef FIONREAD
|
||||
- if (!(ret = ioctl( conn->socket, FIONREAD, &unread )))
|
||||
+ if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread )))
|
||||
{
|
||||
TRACE("%d bytes of queued, but unread data\n", unread);
|
||||
*available += unread;
|
||||
@@ -474,7 +479,8 @@
|
||||
#ifdef SONAME_LIBSSL
|
||||
static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
|
||||
@@ -632,11 +636,16 @@
|
||||
res = sock_get_error( errno );
|
||||
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
|
||||
{
|
||||
- struct pollfd pfd;
|
||||
+ fd_set outfd;
|
||||
+ struct timeval tv;
|
||||
+
|
||||
+ FD_ZERO(&outfd);
|
||||
+ FD_SET(conn->socket, &outfd);
|
||||
|
||||
- pfd.fd = conn->socket;
|
||||
- pfd.events = POLLOUT;
|
||||
- if (poll( &pfd, 1, timeout ) > 0)
|
||||
+ tv.tv_sec = 0;
|
||||
+ tv.tv_usec = timeout * 1000;
|
||||
+
|
||||
+ if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
|
||||
ret = TRUE;
|
||||
else
|
||||
res = sock_get_error( errno );
|
||||
@@ -832,7 +841,7 @@
|
||||
|
||||
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||
{
|
||||
- struct pollfd pfd;
|
||||
+ struct timeval tv;
|
||||
+ fd_set infd;
|
||||
BOOL ret = FALSE;
|
||||
DWORD recvd = 0;
|
||||
|
||||
@@ -516,11 +522,13 @@
|
||||
@@ -867,20 +876,22 @@
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
-
|
||||
- pfd.fd = conn->socket;
|
||||
- pfd.events = POLLIN;
|
||||
+
|
||||
+ FD_ZERO(&infd);
|
||||
+ FD_SET(conn->socket, &infd);
|
||||
+ tv.tv_sec=RESPONSE_TIMEOUT;
|
||||
+ tv.tv_usec=0;
|
||||
+
|
||||
while (recvd < *buflen)
|
||||
{
|
||||
- if (poll( &pfd, 1, DEFAULT_RECEIVE_TIMEOUT * 1000 ) > 0)
|
||||
+ if (select(conn->socket+1,&infd,NULL,NULL,&tv) > 0)
|
||||
{
|
||||
int res;
|
||||
if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
|
||||
--- request.c Fri Sep 05 17:34:17 2008
|
||||
+++ request.c Sun Sep 07 11:29:55 2008
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "wine/port.h"
|
||||
#include "wine/debug.h"
|
||||
- int timeout, res;
|
||||
- struct timeval tv;
|
||||
+ int res;
|
||||
+ struct timeval tv, *ptv;
|
||||
socklen_t len = sizeof(tv);
|
||||
|
||||
+#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef HAVE_ARPA_INET_H
|
||||
# include <arpa/inet.h>
|
||||
@@ -33,6 +34,8 @@
|
||||
#include "winhttp.h"
|
||||
if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1))
|
||||
- timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||
+ ptv = &tv;
|
||||
else
|
||||
- timeout = -1;
|
||||
- if (poll( &pfd, 1, timeout ) > 0)
|
||||
+ ptv = NULL;
|
||||
+
|
||||
+ if (select( 0, &infd, NULL, NULL, ptv ) > 0)
|
||||
{
|
||||
if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
|
||||
{
|
||||
--- wine-1.3.4/dlls/winhttp/session.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/winhttp/session.c 2010-10-09 17:04:11.000000000 -0400
|
||||
@@ -38,6 +38,9 @@
|
||||
#define DEFAULT_SEND_TIMEOUT 30000
|
||||
#define DEFAULT_RECEIVE_TIMEOUT 30000
|
||||
|
||||
+/* FIXME */
|
||||
+#define CP_UNIXCP CP_ACP
|
||||
+
|
||||
void set_last_error( DWORD error )
|
||||
{
|
||||
/* FIXME */
|
||||
--- wine-1.3.4/dlls/winhttp/request.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/winhttp/request.c 2010-10-09 17:04:11.000000000 -0400
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "winhttp_private.h"
|
||||
+
|
||||
+#include "inet_ntop.c"
|
||||
|
||||
+#include "inet_ntop.c"
|
||||
+
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
||||
|
||||
--- winhttp_private.h Thu Sep 04 15:27:29 2008
|
||||
+++ winhttp_private.h Sun Sep 07 10:46:54 2008
|
||||
@@ -33,8 +33,14 @@
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
#if defined(__MINGW32__) || defined (_MSC_VER)
|
||||
-# include <ws2tcpip.h>
|
||||
-#endif
|
||||
+# include "ws2tcpip.h"
|
||||
+# ifndef MSG_WAITALL
|
||||
+# define MSG_WAITALL 0
|
||||
+# endif
|
||||
+#else
|
||||
+# define closesocket close
|
||||
+# define ioctlsocket ioctl
|
||||
+#endif /* __MINGW32__ */
|
||||
|
||||
typedef struct _object_header_t object_header_t;
|
||||
|
||||
static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
|
|
@ -37,4 +37,33 @@
|
|||
+#endif
|
||||
|
||||
/******************************************************************************
|
||||
* NETCON_create
|
||||
* NETCON_create
|
||||
--- wine-1.3.4/dlls/wininet/internet.c 2010-10-01 14:46:44.000000000 -0400
|
||||
+++ dll/win32/wininet/internet.c 2010-10-09 15:33:04.000000000 -0400
|
||||
@@ -3569,19 +3569,22 @@
|
||||
|
||||
LPSTR INTERNET_GetNextLine(INT nSocket, LPDWORD dwLen)
|
||||
{
|
||||
- struct pollfd pfd;
|
||||
+ fd_set infd;
|
||||
+ struct timeval tv;
|
||||
BOOL bSuccess = FALSE;
|
||||
INT nRecv = 0;
|
||||
LPSTR lpszBuffer = INTERNET_GetResponseBuffer();
|
||||
|
||||
TRACE("\n");
|
||||
|
||||
- pfd.fd = nSocket;
|
||||
- pfd.events = POLLIN;
|
||||
+ FD_ZERO(&infd);
|
||||
+ FD_SET(nSocket,&infd);
|
||||
+ tv.tv_sec = RESPONSE_TIMEOUT;
|
||||
+ tv.tv_usec = 0;
|
||||
|
||||
while (nRecv < MAX_REPLY_LEN)
|
||||
{
|
||||
- if (poll(&pfd,1, RESPONSE_TIMEOUT * 1000) > 0)
|
||||
+ if (select(0, &infd, NULL, NULL, &tv) > 0)
|
||||
{
|
||||
if (recv(nSocket, &lpszBuffer[nRecv], 1, 0) <= 0)
|
||||
{
|
Loading…
Reference in a new issue