mirror of
https://github.com/reactos/reactos.git
synced 2024-07-04 11:44:33 +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->to_object) {
|
||||||
if(!(This->state & BINDING_OBJAVAIL))
|
if(!(This->state & BINDING_OBJAVAIL)) {
|
||||||
|
IBinding_AddRef(BINDING(This));
|
||||||
create_object(This);
|
create_object(This);
|
||||||
|
IBinding_Release(BINDING(This));
|
||||||
|
}
|
||||||
}else {
|
}else {
|
||||||
STGMEDIUM stgmed;
|
STGMEDIUM stgmed;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
@ -1519,7 +1522,7 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, LPCWSTR url, I
|
||||||
}
|
}
|
||||||
|
|
||||||
if(binding_ctx) {
|
if(binding_ctx) {
|
||||||
set_binding_sink(binding->protocol, PROTSINK(binding));
|
set_binding_sink(binding->protocol, PROTSINK(binding), BINDINF(binding));
|
||||||
if(binding_ctx->redirect_url)
|
if(binding_ctx->redirect_url)
|
||||||
IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url);
|
IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url);
|
||||||
report_data(binding, 0, 0, 0);
|
report_data(binding, 0, 0, 0);
|
||||||
|
|
|
@ -382,7 +382,7 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocol *iface)
|
||||||
if(This->filter_proxy)
|
if(This->filter_proxy)
|
||||||
IInternetProtocol_Release(PROTOCOL(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)
|
if(This->notif_hwnd)
|
||||||
release_notif_hwnd(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);
|
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);
|
BindProtocol *This = PROTOCOL_THIS(bind_protocol);
|
||||||
IInternetProtocolSink *prev_sink;
|
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);
|
service_provider = InterlockedExchangePointer((void**)&This->service_provider, service_provider);
|
||||||
if(service_provider)
|
if(service_provider)
|
||||||
IServiceProvider_Release(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)
|
IWinInetInfo *get_wininet_info(IInternetProtocol *bind_protocol)
|
||||||
|
@ -619,10 +625,7 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz
|
||||||
if(urlmon_protocol)
|
if(urlmon_protocol)
|
||||||
IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
|
IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
|
||||||
|
|
||||||
IInternetBindInfo_AddRef(pOIBindInfo);
|
set_binding_sink(PROTOCOL(This), pOIProtSink, pOIBindInfo);
|
||||||
This->bind_info = pOIBindInfo;
|
|
||||||
|
|
||||||
set_binding_sink(PROTOCOL(This), pOIProtSink);
|
|
||||||
|
|
||||||
hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
|
hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
|
@ -670,7 +673,7 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD
|
||||||
This->filter_proxy = NULL;
|
This->filter_proxy = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_binding_sink(PROTOCOL(This), NULL);
|
set_binding_sink(PROTOCOL(This), NULL, NULL);
|
||||||
|
|
||||||
if(This->bind_info) {
|
if(This->bind_info) {
|
||||||
IInternetBindInfo_Release(This->bind_info);
|
IInternetBindInfo_Release(This->bind_info);
|
||||||
|
|
|
@ -119,22 +119,22 @@ static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWOR
|
||||||
return E_NOTIMPL;
|
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;
|
HRESULT hres;
|
||||||
|
|
||||||
if(!This->callback)
|
if(!This->callback)
|
||||||
return;
|
return S_OK;
|
||||||
|
|
||||||
hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
|
hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
|
||||||
if(FAILED(hres))
|
return hres;
|
||||||
FIXME("OnProgress failed: %08x\n", hres);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
|
static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
|
||||||
ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
|
ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
|
||||||
{
|
{
|
||||||
DownloadBSC *This = STATUSCLB_THIS(iface);
|
DownloadBSC *This = STATUSCLB_THIS(iface);
|
||||||
|
HRESULT hres = S_OK;
|
||||||
|
|
||||||
TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
|
TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
|
||||||
debugstr_w(szStatusText));
|
debugstr_w(szStatusText));
|
||||||
|
@ -146,11 +146,11 @@ static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG u
|
||||||
case BINDSTATUS_ENDDOWNLOADDATA:
|
case BINDSTATUS_ENDDOWNLOADDATA:
|
||||||
case BINDSTATUS_SENDINGREQUEST:
|
case BINDSTATUS_SENDINGREQUEST:
|
||||||
case BINDSTATUS_MIMETYPEAVAILABLE:
|
case BINDSTATUS_MIMETYPEAVAILABLE:
|
||||||
on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
|
case BINDSTATUS_CACHEFILENAMEAVAILABLE:
|
||||||
on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
|
||||||
This->cache_file = heap_strdupW(szStatusText);
|
This->cache_file = heap_strdupW(szStatusText);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG u
|
||||||
FIXME("Unsupported status %u\n", ulStatusCode);
|
FIXME("Unsupported status %u\n", ulStatusCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return S_OK;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
|
static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
|
||||||
|
|
|
@ -17,38 +17,46 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "urlmon_main.h"
|
#include "urlmon_main.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
#include "shlwapi.h"
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const IInternetProtocolVtbl *lpIInternetProtocolVtbl;
|
const IInternetProtocolExVtbl *lpIInternetProtocolExVtbl;
|
||||||
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
const IInternetPriorityVtbl *lpInternetPriorityVtbl;
|
||||||
|
|
||||||
HANDLE file;
|
HANDLE file;
|
||||||
|
ULONG size;
|
||||||
LONG priority;
|
LONG priority;
|
||||||
|
|
||||||
LONG ref;
|
LONG ref;
|
||||||
} FileProtocol;
|
} 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);
|
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||||
|
|
||||||
*ppv = NULL;
|
*ppv = NULL;
|
||||||
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
if(IsEqualGUID(&IID_IUnknown, riid)) {
|
||||||
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
|
||||||
*ppv = PROTOCOL(This);
|
*ppv = PROTOCOLEX(This);
|
||||||
}else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
|
}else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
|
||||||
TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
|
TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
|
||||||
*ppv = PROTOCOL(This);
|
*ppv = PROTOCOLEX(This);
|
||||||
}else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
|
}else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
|
||||||
TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
|
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)) {
|
}else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
|
||||||
TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
|
TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
|
||||||
*ppv = PRIORITY(This);
|
*ppv = PRIORITY(This);
|
||||||
|
@ -63,7 +71,7 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocol *iface, REFI
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI FileProtocol_AddRef(IInternetProtocol *iface)
|
static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||||
LONG ref = InterlockedIncrement(&This->ref);
|
LONG ref = InterlockedIncrement(&This->ref);
|
||||||
|
@ -71,7 +79,7 @@ static ULONG WINAPI FileProtocol_AddRef(IInternetProtocol *iface)
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||||
LONG ref = InterlockedDecrement(&This->ref);
|
LONG ref = InterlockedDecrement(&This->ref);
|
||||||
|
@ -79,7 +87,7 @@ static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
||||||
TRACE("(%p) ref=%d\n", This, ref);
|
TRACE("(%p) ref=%d\n", This, ref);
|
||||||
|
|
||||||
if(!ref) {
|
if(!ref) {
|
||||||
if(This->file)
|
if(This->file != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(This->file);
|
CloseHandle(This->file);
|
||||||
heap_free(This);
|
heap_free(This);
|
||||||
|
|
||||||
|
@ -89,27 +97,168 @@ static ULONG WINAPI FileProtocol_Release(IInternetProtocol *iface)
|
||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
|
||||||
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
|
IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
|
||||||
DWORD grfPI, HANDLE_PTR dwReserved)
|
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PROTOCOL_THIS(iface);
|
FileProtocol *This = PROTOCOL_THIS(iface);
|
||||||
BINDINFO bindinfo;
|
IUri *uri;
|
||||||
DWORD grfBINDF = 0;
|
|
||||||
LARGE_INTEGER size;
|
|
||||||
DWORD len;
|
|
||||||
LPWSTR url, mime = NULL, file_name;
|
|
||||||
WCHAR null_char = 0;
|
|
||||||
BOOL first_call = FALSE;
|
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
|
||||||
static const WCHAR wszFile[] = {'f','i','l','e',':'};
|
|
||||||
|
|
||||||
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
||||||
pOIBindInfo, grfPI, dwReserved);
|
pOIBindInfo, grfPI, dwReserved);
|
||||||
|
|
||||||
if(!szUrl || strlenW(szUrl) < sizeof(wszFile)/sizeof(WCHAR)
|
hres = CreateUri(szUrl, Uri_CREATE_FILE_USE_DOS_PATH, 0, &uri);
|
||||||
|| memcmp(szUrl, wszFile, sizeof(wszFile)))
|
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;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
memset(&bindinfo, 0, sizeof(bindinfo));
|
memset(&bindinfo, 0, sizeof(bindinfo));
|
||||||
|
@ -122,170 +271,52 @@ static HRESULT WINAPI FileProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
||||||
|
|
||||||
ReleaseBindInfo(&bindinfo);
|
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))
|
if(!(grfBINDF & BINDF_FROMURLMON))
|
||||||
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL);
|
IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_DIRECTBIND, NULL);
|
||||||
|
|
||||||
if(!This->file) {
|
if(This->file != INVALID_HANDLE_VALUE) {
|
||||||
WCHAR *ptr;
|
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);
|
hres = open_file(This, path, pOIProtSink);
|
||||||
|
SysFreeString(path);
|
||||||
/* Strip both forward and back slashes */
|
if(FAILED(hres))
|
||||||
if( (file_name[0] == '/' && file_name[1] == '/') ||
|
return hres;
|
||||||
(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 = IUri_GetDisplayUri(pUri, &url);
|
||||||
|
if(hres == S_OK) {
|
||||||
hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0);
|
hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0);
|
||||||
|
SysFreeString(url);
|
||||||
if(SUCCEEDED(hres)) {
|
if(SUCCEEDED(hres)) {
|
||||||
IInternetProtocolSink_ReportProgress(pOIProtSink,
|
IInternetProtocolSink_ReportProgress(pOIProtSink,
|
||||||
(grfBINDF & BINDF_FROMURLMON) ?
|
(grfBINDF & BINDF_FROMURLMON) ?
|
||||||
BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
|
BINDSTATUS_VERIFIEDMIMETYPEAVAILABLE : BINDSTATUS_MIMETYPEAVAILABLE,
|
||||||
mime);
|
mime);
|
||||||
CoTaskMemFree(mime);
|
CoTaskMemFree(mime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
heap_free(url);
|
IInternetProtocolSink_ReportData(pOIProtSink,
|
||||||
|
BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION,
|
||||||
|
This->size, This->size);
|
||||||
|
|
||||||
if(GetFileSizeEx(This->file, &size))
|
return report_result(pOIProtSink, S_OK, 0);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef PROTOCOL_THIS
|
#undef PROTOCOL_THIS
|
||||||
|
|
||||||
static const IInternetProtocolVtbl FileProtocolVtbl = {
|
static const IInternetProtocolExVtbl FileProtocolExVtbl = {
|
||||||
FileProtocol_QueryInterface,
|
FileProtocol_QueryInterface,
|
||||||
FileProtocol_AddRef,
|
FileProtocol_AddRef,
|
||||||
FileProtocol_Release,
|
FileProtocol_Release,
|
||||||
|
@ -298,7 +329,8 @@ static const IInternetProtocolVtbl FileProtocolVtbl = {
|
||||||
FileProtocol_Read,
|
FileProtocol_Read,
|
||||||
FileProtocol_Seek,
|
FileProtocol_Seek,
|
||||||
FileProtocol_LockRequest,
|
FileProtocol_LockRequest,
|
||||||
FileProtocol_UnlockRequest
|
FileProtocol_UnlockRequest,
|
||||||
|
FileProtocol_StartEx
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PRIORITY_THIS(iface) DEFINE_THIS(FileProtocol, InternetPriority, iface)
|
#define PRIORITY_THIS(iface) DEFINE_THIS(FileProtocol, InternetPriority, iface)
|
||||||
|
@ -307,19 +339,19 @@ static HRESULT WINAPI FilePriority_QueryInterface(IInternetPriority *iface,
|
||||||
REFIID riid, void **ppv)
|
REFIID riid, void **ppv)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PRIORITY_THIS(iface);
|
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)
|
static ULONG WINAPI FilePriority_AddRef(IInternetPriority *iface)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PRIORITY_THIS(iface);
|
FileProtocol *This = PRIORITY_THIS(iface);
|
||||||
return IInternetProtocol_AddRef(PROTOCOL(This));
|
return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
|
||||||
}
|
}
|
||||||
|
|
||||||
static ULONG WINAPI FilePriority_Release(IInternetPriority *iface)
|
static ULONG WINAPI FilePriority_Release(IInternetPriority *iface)
|
||||||
{
|
{
|
||||||
FileProtocol *This = PRIORITY_THIS(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)
|
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 = heap_alloc(sizeof(FileProtocol));
|
||||||
|
|
||||||
ret->lpIInternetProtocolVtbl = &FileProtocolVtbl;
|
ret->lpIInternetProtocolExVtbl = &FileProtocolExVtbl;
|
||||||
ret->lpInternetPriorityVtbl = &FilePriorityVtbl;
|
ret->lpInternetPriorityVtbl = &FilePriorityVtbl;
|
||||||
ret->file = NULL;
|
ret->file = INVALID_HANDLE_VALUE;
|
||||||
ret->priority = 0;
|
ret->priority = 0;
|
||||||
ret->ref = 1;
|
ret->ref = 1;
|
||||||
|
|
||||||
*ppobj = PROTOCOL(ret);
|
*ppobj = PROTOCOLEX(ret);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,14 +36,21 @@ typedef struct {
|
||||||
|
|
||||||
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface)
|
#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)
|
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||||
{
|
{
|
||||||
FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
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,
|
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
|
||||||
request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
|
request_flags|INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_PASSIVE,
|
||||||
(DWORD_PTR)&This->base);
|
(DWORD_PTR)&This->base);
|
||||||
|
SysFreeString(url);
|
||||||
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
||||||
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
||||||
return INET_E_RESOURCE_NOT_FOUND;
|
return INET_E_RESOURCE_NOT_FOUND;
|
||||||
|
@ -145,6 +152,8 @@ static HRESULT WINAPI FtpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
|
||||||
DWORD grfPI, HANDLE_PTR dwReserved)
|
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||||
{
|
{
|
||||||
FtpProtocol *This = PROTOCOL_THIS(iface);
|
FtpProtocol *This = PROTOCOL_THIS(iface);
|
||||||
|
IUri *uri;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
static const WCHAR ftpW[] = {'f','t','p',':'};
|
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)))
|
if(strncmpW(szUrl, ftpW, sizeof(ftpW)/sizeof(WCHAR)))
|
||||||
return MK_E_SYNTAX;
|
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)
|
static HRESULT WINAPI FtpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||||
|
|
|
@ -34,13 +34,20 @@ typedef struct {
|
||||||
|
|
||||||
#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(GopherProtocol, base, iface)
|
#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)
|
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||||
{
|
{
|
||||||
GopherProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
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,
|
This->base.request = InternetOpenUrlW(internet_session, url, NULL, 0,
|
||||||
request_flags, (DWORD_PTR)&This->base);
|
request_flags, (DWORD_PTR)&This->base);
|
||||||
|
SysFreeString(url);
|
||||||
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
if (!This->base.request && GetLastError() != ERROR_IO_PENDING) {
|
||||||
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
WARN("InternetOpenUrl failed: %d\n", GetLastError());
|
||||||
return INET_E_RESOURCE_NOT_FOUND;
|
return INET_E_RESOURCE_NOT_FOUND;
|
||||||
|
@ -125,11 +132,20 @@ static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szU
|
||||||
DWORD grfPI, HANDLE_PTR dwReserved)
|
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||||
{
|
{
|
||||||
GopherProtocol *This = PROTOCOL_THIS(iface);
|
GopherProtocol *This = PROTOCOL_THIS(iface);
|
||||||
|
IUri *uri;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
|
||||||
pOIBindInfo, grfPI, dwReserved);
|
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)
|
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)
|
#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)
|
HINTERNET internet_session, IInternetBindInfo *bind_info)
|
||||||
{
|
{
|
||||||
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
|
||||||
LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL;
|
LPWSTR addl_header = NULL, post_cookie = NULL, optional = NULL;
|
||||||
IServiceProvider *service_provider = NULL;
|
IServiceProvider *service_provider = NULL;
|
||||||
IHttpNegotiate2 *http_negotiate2 = NULL;
|
IHttpNegotiate2 *http_negotiate2 = NULL;
|
||||||
LPWSTR host, user, pass, path;
|
BSTR url, host, user, pass, path;
|
||||||
LPOLESTR accept_mimes[257];
|
LPOLESTR accept_mimes[257];
|
||||||
URL_COMPONENTSW url_comp;
|
const WCHAR **accept_types;
|
||||||
BYTE security_id[512];
|
BYTE security_id[512];
|
||||||
DWORD len = 0;
|
DWORD len = 0, port;
|
||||||
ULONG num;
|
ULONG num;
|
||||||
BOOL res, b;
|
BOOL res, b;
|
||||||
HRESULT hres;
|
HRESULT hres;
|
||||||
|
@ -88,24 +88,28 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
|
||||||
{'P','O','S','T',0},
|
{'P','O','S','T',0},
|
||||||
{'P','U','T',0}};
|
{'P','U','T',0}};
|
||||||
|
|
||||||
memset(&url_comp, 0, sizeof(url_comp));
|
hres = IUri_GetPort(uri, &port);
|
||||||
url_comp.dwStructSize = sizeof(url_comp);
|
if(FAILED(hres))
|
||||||
url_comp.dwSchemeLength = url_comp.dwHostNameLength = url_comp.dwUrlPathLength = url_comp.dwExtraInfoLength =
|
return hres;
|
||||||
url_comp.dwUserNameLength = url_comp.dwPasswordLength = 1;
|
|
||||||
if (!InternetCrackUrlW(url, 0, 0, &url_comp))
|
|
||||||
return MK_E_SYNTAX;
|
|
||||||
|
|
||||||
if(!url_comp.nPort)
|
hres = IUri_GetHost(uri, &host);
|
||||||
url_comp.nPort = This->https ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT;
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
|
|
||||||
host = heap_strndupW(url_comp.lpszHostName, url_comp.dwHostNameLength);
|
hres = IUri_GetUserName(uri, &user);
|
||||||
user = heap_strndupW(url_comp.lpszUserName, url_comp.dwUserNameLength);
|
if(SUCCEEDED(hres)) {
|
||||||
pass = heap_strndupW(url_comp.lpszPassword, url_comp.dwPasswordLength);
|
hres = IUri_GetPassword(uri, &pass);
|
||||||
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);
|
if(SUCCEEDED(hres)) {
|
||||||
heap_free(pass);
|
This->base.connection = InternetConnectW(internet_session, host, port, user, pass,
|
||||||
heap_free(user);
|
INTERNET_SERVICE_HTTP, This->https ? INTERNET_FLAG_SECURE : 0, (DWORD_PTR)&This->base);
|
||||||
heap_free(host);
|
SysFreeString(pass);
|
||||||
|
}
|
||||||
|
SysFreeString(user);
|
||||||
|
}
|
||||||
|
SysFreeString(host);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
if(!This->base.connection) {
|
if(!This->base.connection) {
|
||||||
WARN("InternetConnect failed: %d\n", GetLastError());
|
WARN("InternetConnect failed: %d\n", GetLastError());
|
||||||
return INET_E_CANNOT_CONNECT;
|
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;
|
num = sizeof(accept_mimes)/sizeof(accept_mimes[0])-1;
|
||||||
hres = IInternetBindInfo_GetBindString(bind_info, BINDSTRING_ACCEPT_MIMES, accept_mimes, num, &num);
|
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);
|
WARN("GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x\n", hres);
|
||||||
return INET_E_NO_VALID_MEDIA;
|
return INET_E_NO_VALID_MEDIA;
|
||||||
}
|
}
|
||||||
accept_mimes[num] = 0;
|
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)
|
if(This->https)
|
||||||
request_flags |= INTERNET_FLAG_SECURE;
|
request_flags |= INTERNET_FLAG_SECURE;
|
||||||
This->base.request = HttpOpenRequestW(This->base.connection,
|
|
||||||
This->base.bind_info.dwBindVerb < BINDVERB_CUSTOM
|
hres = IUri_GetPathAndQuery(uri, &path);
|
||||||
? wszBindVerb[This->base.bind_info.dwBindVerb] : This->base.bind_info.szCustomVerb,
|
if(SUCCEEDED(hres)) {
|
||||||
path, NULL, NULL, (LPCWSTR *)accept_mimes, request_flags, (DWORD_PTR)&This->base);
|
This->base.request = HttpOpenRequestW(This->base.connection,
|
||||||
heap_free(path);
|
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--)
|
while(num--)
|
||||||
CoTaskMemFree(accept_mimes[num]);
|
CoTaskMemFree(accept_mimes[num]);
|
||||||
|
if(FAILED(hres))
|
||||||
|
return hres;
|
||||||
if (!This->base.request) {
|
if (!This->base.request) {
|
||||||
WARN("HttpOpenRequest failed: %d\n", GetLastError());
|
WARN("HttpOpenRequest failed: %d\n", GetLastError());
|
||||||
return INET_E_RESOURCE_NOT_FOUND;
|
return INET_E_RESOURCE_NOT_FOUND;
|
||||||
|
@ -153,8 +165,15 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, LPCWSTR url, DWORD requ
|
||||||
return hres;
|
return hres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hres = IUri_GetAbsoluteUri(uri, &url);
|
||||||
|
if(FAILED(hres)) {
|
||||||
|
IServiceProvider_Release(service_provider);
|
||||||
|
return hres;
|
||||||
|
}
|
||||||
|
|
||||||
hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, wszHeaders,
|
hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, wszHeaders,
|
||||||
0, &addl_header);
|
0, &addl_header);
|
||||||
|
SysFreeString(url);
|
||||||
if(hres != S_OK) {
|
if(hres != S_OK) {
|
||||||
WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres);
|
WARN("IHttpNegotiate_BeginningTransaction failed: %08x\n", hres);
|
||||||
IServiceProvider_Release(service_provider);
|
IServiceProvider_Release(service_provider);
|
||||||
|
@ -382,6 +401,8 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
|
||||||
DWORD grfPI, HANDLE_PTR dwReserved)
|
DWORD grfPI, HANDLE_PTR dwReserved)
|
||||||
{
|
{
|
||||||
HttpProtocol *This = PROTOCOL_THIS(iface);
|
HttpProtocol *This = PROTOCOL_THIS(iface);
|
||||||
|
IUri *uri;
|
||||||
|
HRESULT hres;
|
||||||
|
|
||||||
static const WCHAR httpW[] = {'h','t','t','p',':'};
|
static const WCHAR httpW[] = {'h','t','t','p',':'};
|
||||||
static const WCHAR httpsW[] = {'h','t','t','p','s',':'};
|
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)))
|
: strncmpW(szUrl, httpW, sizeof(httpW)/sizeof(WCHAR)))
|
||||||
return MK_E_SYNTAX;
|
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)
|
static HRESULT WINAPI HttpProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
|
||||||
|
|
|
@ -234,7 +234,7 @@ HINTERNET get_internet_session(IInternetBindInfo *bind_info)
|
||||||
return internet_session;
|
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)
|
IInternetProtocolSink *protocol_sink, IInternetBindInfo *bind_info)
|
||||||
{
|
{
|
||||||
DWORD request_flags;
|
DWORD request_flags;
|
||||||
|
@ -265,7 +265,7 @@ HRESULT protocol_start(Protocol *protocol, IInternetProtocol *prot, LPCWSTR url,
|
||||||
if(protocol->bindf & BINDF_NEEDFILE)
|
if(protocol->bindf & BINDF_NEEDFILE)
|
||||||
request_flags |= INTERNET_FLAG_NEED_FILE;
|
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)) {
|
if(FAILED(hres)) {
|
||||||
protocol_close_connection(protocol);
|
protocol_close_connection(protocol);
|
||||||
return report_result(protocol, hres);
|
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 CreateFormatEnumerator(long ptr ptr)
|
||||||
@ stdcall CreateIUriBuilder(ptr long long ptr)
|
@ stdcall CreateIUriBuilder(ptr long long ptr)
|
||||||
@ stdcall CreateUri(wstr long long ptr)
|
@ stdcall CreateUri(wstr long long ptr)
|
||||||
|
@ stdcall CreateUriWithFragment(wstr wstr long long ptr)
|
||||||
@ stdcall CreateURLMoniker(ptr wstr ptr)
|
@ stdcall CreateURLMoniker(ptr wstr ptr)
|
||||||
@ stdcall CreateURLMonikerEx(ptr wstr ptr long)
|
@ stdcall CreateURLMonikerEx(ptr wstr ptr long)
|
||||||
@ stdcall -private DllCanUnloadNow()
|
@ 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 bind_to_object(IMoniker *mon, LPCWSTR url, IBindCtx *pbc, REFIID riid, void **ppv);
|
||||||
|
|
||||||
HRESULT create_binding_protocol(LPCWSTR url, BOOL from_urlmon, IInternetProtocol **protocol);
|
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*);
|
IWinInetInfo *get_wininet_info(IInternetProtocol*);
|
||||||
|
|
||||||
typedef struct ProtocolVtbl ProtocolVtbl;
|
typedef struct ProtocolVtbl ProtocolVtbl;
|
||||||
|
@ -105,12 +105,12 @@ typedef struct {
|
||||||
} Protocol;
|
} Protocol;
|
||||||
|
|
||||||
struct ProtocolVtbl {
|
struct ProtocolVtbl {
|
||||||
HRESULT (*open_request)(Protocol*,LPCWSTR,DWORD,HINTERNET,IInternetBindInfo*);
|
HRESULT (*open_request)(Protocol*,IUri*,DWORD,HINTERNET,IInternetBindInfo*);
|
||||||
HRESULT (*start_downloading)(Protocol*);
|
HRESULT (*start_downloading)(Protocol*);
|
||||||
void (*close_connection)(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_continue(Protocol*,PROTOCOLDATA*);
|
||||||
HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*);
|
HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*);
|
||||||
HRESULT protocol_lock_request(Protocol*);
|
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->entry );
|
||||||
list_init( &domain->cookies );
|
list_init( &domain->cookies );
|
||||||
|
|
||||||
domain->name = name;
|
domain->name = strdupW( name );
|
||||||
list_add_tail( &session->cookie_cache, &domain->entry );
|
list_add_tail( &session->cookie_cache, &domain->entry );
|
||||||
|
|
||||||
TRACE("%s\n", debugstr_w(domain->name));
|
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 );
|
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 );
|
list_add_tail( &domain->cookies, &cookie->entry );
|
||||||
|
|
||||||
TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path),
|
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 );
|
ret = add_cookie( session, cookie, cookie_domain, cookie_path );
|
||||||
|
|
||||||
end:
|
end:
|
||||||
if (!ret)
|
if (!ret) free_cookie( cookie );
|
||||||
{
|
heap_free( cookie_domain );
|
||||||
free_cookie( cookie );
|
heap_free( cookie_path );
|
||||||
heap_free( cookie_domain );
|
|
||||||
heap_free( cookie_path );
|
|
||||||
}
|
|
||||||
heap_free( buffer );
|
heap_free( buffer );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,7 @@
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ENOSPC 28
|
#include <stdio.h>
|
||||||
#define EAFNOSUPPORT 52
|
|
||||||
|
|
||||||
#ifndef IN6ADDRSZ
|
#ifndef IN6ADDRSZ
|
||||||
#define IN6ADDRSZ 16
|
#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));
|
return (inet_ntop6(src, dst, size));
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
errno = EAFNOSUPPORT;
|
WSASetLastError(WSAEAFNOSUPPORT);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
@ -88,7 +87,7 @@ inet_ntop4(const u_char *src, char *dst, size_t size)
|
||||||
char tmp[sizeof "255.255.255.255"];
|
char tmp[sizeof "255.255.255.255"];
|
||||||
|
|
||||||
if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
|
if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) {
|
||||||
errno = ENOSPC;
|
WSASetLastError(WSAEINVAL);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
strcpy(dst, tmp);
|
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.
|
* Check for overflow, copy, and we're done.
|
||||||
*/
|
*/
|
||||||
if ((size_t)(tp - tmp) > size) {
|
if ((size_t)(tp - tmp) > size) {
|
||||||
errno = ENOSPC;
|
WSASetLastError(WSAEINVAL);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
strcpy(dst, tmp);
|
strcpy(dst, tmp);
|
||||||
|
|
|
@ -42,6 +42,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpv)
|
||||||
DisableThreadLibraryCalls(hInstDLL);
|
DisableThreadLibraryCalls(hInstDLL);
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
|
netconn_unload();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -61,7 +62,6 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI DllCanUnloadNow(void)
|
HRESULT WINAPI DllCanUnloadNow(void)
|
||||||
{
|
{
|
||||||
FIXME("()\n");
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,10 +38,13 @@
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_OPENSSL_SSL_H
|
#ifdef HAVE_OPENSSL_SSL_H
|
||||||
# include <openssl/ssl.h>
|
# include <openssl/ssl.h>
|
||||||
|
# include <openssl/opensslv.h>
|
||||||
#undef FAR
|
#undef FAR
|
||||||
#undef DSA
|
#undef DSA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define NONAMELESSUNION
|
||||||
|
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
#include "wine/library.h"
|
#include "wine/library.h"
|
||||||
|
|
||||||
|
@ -58,10 +61,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
||||||
|
|
||||||
#define DEFAULT_SEND_TIMEOUT 30
|
|
||||||
#define DEFAULT_RECEIVE_TIMEOUT 30
|
|
||||||
#define RESPONSE_TIMEOUT 30
|
|
||||||
|
|
||||||
#ifndef HAVE_GETADDRINFO
|
#ifndef HAVE_GETADDRINFO
|
||||||
|
|
||||||
/* critical section to protect non-reentrant gethostbyname() */
|
/* 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>
|
#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 *libssl_handle;
|
||||||
static void *libcrypto_handle;
|
static void *libcrypto_handle;
|
||||||
|
|
||||||
|
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER> 0x1000000)
|
||||||
|
static const SSL_METHOD *method;
|
||||||
|
#else
|
||||||
static SSL_METHOD *method;
|
static SSL_METHOD *method;
|
||||||
|
#endif
|
||||||
static SSL_CTX *ctx;
|
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
|
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||||
|
|
||||||
MAKE_FUNCPTR( SSL_library_init );
|
MAKE_FUNCPTR( SSL_library_init );
|
||||||
MAKE_FUNCPTR( SSL_load_error_strings );
|
MAKE_FUNCPTR( SSL_load_error_strings );
|
||||||
MAKE_FUNCPTR( SSLv23_method );
|
MAKE_FUNCPTR( SSLv23_method );
|
||||||
|
MAKE_FUNCPTR( SSL_CTX_free );
|
||||||
MAKE_FUNCPTR( SSL_CTX_new );
|
MAKE_FUNCPTR( SSL_CTX_new );
|
||||||
MAKE_FUNCPTR( SSL_new );
|
MAKE_FUNCPTR( SSL_new );
|
||||||
MAKE_FUNCPTR( SSL_free );
|
MAKE_FUNCPTR( SSL_free );
|
||||||
|
@ -99,21 +116,49 @@ MAKE_FUNCPTR( SSL_connect );
|
||||||
MAKE_FUNCPTR( SSL_shutdown );
|
MAKE_FUNCPTR( SSL_shutdown );
|
||||||
MAKE_FUNCPTR( SSL_write );
|
MAKE_FUNCPTR( SSL_write );
|
||||||
MAKE_FUNCPTR( SSL_read );
|
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_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_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_get_error );
|
||||||
MAKE_FUNCPTR( ERR_error_string );
|
MAKE_FUNCPTR( ERR_error_string );
|
||||||
|
MAKE_FUNCPTR( X509_STORE_CTX_get_ex_data );
|
||||||
MAKE_FUNCPTR( i2d_X509 );
|
MAKE_FUNCPTR( i2d_X509 );
|
||||||
|
MAKE_FUNCPTR( sk_value );
|
||||||
|
MAKE_FUNCPTR( sk_num );
|
||||||
#undef MAKE_FUNCPTR
|
#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
|
#endif
|
||||||
|
|
||||||
/* translate a unix error code into a winsock error code */
|
/* translate a unix error code into a winsock error code */
|
||||||
|
#if 0
|
||||||
static int sock_get_error( int err )
|
static int sock_get_error( int err )
|
||||||
{
|
{
|
||||||
#if !defined(__MINGW32__) && !defined (_MSC_VER)
|
#if !defined(__MINGW32__) && !defined (_MSC_VER)
|
||||||
|
@ -179,24 +224,222 @@ static int sock_get_error( int err )
|
||||||
#endif
|
#endif
|
||||||
return err;
|
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 )
|
BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
{
|
{
|
||||||
|
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
conn->socket = -1;
|
conn->socket = -1;
|
||||||
if (!secure) return TRUE;
|
if (!secure) return TRUE;
|
||||||
|
|
||||||
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
|
#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 )))
|
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);
|
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
LeaveCriticalSection( &init_ssl_cs );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 )))
|
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);
|
ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
LeaveCriticalSection( &init_ssl_cs );
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
#define LOAD_FUNCPTR(x) \
|
#define LOAD_FUNCPTR(x) \
|
||||||
|
@ -204,11 +447,13 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
{ \
|
{ \
|
||||||
ERR("Failed to load symbol %s\n", #x); \
|
ERR("Failed to load symbol %s\n", #x); \
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||||
|
LeaveCriticalSection( &init_ssl_cs ); \
|
||||||
return FALSE; \
|
return FALSE; \
|
||||||
}
|
}
|
||||||
LOAD_FUNCPTR( SSL_library_init );
|
LOAD_FUNCPTR( SSL_library_init );
|
||||||
LOAD_FUNCPTR( SSL_load_error_strings );
|
LOAD_FUNCPTR( SSL_load_error_strings );
|
||||||
LOAD_FUNCPTR( SSLv23_method );
|
LOAD_FUNCPTR( SSLv23_method );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_free );
|
||||||
LOAD_FUNCPTR( SSL_CTX_new );
|
LOAD_FUNCPTR( SSL_CTX_new );
|
||||||
LOAD_FUNCPTR( SSL_new );
|
LOAD_FUNCPTR( SSL_new );
|
||||||
LOAD_FUNCPTR( SSL_free );
|
LOAD_FUNCPTR( SSL_free );
|
||||||
|
@ -217,11 +462,16 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
LOAD_FUNCPTR( SSL_shutdown );
|
LOAD_FUNCPTR( SSL_shutdown );
|
||||||
LOAD_FUNCPTR( SSL_write );
|
LOAD_FUNCPTR( SSL_write );
|
||||||
LOAD_FUNCPTR( SSL_read );
|
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_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_default_verify_paths );
|
||||||
|
LOAD_FUNCPTR( SSL_CTX_set_verify );
|
||||||
|
LOAD_FUNCPTR( SSL_get_current_cipher );
|
||||||
|
LOAD_FUNCPTR( SSL_CIPHER_get_bits );
|
||||||
#undef LOAD_FUNCPTR
|
#undef LOAD_FUNCPTR
|
||||||
|
|
||||||
#define LOAD_FUNCPTR(x) \
|
#define LOAD_FUNCPTR(x) \
|
||||||
|
@ -229,19 +479,72 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
{ \
|
{ \
|
||||||
ERR("Failed to load symbol %s\n", #x); \
|
ERR("Failed to load symbol %s\n", #x); \
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
|
||||||
|
LeaveCriticalSection( &init_ssl_cs ); \
|
||||||
return FALSE; \
|
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_get_error );
|
||||||
LOAD_FUNCPTR( ERR_error_string );
|
LOAD_FUNCPTR( ERR_error_string );
|
||||||
|
LOAD_FUNCPTR( X509_STORE_CTX_get_ex_data );
|
||||||
LOAD_FUNCPTR( i2d_X509 );
|
LOAD_FUNCPTR( i2d_X509 );
|
||||||
|
LOAD_FUNCPTR( sk_value );
|
||||||
|
LOAD_FUNCPTR( sk_num );
|
||||||
#undef LOAD_FUNCPTR
|
#undef LOAD_FUNCPTR
|
||||||
|
|
||||||
pSSL_library_init();
|
pSSL_library_init();
|
||||||
pSSL_load_error_strings();
|
pSSL_load_error_strings();
|
||||||
pBIO_new_fp( stderr, BIO_NOCLOSE );
|
|
||||||
|
|
||||||
method = pSSLv23_method();
|
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
|
#else
|
||||||
WARN("SSL support not compiled in.\n");
|
WARN("SSL support not compiled in.\n");
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
||||||
|
@ -250,6 +553,29 @@ BOOL netconn_init( netconn_t *conn, BOOL secure )
|
||||||
return TRUE;
|
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 )
|
BOOL netconn_connected( netconn_t *conn )
|
||||||
{
|
{
|
||||||
return (conn->socket != -1);
|
return (conn->socket != -1);
|
||||||
|
@ -295,36 +621,72 @@ BOOL netconn_close( netconn_t *conn )
|
||||||
return TRUE;
|
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));
|
state = 1;
|
||||||
set_last_error( sock_get_error( errno ) );
|
ioctlsocket( conn->socket, FIONBIO, &state );
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
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
|
#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 )))
|
if (!(conn->ssl_conn = pSSL_new( ctx )))
|
||||||
{
|
{
|
||||||
ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
||||||
set_last_error( ERROR_OUTOFMEMORY );
|
set_last_error( ERROR_OUTOFMEMORY );
|
||||||
goto fail;
|
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 ))
|
if (!pSSL_set_fd( conn->ssl_conn, conn->socket ))
|
||||||
{
|
{
|
||||||
ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
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)
|
if (pSSL_connect( conn->ssl_conn ) <= 0)
|
||||||
{
|
{
|
||||||
ERR("SSL_connect failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
|
DWORD err;
|
||||||
set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
|
|
||||||
|
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;
|
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");
|
TRACE("established SSL connection\n");
|
||||||
conn->secure = TRUE;
|
conn->secure = TRUE;
|
||||||
return 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 )
|
BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
*recvd = 0;
|
*recvd = 0;
|
||||||
if (!netconn_connected( conn )) return FALSE;
|
if (!netconn_connected( conn )) return FALSE;
|
||||||
if (!len) return TRUE;
|
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 */
|
/* check if we have enough data from the peek buffer */
|
||||||
if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
|
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 */
|
if (flags & MSG_PEEK) /* must copy into buffer */
|
||||||
{
|
{
|
||||||
conn->peek_len = *recvd;
|
conn->peek_len = ret;
|
||||||
if (!*recvd)
|
if (!ret)
|
||||||
{
|
{
|
||||||
heap_free( conn->peek_msg_mem );
|
heap_free( conn->peek_msg_mem );
|
||||||
conn->peek_msg_mem = NULL;
|
conn->peek_msg_mem = NULL;
|
||||||
conn->peek_msg = 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;
|
return TRUE;
|
||||||
#else
|
#else
|
||||||
return FALSE;
|
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 )
|
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||||
{
|
{
|
||||||
struct timeval tv;
|
|
||||||
fd_set infd;
|
fd_set infd;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
DWORD recvd = 0;
|
DWORD recvd = 0;
|
||||||
|
@ -484,11 +850,6 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||||
if (conn->secure)
|
if (conn->secure)
|
||||||
{
|
{
|
||||||
#ifdef SONAME_LIBSSL
|
#ifdef SONAME_LIBSSL
|
||||||
long timeout;
|
|
||||||
|
|
||||||
timeout = pSSL_CTX_get_timeout( ctx );
|
|
||||||
pSSL_CTX_set_timeout( ctx, DEFAULT_RECEIVE_TIMEOUT );
|
|
||||||
|
|
||||||
while (recvd < *buflen)
|
while (recvd < *buflen)
|
||||||
{
|
{
|
||||||
int dummy;
|
int dummy;
|
||||||
|
@ -504,7 +865,6 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||||
}
|
}
|
||||||
if (buffer[recvd] != '\r') recvd++;
|
if (buffer[recvd] != '\r') recvd++;
|
||||||
}
|
}
|
||||||
pSSL_CTX_set_timeout( ctx, timeout );
|
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
buffer[recvd++] = 0;
|
buffer[recvd++] = 0;
|
||||||
|
@ -516,16 +876,23 @@ BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||||
return FALSE;
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
FD_ZERO(&infd);
|
FD_ZERO(&infd);
|
||||||
FD_SET(conn->socket, &infd);
|
FD_SET(conn->socket, &infd);
|
||||||
tv.tv_sec=RESPONSE_TIMEOUT;
|
|
||||||
tv.tv_usec=0;
|
|
||||||
while (recvd < *buflen)
|
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 = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
|
||||||
{
|
{
|
||||||
if (res == -1) set_last_error( sock_get_error( errno ) );
|
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;
|
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;
|
char *hostname;
|
||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
|
@ -578,27 +945,53 @@ BOOL netconn_resolve( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr_in *
|
||||||
int ret;
|
int ret;
|
||||||
#else
|
#else
|
||||||
struct hostent *he;
|
struct hostent *he;
|
||||||
|
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!(hostname = strdupWA( hostnameW ))) return FALSE;
|
if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY;
|
||||||
|
|
||||||
#ifdef HAVE_GETADDRINFO
|
#ifdef HAVE_GETADDRINFO
|
||||||
memset( &hints, 0, sizeof(struct addrinfo) );
|
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;
|
hints.ai_family = AF_INET;
|
||||||
|
|
||||||
ret = getaddrinfo( hostname, NULL, &hints, &res );
|
ret = getaddrinfo( hostname, NULL, &hints, &res );
|
||||||
heap_free( hostname );
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
{
|
{
|
||||||
TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
|
TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret));
|
||||||
return FALSE;
|
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 );
|
freeaddrinfo( res );
|
||||||
|
return ERROR_SUCCESS;
|
||||||
#else
|
#else
|
||||||
EnterCriticalSection( &cs_gethostbyname );
|
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);
|
TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
|
||||||
LeaveCriticalSection( &cs_gethostbyname );
|
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) );
|
memset( sa, 0, sizeof(struct sockaddr_in) );
|
||||||
memcpy( &sa->sin_addr, he->h_addr, he->h_length );
|
memcpy( &sin->sin_addr, he->h_addr, he->h_length );
|
||||||
sa->sin_family = he->h_addrtype;
|
sin->sin_family = he->h_addrtype;
|
||||||
sa->sin_port = htons( port );
|
sin->sin_port = htons( port );
|
||||||
|
|
||||||
LeaveCriticalSection( &cs_gethostbyname );
|
LeaveCriticalSection( &cs_gethostbyname );
|
||||||
|
return ERROR_SUCCESS;
|
||||||
#endif
|
#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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,41 +1071,29 @@ const void *netconn_get_certificate( netconn_t *conn )
|
||||||
{
|
{
|
||||||
#ifdef SONAME_LIBSSL
|
#ifdef SONAME_LIBSSL
|
||||||
X509 *cert;
|
X509 *cert;
|
||||||
unsigned char *buffer, *p;
|
|
||||||
int len;
|
|
||||||
BOOL malloc = FALSE;
|
|
||||||
const CERT_CONTEXT *ret;
|
const CERT_CONTEXT *ret;
|
||||||
|
|
||||||
if (!conn->secure) return NULL;
|
if (!conn->secure) return NULL;
|
||||||
|
|
||||||
if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
|
if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
|
||||||
p = NULL;
|
ret = X509_to_cert_context( cert );
|
||||||
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;
|
return ret;
|
||||||
#else
|
#else
|
||||||
return NULL;
|
return NULL;
|
||||||
#endif
|
#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 "wine/debug.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "windef.h"
|
#include "windef.h"
|
||||||
#include "winbase.h"
|
#include "winbase.h"
|
||||||
#include "winhttp.h"
|
#include "winhttp.h"
|
||||||
#include "wincrypt.h"
|
#include "wincrypt.h"
|
||||||
|
#include "winreg.h"
|
||||||
|
|
||||||
#include "winhttp_private.h"
|
#include "winhttp_private.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
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 )
|
void set_last_error( DWORD error )
|
||||||
{
|
{
|
||||||
/* FIXME */
|
/* 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 )
|
static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
|
||||||
{
|
{
|
||||||
|
session_t *session = (session_t *)hdr;
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case WINHTTP_OPTION_REDIRECT_POLICY:
|
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);
|
*buflen = sizeof(DWORD);
|
||||||
return TRUE;
|
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:
|
default:
|
||||||
FIXME("unimplemented option %u\n", option);
|
FIXME("unimplemented option %u\n", option);
|
||||||
set_last_error( ERROR_INVALID_PARAMETER );
|
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 )
|
static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
|
||||||
{
|
{
|
||||||
|
session_t *session = (session_t *)hdr;
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case WINHTTP_OPTION_PROXY:
|
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:
|
case WINHTTP_OPTION_DISABLE_FEATURE:
|
||||||
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
|
set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE );
|
||||||
return FALSE;
|
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:
|
default:
|
||||||
FIXME("unimplemented option %u\n", option);
|
FIXME("unimplemented option %u\n", option);
|
||||||
set_last_error( ERROR_INVALID_PARAMETER );
|
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.vtbl = &session_vtbl;
|
||||||
session->hdr.flags = flags;
|
session->hdr.flags = flags;
|
||||||
session->hdr.refs = 1;
|
session->hdr.refs = 1;
|
||||||
session->access = access;
|
|
||||||
session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP;
|
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 );
|
list_init( &session->cookie_cache );
|
||||||
|
|
||||||
if (agent && !(session->agent = strdupW( agent ))) goto end;
|
if (agent && !(session->agent = strdupW( agent ))) goto end;
|
||||||
if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end;
|
if (access == WINHTTP_ACCESS_TYPE_DEFAULT_PROXY)
|
||||||
if (bypass && !(session->proxy_bypass = strdupW( bypass ))) goto end;
|
{
|
||||||
|
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;
|
if (!(handle = alloc_handle( &session->hdr ))) goto end;
|
||||||
session->hdr.handle = handle;
|
session->hdr.handle = handle;
|
||||||
|
@ -201,13 +269,199 @@ static void connect_destroy( object_header_t *hdr )
|
||||||
heap_free( connect );
|
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 =
|
static const object_vtbl_t connect_vtbl =
|
||||||
{
|
{
|
||||||
connect_destroy,
|
connect_destroy,
|
||||||
NULL,
|
connect_query_option,
|
||||||
NULL
|
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.@)
|
* WinHttpConnect (winhttp.@)
|
||||||
*/
|
*/
|
||||||
|
@ -252,11 +506,11 @@ HINTERNET WINAPI WinHttpConnect( HINTERNET hsession, LPCWSTR server, INTERNET_PO
|
||||||
connect->session = session;
|
connect->session = session;
|
||||||
list_add_head( &session->hdr.children, &connect->hdr.entry );
|
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;
|
connect->hostport = port;
|
||||||
|
|
||||||
if (server && !(connect->servername = strdupW( server ))) goto end;
|
if (!set_server_for_hostname( connect, server, port ))
|
||||||
connect->serverport = port;
|
goto end;
|
||||||
|
|
||||||
if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
|
if (!(hconnect = alloc_handle( &connect->hdr ))) goto end;
|
||||||
connect->hdr.handle = hconnect;
|
connect->hdr.handle = hconnect;
|
||||||
|
@ -296,13 +550,40 @@ static void request_destroy( object_header_t *hdr )
|
||||||
heap_free( request );
|
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 )
|
static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen )
|
||||||
{
|
{
|
||||||
|
request_t *request = (request_t *)hdr;
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case WINHTTP_OPTION_SECURITY_FLAGS:
|
case WINHTTP_OPTION_SECURITY_FLAGS:
|
||||||
{
|
{
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
|
int bits;
|
||||||
|
|
||||||
if (!buffer || *buflen < sizeof(flags))
|
if (!buffer || *buflen < sizeof(flags))
|
||||||
{
|
{
|
||||||
|
@ -313,6 +594,14 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
|
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE;
|
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;
|
*(DWORD *)buffer = flags;
|
||||||
*buflen = sizeof(flags);
|
*buflen = sizeof(flags);
|
||||||
return TRUE;
|
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:
|
case WINHTTP_OPTION_SERVER_CERT_CONTEXT:
|
||||||
{
|
{
|
||||||
const CERT_CONTEXT *cert;
|
const CERT_CONTEXT *cert;
|
||||||
request_t *request = (request_t *)hdr;
|
|
||||||
|
|
||||||
if (!buffer || *buflen < sizeof(cert))
|
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);
|
*buflen = sizeof(cert);
|
||||||
return TRUE;
|
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:
|
case WINHTTP_OPTION_SECURITY_KEY_BITNESS:
|
||||||
{
|
{
|
||||||
if (!buffer || *buflen < sizeof(DWORD))
|
if (!buffer || *buflen < sizeof(DWORD))
|
||||||
|
@ -343,10 +666,43 @@ static BOOL request_query_option( object_header_t *hdr, DWORD option, LPVOID buf
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(DWORD *)buffer = 128; /* FIXME */
|
*(DWORD *)buffer = netconn_get_cipher_strength( &request->netconn );
|
||||||
*buflen = sizeof(DWORD);
|
*buflen = sizeof(DWORD);
|
||||||
return TRUE;
|
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:
|
default:
|
||||||
FIXME("unimplemented option %u\n", option);
|
FIXME("unimplemented option %u\n", option);
|
||||||
set_last_error( ERROR_INVALID_PARAMETER );
|
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 )
|
static BOOL request_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen )
|
||||||
{
|
{
|
||||||
|
request_t *request = (request_t *)hdr;
|
||||||
|
|
||||||
switch (option)
|
switch (option)
|
||||||
{
|
{
|
||||||
case WINHTTP_OPTION_PROXY:
|
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;
|
hdr->redirect_policy = policy;
|
||||||
return TRUE;
|
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:
|
default:
|
||||||
FIXME("unimplemented option %u\n", option);
|
FIXME("unimplemented option %u\n", option);
|
||||||
set_last_error( ERROR_INVALID_PARAMETER );
|
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 );
|
list_add_head( &connect->hdr.children, &request->hdr.entry );
|
||||||
|
|
||||||
if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
|
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 (!verb || !verb[0]) verb = getW;
|
||||||
if (!(request->verb = strdupW( verb ))) goto end;
|
if (!(request->verb = strdupW( verb ))) goto end;
|
||||||
|
@ -648,17 +1090,167 @@ BOOL WINAPI WinHttpDetectAutoProxyConfigUrl( DWORD flags, LPWSTR *url )
|
||||||
return FALSE;
|
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.@)
|
* WinHttpGetDefaultProxyConfiguration (winhttp.@)
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI WinHttpGetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
|
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;
|
TRACE("%p\n", info);
|
||||||
info->lpszProxy = NULL;
|
|
||||||
info->lpszProxyBypass = NULL;
|
|
||||||
|
|
||||||
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -703,9 +1295,106 @@ BOOL WINAPI WinHttpGetProxyForUrl( HINTERNET hsession, LPCWSTR url, WINHTTP_AUTO
|
||||||
*/
|
*/
|
||||||
BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
|
BOOL WINAPI WinHttpSetDefaultProxyConfiguration( WINHTTP_PROXY_INFO *info )
|
||||||
{
|
{
|
||||||
FIXME("%p [%u, %s, %s]\n", info, info->dwAccessType, debugstr_w(info->lpszProxy),
|
LONG l;
|
||||||
debugstr_w(info->lpszProxyBypass));
|
HKEY key;
|
||||||
return TRUE;
|
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 )
|
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);
|
BOOL ret = TRUE;
|
||||||
return 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] =
|
static const WCHAR wkday[7][4] =
|
||||||
|
|
|
@ -133,7 +133,7 @@ BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONEN
|
||||||
p += 2;
|
p += 2;
|
||||||
|
|
||||||
if (!p[0]) goto exit;
|
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 )))
|
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);
|
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 );
|
set_last_error( ERROR_INVALID_PARAMETER );
|
||||||
return FALSE;
|
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 (!calc_length( uc, flags, &len )) return FALSE;
|
||||||
|
|
||||||
if (!url || *required < len)
|
if (*required < len)
|
||||||
{
|
{
|
||||||
*required = len + 1;
|
*required = len + 1;
|
||||||
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
set_last_error( ERROR_INSUFFICIENT_BUFFER );
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
<file>session.c</file>
|
<file>session.c</file>
|
||||||
<file>url.c</file>
|
<file>url.c</file>
|
||||||
<library>wine</library>
|
<library>wine</library>
|
||||||
|
<library>advapi32</library>
|
||||||
|
<library>crypt32</library>
|
||||||
<library>shlwapi</library>
|
<library>shlwapi</library>
|
||||||
<library>wininet</library>
|
<library>wininet</library>
|
||||||
<library>ws2_32</library>
|
<library>ws2_32</library>
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
#include "wine/unicode.h"
|
#include "wine/unicode.h"
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
# include <sys/socket.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_NETINET_IN_H
|
||||||
# include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,6 +96,10 @@ typedef struct
|
||||||
object_header_t hdr;
|
object_header_t hdr;
|
||||||
LPWSTR agent;
|
LPWSTR agent;
|
||||||
DWORD access;
|
DWORD access;
|
||||||
|
int resolve_timeout;
|
||||||
|
int connect_timeout;
|
||||||
|
int send_timeout;
|
||||||
|
int recv_timeout;
|
||||||
LPWSTR proxy_server;
|
LPWSTR proxy_server;
|
||||||
LPWSTR proxy_bypass;
|
LPWSTR proxy_bypass;
|
||||||
LPWSTR proxy_username;
|
LPWSTR proxy_username;
|
||||||
|
@ -110,7 +117,7 @@ typedef struct
|
||||||
LPWSTR password;
|
LPWSTR password;
|
||||||
INTERNET_PORT hostport;
|
INTERNET_PORT hostport;
|
||||||
INTERNET_PORT serverport;
|
INTERNET_PORT serverport;
|
||||||
struct sockaddr_in sockaddr;
|
struct sockaddr_storage sockaddr;
|
||||||
} connect_t;
|
} connect_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -121,6 +128,7 @@ typedef struct
|
||||||
char *peek_msg;
|
char *peek_msg;
|
||||||
char *peek_msg_mem;
|
char *peek_msg_mem;
|
||||||
size_t peek_len;
|
size_t peek_len;
|
||||||
|
DWORD security_flags;
|
||||||
} netconn_t;
|
} netconn_t;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -139,6 +147,10 @@ typedef struct
|
||||||
LPWSTR version;
|
LPWSTR version;
|
||||||
LPWSTR raw_headers;
|
LPWSTR raw_headers;
|
||||||
netconn_t netconn;
|
netconn_t netconn;
|
||||||
|
int resolve_timeout;
|
||||||
|
int connect_timeout;
|
||||||
|
int send_timeout;
|
||||||
|
int recv_timeout;
|
||||||
LPWSTR status_text;
|
LPWSTR status_text;
|
||||||
DWORD content_length; /* total number of bytes to be read (per chunk) */
|
DWORD content_length; /* total number of bytes to be read (per chunk) */
|
||||||
DWORD content_read; /* bytes read so far */
|
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 * );
|
void close_connection( request_t * );
|
||||||
|
|
||||||
BOOL netconn_close( netconn_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_connected( netconn_t * );
|
||||||
BOOL netconn_create( netconn_t *, int, int, int );
|
BOOL netconn_create( netconn_t *, int, int, int );
|
||||||
BOOL netconn_get_next_line( netconn_t *, char *, DWORD * );
|
BOOL netconn_get_next_line( netconn_t *, char *, DWORD * );
|
||||||
BOOL netconn_init( netconn_t *, BOOL );
|
BOOL netconn_init( netconn_t *, BOOL );
|
||||||
|
void netconn_unload( void );
|
||||||
BOOL netconn_query_data_available( netconn_t *, DWORD * );
|
BOOL netconn_query_data_available( netconn_t *, DWORD * );
|
||||||
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * );
|
BOOL netconn_recv( netconn_t *, void *, size_t, int, int * );
|
||||||
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * );
|
BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr *, socklen_t *, int );
|
||||||
BOOL netconn_secure_connect( netconn_t * );
|
BOOL netconn_secure_connect( netconn_t *, WCHAR * );
|
||||||
BOOL netconn_send( netconn_t *, const void *, size_t, int, int * );
|
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 * );
|
const void *netconn_get_certificate( netconn_t * );
|
||||||
|
int netconn_get_cipher_strength( netconn_t * );
|
||||||
|
|
||||||
BOOL set_cookies( request_t *, const WCHAR * );
|
BOOL set_cookies( request_t *, const WCHAR * );
|
||||||
BOOL add_cookie_headers( request_t * );
|
BOOL add_cookie_headers( request_t * );
|
||||||
BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD );
|
BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD );
|
||||||
void delete_domain( domain_t * );
|
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 )
|
static inline void *heap_alloc( SIZE_T size )
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,111 +1,104 @@
|
||||||
--- net.c Wed Sep 03 14:46:10 2008
|
--- wine-1.3.4/dlls/winhttp/net.c 2010-10-01 14:46:44.000000000 -0400
|
||||||
+++ net.c Sun Sep 07 10:54:26 2008
|
+++ dll/win32/winhttp/net.c 2010-10-09 17:04:11.000000000 -0400
|
||||||
@@ -59,6 +59,7 @@
|
@@ -158,6 +158,7 @@
|
||||||
|
|
||||||
#define DEFAULT_SEND_TIMEOUT 30
|
|
||||||
#define DEFAULT_RECEIVE_TIMEOUT 30
|
|
||||||
+#define RESPONSE_TIMEOUT 30
|
|
||||||
|
|
||||||
#ifndef HAVE_GETADDRINFO
|
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
+#if 0
|
|
||||||
/* translate a unix error code into a winsock error code */
|
/* translate a unix error code into a winsock error code */
|
||||||
|
+#if 0
|
||||||
static int sock_get_error( int err )
|
static int sock_get_error( int err )
|
||||||
{
|
{
|
||||||
@@ -174,6 +176,9 @@
|
#if !defined(__MINGW32__) && !defined (_MSC_VER)
|
||||||
}
|
@@ -223,6 +224,9 @@
|
||||||
|
#endif
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
+#else
|
+#else
|
||||||
+#define sock_get_error(x) WSAGetLastError()
|
+#define sock_get_error(x) WSAGetLastError()
|
||||||
+#endif
|
+#endif
|
||||||
|
|
||||||
BOOL netconn_init( netconn_t *conn, BOOL secure )
|
#ifdef SONAME_LIBSSL
|
||||||
{
|
static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
|
||||||
@@ -282,7 +287,7 @@
|
@@ -632,11 +636,16 @@
|
||||||
conn->secure = FALSE;
|
res = sock_get_error( errno );
|
||||||
}
|
if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
|
||||||
#endif
|
{
|
||||||
- res = close( conn->socket );
|
- struct pollfd pfd;
|
||||||
+ res = closesocket( conn->socket );
|
+ fd_set outfd;
|
||||||
conn->socket = -1;
|
+ struct timeval tv;
|
||||||
if (res == -1)
|
+
|
||||||
{
|
+ FD_ZERO(&outfd);
|
||||||
@@ -463,7 +468,7 @@
|
+ FD_SET(conn->socket, &outfd);
|
||||||
return TRUE;
|
|
||||||
}
|
- pfd.fd = conn->socket;
|
||||||
#ifdef FIONREAD
|
- pfd.events = POLLOUT;
|
||||||
- if (!(ret = ioctl( conn->socket, FIONREAD, &unread )))
|
- if (poll( &pfd, 1, timeout ) > 0)
|
||||||
+ if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread )))
|
+ tv.tv_sec = 0;
|
||||||
{
|
+ tv.tv_usec = timeout * 1000;
|
||||||
TRACE("%d bytes of queued, but unread data\n", unread);
|
+
|
||||||
*available += unread;
|
+ if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
|
||||||
@@ -474,7 +479,8 @@
|
ret = TRUE;
|
||||||
|
else
|
||||||
|
res = sock_get_error( errno );
|
||||||
|
@@ -832,7 +841,7 @@
|
||||||
|
|
||||||
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
|
||||||
{
|
{
|
||||||
- struct pollfd pfd;
|
- struct pollfd pfd;
|
||||||
+ struct timeval tv;
|
|
||||||
+ fd_set infd;
|
+ fd_set infd;
|
||||||
BOOL ret = FALSE;
|
BOOL ret = FALSE;
|
||||||
DWORD recvd = 0;
|
DWORD recvd = 0;
|
||||||
|
|
||||||
@@ -516,11 +522,13 @@
|
@@ -867,20 +876,22 @@
|
||||||
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
-
|
||||||
- pfd.fd = conn->socket;
|
- pfd.fd = conn->socket;
|
||||||
- pfd.events = POLLIN;
|
- pfd.events = POLLIN;
|
||||||
|
+
|
||||||
+ FD_ZERO(&infd);
|
+ FD_ZERO(&infd);
|
||||||
+ FD_SET(conn->socket, &infd);
|
+ FD_SET(conn->socket, &infd);
|
||||||
+ tv.tv_sec=RESPONSE_TIMEOUT;
|
+
|
||||||
+ tv.tv_usec=0;
|
|
||||||
while (recvd < *buflen)
|
while (recvd < *buflen)
|
||||||
{
|
{
|
||||||
- if (poll( &pfd, 1, DEFAULT_RECEIVE_TIMEOUT * 1000 ) > 0)
|
- int timeout, res;
|
||||||
+ if (select(conn->socket+1,&infd,NULL,NULL,&tv) > 0)
|
- struct timeval tv;
|
||||||
{
|
+ int res;
|
||||||
int res;
|
+ struct timeval tv, *ptv;
|
||||||
if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
|
socklen_t len = sizeof(tv);
|
||||||
--- 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"
|
|
||||||
|
|
||||||
+#include <stdio.h>
|
if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1))
|
||||||
#include <stdarg.h>
|
- timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
|
||||||
#ifdef HAVE_ARPA_INET_H
|
+ ptv = &tv;
|
||||||
# include <arpa/inet.h>
|
else
|
||||||
@@ -33,6 +34,8 @@
|
- timeout = -1;
|
||||||
#include "winhttp.h"
|
- 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 "winhttp_private.h"
|
||||||
+
|
|
||||||
+#include "inet_ntop.c"
|
|
||||||
|
|
||||||
|
+#include "inet_ntop.c"
|
||||||
|
+
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
|
||||||
|
|
||||||
--- winhttp_private.h Thu Sep 04 15:27:29 2008
|
static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0};
|
||||||
+++ 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;
|
|
||||||
|
|
|
@ -37,4 +37,33 @@
|
||||||
+#endif
|
+#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