Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
wine
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Package registry
Container Registry
Model registry
Operate
Terraform modules
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Alexey Alyaev
wine
Commits
dab80a8d
Commit
dab80a8d
authored
17 years ago
by
Misha Koshelev
Committed by
Alexandre Julliard
17 years ago
Browse files
Options
Downloads
Patches
Plain Diff
urlmon: Implement HttpProtocol.
parent
8a865e5a
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dlls/urlmon/http.c
+547
-13
547 additions, 13 deletions
dlls/urlmon/http.c
dlls/urlmon/tests/protocol.c
+1
-3
1 addition, 3 deletions
dlls/urlmon/tests/protocol.c
with
548 additions
and
16 deletions
dlls/urlmon/http.c
+
547
−
13
View file @
dab80a8d
/*
* Copyright 2005 Jacek Caban
* Copyright 2007 Misha Koshelev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
...
...
@@ -16,6 +17,12 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
/*
* TODO:
* - Handle redirects as native.
* - Add support for non-GET requests (e.g., POST).
*/
#include
<stdarg.h>
#define COBJMACROS
...
...
@@ -25,21 +32,177 @@
#include
"winuser.h"
#include
"ole2.h"
#include
"urlmon.h"
#include
"wininet.h"
#include
"urlmon_main.h"
#include
"wine/debug.h"
#include
"wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
urlmon
);
/* Flags are needed for, among other things, return HRESULTs from the Read function
* to conform to native. For example, Read returns:
*
* 1. E_PENDING if called before the request has completed,
* (flags = 0)
* 2. S_FALSE after all data has been read and S_OK has been reported,
* (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED)
* 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time
* this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink,
* (flags = FLAG_REQUEST_COMPLETE)
* but upon subsequent calls to Read no reporting will take place, yet
* InternetQueryDataAvailable will still be called, and, on failure,
* INET_E_DATA_NOT_AVAILABLE will still be returned.
* (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED)
*
* FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper
* ReportData reporting. For example, if OnResponse returns S_OK, Continue will
* report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will
* report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However,
* if OnResponse does not return S_OK, Continue will not report data, and Read
* will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all
* data has been read.
*/
#define FLAG_REQUEST_COMPLETE 0x1
#define FLAG_FIRST_DATA_REPORTED 0x2
#define FLAG_ALL_DATA_READ 0x4
#define FLAG_LAST_DATA_REPORTED 0x8
#define FLAG_RESULT_REPORTED 0x10
typedef
struct
{
const
IInternetProtocolVtbl
*
lpInternetProtocolVtbl
;
const
IInternetPriorityVtbl
*
lpInternetPriorityVtbl
;
DWORD
flags
;
IInternetProtocolSink
*
protocol_sink
;
IHttpNegotiate
*
http_negotiate
;
HINTERNET
internet
,
connect
,
request
;
HANDLE
lock
;
ULONG
current_position
,
content_length
,
available_bytes
;
LONG
priority
;
LONG
ref
;
}
HttpProtocol
;
/*
* Helpers
*/
static
void
HTTPPROTOCOL_ReportResult
(
HttpProtocol
*
This
,
HRESULT
hres
)
{
if
(
!
(
This
->
flags
&
FLAG_RESULT_REPORTED
)
&&
This
->
protocol_sink
)
{
This
->
flags
|=
FLAG_RESULT_REPORTED
;
IInternetProtocolSink_ReportResult
(
This
->
protocol_sink
,
hres
,
0
,
NULL
);
}
}
static
void
HTTPPROTOCOL_ReportData
(
HttpProtocol
*
This
)
{
DWORD
bscf
;
if
(
!
(
This
->
flags
&
FLAG_LAST_DATA_REPORTED
)
&&
This
->
protocol_sink
)
{
if
(
This
->
flags
&
FLAG_FIRST_DATA_REPORTED
)
{
bscf
=
BSCF_INTERMEDIATEDATANOTIFICATION
;
}
else
{
This
->
flags
|=
FLAG_FIRST_DATA_REPORTED
;
bscf
=
BSCF_FIRSTDATANOTIFICATION
;
}
if
(
This
->
flags
&
FLAG_ALL_DATA_READ
&&
!
(
This
->
flags
&
FLAG_LAST_DATA_REPORTED
))
{
This
->
flags
|=
FLAG_LAST_DATA_REPORTED
;
bscf
|=
BSCF_LASTDATANOTIFICATION
;
}
IInternetProtocolSink_ReportData
(
This
->
protocol_sink
,
bscf
,
This
->
current_position
+
This
->
available_bytes
,
This
->
content_length
);
}
}
static
void
HTTPPROTOCOL_AllDataRead
(
HttpProtocol
*
This
)
{
if
(
!
(
This
->
flags
&
FLAG_ALL_DATA_READ
))
This
->
flags
|=
FLAG_ALL_DATA_READ
;
HTTPPROTOCOL_ReportData
(
This
);
HTTPPROTOCOL_ReportResult
(
This
,
S_OK
);
}
static
void
HTTPPROTOCOL_Close
(
HttpProtocol
*
This
)
{
if
(
This
->
protocol_sink
)
{
IInternetProtocolSink_Release
(
This
->
protocol_sink
);
This
->
protocol_sink
=
0
;
}
if
(
This
->
http_negotiate
)
{
IHttpNegotiate_Release
(
This
->
http_negotiate
);
This
->
http_negotiate
=
0
;
}
if
(
This
->
request
)
InternetCloseHandle
(
This
->
request
);
CloseHandle
(
This
->
connect
);
CloseHandle
(
This
->
internet
);
This
->
request
=
This
->
connect
=
This
->
internet
=
0
;
This
->
flags
=
0
;
}
static
void
CALLBACK
HTTPPROTOCOL_InternetStatusCallback
(
HINTERNET
hInternet
,
DWORD_PTR
dwContext
,
DWORD
dwInternetStatus
,
LPVOID
lpvStatusInformation
,
DWORD
dwStatusInformationLength
)
{
HttpProtocol
*
This
=
(
HttpProtocol
*
)
dwContext
;
PROTOCOLDATA
data
;
ULONG
ulStatusCode
;
switch
(
dwInternetStatus
)
{
case
INTERNET_STATUS_RESOLVING_NAME
:
ulStatusCode
=
BINDSTATUS_FINDINGRESOURCE
;
break
;
case
INTERNET_STATUS_CONNECTING_TO_SERVER
:
ulStatusCode
=
BINDSTATUS_CONNECTING
;
break
;
case
INTERNET_STATUS_SENDING_REQUEST
:
ulStatusCode
=
BINDSTATUS_SENDINGREQUEST
;
break
;
case
INTERNET_STATUS_REQUEST_COMPLETE
:
This
->
flags
|=
FLAG_REQUEST_COMPLETE
;
/* PROTOCOLDATA same as native */
memset
(
&
data
,
0
,
sizeof
(
data
));
data
.
dwState
=
0xf1000000
;
data
.
pData
=
(
LPVOID
)
BINDSTATUS_DOWNLOADINGDATA
;
IInternetProtocolSink_Switch
(
This
->
protocol_sink
,
&
data
);
return
;
default:
WARN
(
"Unhandled Internet status callback %d
\n
"
,
dwInternetStatus
);
return
;
}
IInternetProtocolSink_ReportProgress
(
This
->
protocol_sink
,
ulStatusCode
,
(
LPWSTR
)
lpvStatusInformation
);
}
static
inline
LPWSTR
strndupW
(
LPWSTR
string
,
int
len
)
{
LPWSTR
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
(
len
+
1
)
*
sizeof
(
WCHAR
));
if
(
ret
)
{
memcpy
(
ret
,
string
,
len
*
sizeof
(
WCHAR
));
ret
[
len
]
=
0
;
}
return
ret
;
}
/*
* Interface implementations
*/
#define PROTOCOL(x) ((IInternetProtocol*) &(x)->lpInternetProtocolVtbl)
#define PRIORITY(x) ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
...
...
@@ -89,6 +252,7 @@ static ULONG WINAPI HttpProtocol_Release(IInternetProtocol *iface)
TRACE
(
"(%p) ref=%d
\n
"
,
This
,
ref
);
if
(
!
ref
)
{
HTTPPROTOCOL_Close
(
This
);
HeapFree
(
GetProcessHeap
(),
0
,
This
);
URLMON_UnlockModule
();
...
...
@@ -102,16 +266,310 @@ static HRESULT WINAPI HttpProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl
DWORD
grfPI
,
DWORD
dwReserved
)
{
HttpProtocol
*
This
=
PROTOCOL_THIS
(
iface
);
FIXME
(
"(%p)->(%s %p %p %08x %d)
\n
"
,
This
,
debugstr_w
(
szUrl
),
pOIProtSink
,
URL_COMPONENTSW
url
;
BINDINFO
bindinfo
;
DWORD
grfBINDF
=
0
,
len
=
0
;
ULONG
num
=
0
;
IServiceProvider
*
service_provider
=
0
;
IHttpNegotiate2
*
http_negotiate2
=
0
;
LPWSTR
host
=
0
,
path
=
0
,
user
=
0
,
pass
=
0
,
addl_header
=
0
;
BYTE
security_id
[
512
];
LPOLESTR
user_agent
,
accept_mimes
[
257
];
HRESULT
hres
;
static
const
WCHAR
wszHttp
[]
=
{
'h'
,
't'
,
't'
,
'p'
,
':'
};
static
const
WCHAR
wszHeaders
[]
=
{
'A'
,
'c'
,
'c'
,
'e'
,
'p'
,
't'
,
'-'
,
'E'
,
'n'
,
'c'
,
'o'
,
'd'
,
'i'
,
'n'
,
'g'
,
':'
,
' '
,
'g'
,
'z'
,
'i'
,
'p'
,
','
,
' '
,
'd'
,
'e'
,
'f'
,
'l'
,
'a'
,
't'
,
'e'
,
0
};
TRACE
(
"(%p)->(%s %p %p %08x %d)
\n
"
,
This
,
debugstr_w
(
szUrl
),
pOIProtSink
,
pOIBindInfo
,
grfPI
,
dwReserved
);
return
E_NOTIMPL
;
memset
(
&
bindinfo
,
0
,
sizeof
(
bindinfo
));
bindinfo
.
cbSize
=
sizeof
(
BINDINFO
);
hres
=
IInternetBindInfo_GetBindInfo
(
pOIBindInfo
,
&
grfBINDF
,
&
bindinfo
);
if
(
hres
!=
S_OK
)
{
WARN
(
"GetBindInfo failed: %08x
\n
"
,
hres
);
goto
done
;
}
if
(
lstrlenW
(
szUrl
)
<
sizeof
(
wszHttp
)
/
sizeof
(
WCHAR
)
||
memcmp
(
szUrl
,
wszHttp
,
sizeof
(
wszHttp
)))
{
hres
=
MK_E_SYNTAX
;
goto
done
;
}
memset
(
&
url
,
0
,
sizeof
(
url
));
url
.
dwStructSize
=
sizeof
(
url
);
url
.
dwSchemeLength
=
url
.
dwHostNameLength
=
url
.
dwUrlPathLength
=
url
.
dwUserNameLength
=
url
.
dwPasswordLength
=
1
;
if
(
!
InternetCrackUrlW
(
szUrl
,
0
,
ICU_ESCAPE
,
&
url
))
{
hres
=
MK_E_SYNTAX
;
goto
done
;
}
host
=
strndupW
(
url
.
lpszHostName
,
url
.
dwHostNameLength
);
path
=
strndupW
(
url
.
lpszUrlPath
,
url
.
dwUrlPathLength
);
user
=
strndupW
(
url
.
lpszUserName
,
url
.
dwUserNameLength
);
pass
=
strndupW
(
url
.
lpszPassword
,
url
.
dwPasswordLength
);
if
(
!
url
.
nPort
)
url
.
nPort
=
INTERNET_DEFAULT_HTTP_PORT
;
hres
=
IInternetBindInfo_GetBindString
(
pOIBindInfo
,
BINDSTRING_USER_AGENT
,
&
user_agent
,
1
,
&
num
);
if
(
hres
!=
S_OK
||
!
num
)
{
CHAR
null_char
=
0
;
LPSTR
user_agenta
=
NULL
;
len
=
0
;
if
((
hres
=
ObtainUserAgentString
(
0
,
&
null_char
,
&
len
))
!=
E_OUTOFMEMORY
)
{
WARN
(
"ObtainUserAgentString failed: %08x
\n
"
,
hres
);
}
else
if
(
!
(
user_agenta
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
*
sizeof
(
CHAR
))))
{
WARN
(
"Out of memory
\n
"
);
}
else
if
((
hres
=
ObtainUserAgentString
(
0
,
user_agenta
,
&
len
))
!=
S_OK
)
{
WARN
(
"ObtainUserAgentString failed: %08x
\n
"
,
hres
);
}
else
{
if
(
!
(
user_agent
=
CoTaskMemAlloc
((
len
)
*
sizeof
(
WCHAR
))))
WARN
(
"Out of memory
\n
"
);
else
MultiByteToWideChar
(
CP_ACP
,
0
,
user_agenta
,
-
1
,
user_agent
,
len
*
sizeof
(
WCHAR
));
}
HeapFree
(
GetProcessHeap
(),
0
,
user_agenta
);
}
This
->
internet
=
InternetOpenW
(
user_agent
,
0
,
NULL
,
NULL
,
INTERNET_FLAG_ASYNC
);
if
(
!
This
->
internet
)
{
WARN
(
"InternetOpen failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_NO_SESSION
;
goto
done
;
}
IInternetProtocolSink_AddRef
(
pOIProtSink
);
This
->
protocol_sink
=
pOIProtSink
;
/* Native does not check for success of next call, so we won't either */
InternetSetStatusCallbackW
(
This
->
internet
,
HTTPPROTOCOL_InternetStatusCallback
);
This
->
connect
=
InternetConnectW
(
This
->
internet
,
host
,
url
.
nPort
,
user
,
pass
,
INTERNET_SERVICE_HTTP
,
0
,
(
DWORD
)
This
);
if
(
!
This
->
connect
)
{
WARN
(
"InternetConnect failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_CANNOT_CONNECT
;
goto
done
;
}
num
=
sizeof
(
accept_mimes
)
/
sizeof
(
accept_mimes
[
0
])
-
1
;
hres
=
IInternetBindInfo_GetBindString
(
pOIBindInfo
,
BINDSTRING_ACCEPT_MIMES
,
accept_mimes
,
num
,
&
num
);
if
(
hres
!=
S_OK
)
{
WARN
(
"GetBindString BINDSTRING_ACCEPT_MIMES failed: %08x
\n
"
,
hres
);
hres
=
INET_E_NO_VALID_MEDIA
;
goto
done
;
}
accept_mimes
[
num
]
=
0
;
This
->
request
=
HttpOpenRequestW
(
This
->
connect
,
NULL
,
path
,
NULL
,
NULL
,
(
LPCWSTR
*
)
accept_mimes
,
0
,
(
DWORD
)
This
);
if
(
!
This
->
request
)
{
WARN
(
"HttpOpenRequest failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_RESOURCE_NOT_FOUND
;
goto
done
;
}
hres
=
IInternetProtocolSink_QueryInterface
(
pOIProtSink
,
&
IID_IServiceProvider
,
(
void
**
)
&
service_provider
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IInternetProtocolSink_QueryInterface IID_IServiceProvider failed: %08x
\n
"
,
hres
);
goto
done
;
}
hres
=
IServiceProvider_QueryService
(
service_provider
,
&
IID_IHttpNegotiate
,
&
IID_IHttpNegotiate
,
(
void
**
)
&
This
->
http_negotiate
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IServiceProvider_QueryService IID_IHttpNegotiate failed: %08x
\n
"
,
hres
);
goto
done
;
}
hres
=
IHttpNegotiate_BeginningTransaction
(
This
->
http_negotiate
,
szUrl
,
wszHeaders
,
0
,
&
addl_header
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IHttpNegotiate_BeginningTransaction failed: %08x
\n
"
,
hres
);
goto
done
;
}
hres
=
IServiceProvider_QueryService
(
service_provider
,
&
IID_IHttpNegotiate2
,
&
IID_IHttpNegotiate2
,
(
void
**
)
&
http_negotiate2
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IServiceProvider_QueryService IID_IHttpNegotiate2 failed: %08x
\n
"
,
hres
);
/* No goto done as per native */
}
else
{
len
=
sizeof
(
security_id
)
/
sizeof
(
security_id
[
0
]);
hres
=
IHttpNegotiate2_GetRootSecurityId
(
http_negotiate2
,
security_id
,
&
len
,
0
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IHttpNegotiate2_GetRootSecurityId failed: %08x
\n
"
,
hres
);
/* No goto done as per native */
}
}
/* FIXME: Handle security_id. Native calls undocumented function IsHostInProxyBypassList. */
if
(
!
HttpSendRequestW
(
This
->
request
,
wszHeaders
,
lstrlenW
(
wszHeaders
),
NULL
,
0
)
&&
GetLastError
()
!=
ERROR_IO_PENDING
)
{
WARN
(
"HttpSendRequest failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_DOWNLOAD_FAILURE
;
goto
done
;
}
hres
=
S_OK
;
done:
if
(
hres
!=
S_OK
)
{
IInternetProtocolSink_ReportResult
(
pOIProtSink
,
hres
,
0
,
NULL
);
HTTPPROTOCOL_Close
(
This
);
}
CoTaskMemFree
(
addl_header
);
if
(
http_negotiate2
)
IHttpNegotiate2_Release
(
http_negotiate2
);
if
(
service_provider
)
IServiceProvider_Release
(
service_provider
);
while
(
num
<
sizeof
(
accept_mimes
)
/
sizeof
(
accept_mimes
[
0
])
&&
accept_mimes
[
num
])
CoTaskMemFree
(
accept_mimes
[
num
++
]);
CoTaskMemFree
(
user_agent
);
HeapFree
(
GetProcessHeap
(),
0
,
pass
);
HeapFree
(
GetProcessHeap
(),
0
,
user
);
HeapFree
(
GetProcessHeap
(),
0
,
path
);
HeapFree
(
GetProcessHeap
(),
0
,
host
);
ReleaseBindInfo
(
&
bindinfo
);
return
hres
;
}
static
HRESULT
WINAPI
HttpProtocol_Continue
(
IInternetProtocol
*
iface
,
PROTOCOLDATA
*
pProtocolData
)
{
HttpProtocol
*
This
=
PROTOCOL_THIS
(
iface
);
FIXME
(
"(%p)->(%p)
\n
"
,
This
,
pProtocolData
);
return
E_NOTIMPL
;
DWORD
len
=
sizeof
(
DWORD
),
status_code
;
LPWSTR
response_headers
=
0
,
content_type
=
0
,
content_length
=
0
;
static
const
WCHAR
wszDefaultContentType
[]
=
{
't'
,
'e'
,
'x'
,
't'
,
'/'
,
'h'
,
't'
,
'm'
,
'l'
,
0
};
TRACE
(
"(%p)->(%p)
\n
"
,
This
,
pProtocolData
);
if
(
!
pProtocolData
)
WARN
(
"Expected pProtocolData to be non-NULL
\n
"
);
else
if
(
!
This
->
request
)
WARN
(
"Expected request to be non-NULL
\n
"
);
else
if
(
!
This
->
http_negotiate
)
WARN
(
"Expected IHttpNegotiate pointer to be non-NULL
\n
"
);
else
if
(
!
This
->
protocol_sink
)
WARN
(
"Expected IInternetProtocolSink pointer to be non-NULL
\n
"
);
else
if
(
pProtocolData
->
pData
==
(
LPVOID
)
BINDSTATUS_DOWNLOADINGDATA
)
{
if
(
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_STATUS_CODE
|
HTTP_QUERY_FLAG_NUMBER
,
&
status_code
,
&
len
,
NULL
))
{
WARN
(
"HttpQueryInfo failed: %d
\n
"
,
GetLastError
());
}
else
{
len
=
0
;
if
((
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_RAW_HEADERS_CRLF
,
response_headers
,
&
len
,
NULL
)
&&
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
||
!
(
response_headers
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
))
||
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_RAW_HEADERS_CRLF
,
response_headers
,
&
len
,
NULL
))
{
WARN
(
"HttpQueryInfo failed: %d
\n
"
,
GetLastError
());
}
else
{
HRESULT
hres
=
IHttpNegotiate_OnResponse
(
This
->
http_negotiate
,
status_code
,
response_headers
,
NULL
,
NULL
);
if
(
hres
!=
S_OK
)
{
WARN
(
"IHttpNegotiate_OnResponse failed: %08x
\n
"
,
hres
);
goto
done
;
}
}
}
len
=
0
;
if
((
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_CONTENT_TYPE
,
content_type
,
&
len
,
NULL
)
&&
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
||
!
(
content_type
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
))
||
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_CONTENT_TYPE
,
content_type
,
&
len
,
NULL
))
{
WARN
(
"HttpQueryInfo failed: %d
\n
"
,
GetLastError
());
IInternetProtocolSink_ReportProgress
(
This
->
protocol_sink
,
BINDSTATUS_MIMETYPEAVAILABLE
,
wszDefaultContentType
);
}
else
{
IInternetProtocolSink_ReportProgress
(
This
->
protocol_sink
,
BINDSTATUS_MIMETYPEAVAILABLE
,
content_type
);
}
len
=
0
;
if
((
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_CONTENT_LENGTH
,
content_length
,
&
len
,
NULL
)
&&
GetLastError
()
!=
ERROR_INSUFFICIENT_BUFFER
)
||
!
(
content_length
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
))
||
!
HttpQueryInfoW
(
This
->
request
,
HTTP_QUERY_CONTENT_LENGTH
,
content_length
,
&
len
,
NULL
))
{
WARN
(
"HttpQueryInfo failed: %d
\n
"
,
GetLastError
());
This
->
content_length
=
0
;
}
else
{
This
->
content_length
=
atoiW
(
content_length
);
}
if
(
!
InternetQueryDataAvailable
(
This
->
request
,
&
This
->
available_bytes
,
0
,
0
))
{
WARN
(
"InternetQueryDataAvailable failed: %d
\n
"
,
GetLastError
());
HTTPPROTOCOL_ReportResult
(
This
,
INET_E_DATA_NOT_AVAILABLE
);
}
else
{
HTTPPROTOCOL_ReportData
(
This
);
}
}
done:
HeapFree
(
GetProcessHeap
(),
0
,
response_headers
);
HeapFree
(
GetProcessHeap
(),
0
,
content_type
);
HeapFree
(
GetProcessHeap
(),
0
,
content_length
);
/* Returns S_OK on native */
return
S_OK
;
}
static
HRESULT
WINAPI
HttpProtocol_Abort
(
IInternetProtocol
*
iface
,
HRESULT
hrReason
,
...
...
@@ -147,8 +605,66 @@ static HRESULT WINAPI HttpProtocol_Read(IInternetProtocol *iface, void *pv,
ULONG
cb
,
ULONG
*
pcbRead
)
{
HttpProtocol
*
This
=
PROTOCOL_THIS
(
iface
);
FIXME
(
"(%p)->(%p %u %p)
\n
"
,
This
,
pv
,
cb
,
pcbRead
);
return
E_NOTIMPL
;
ULONG
read
=
0
,
len
=
0
;
HRESULT
hres
=
S_FALSE
;
TRACE
(
"(%p)->(%p %u %p)
\n
"
,
This
,
pv
,
cb
,
pcbRead
);
if
(
!
(
This
->
flags
&
FLAG_REQUEST_COMPLETE
))
{
hres
=
E_PENDING
;
}
else
while
(
!
(
This
->
flags
&
FLAG_ALL_DATA_READ
)
&&
read
<
cb
)
{
if
(
This
->
available_bytes
==
0
)
{
if
(
!
InternetQueryDataAvailable
(
This
->
request
,
&
This
->
available_bytes
,
0
,
0
))
{
WARN
(
"InternetQueryDataAvailable failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_DATA_NOT_AVAILABLE
;
HTTPPROTOCOL_ReportResult
(
This
,
hres
);
goto
done
;
}
else
if
(
This
->
available_bytes
==
0
)
{
HTTPPROTOCOL_AllDataRead
(
This
);
}
}
else
{
if
(
!
InternetReadFile
(
This
->
request
,
((
BYTE
*
)
pv
)
+
read
,
This
->
available_bytes
>
cb
-
read
?
cb
-
read
:
This
->
available_bytes
,
&
len
))
{
WARN
(
"InternetReadFile failed: %d
\n
"
,
GetLastError
());
hres
=
INET_E_DOWNLOAD_FAILURE
;
HTTPPROTOCOL_ReportResult
(
This
,
hres
);
goto
done
;
}
else
if
(
len
==
0
)
{
HTTPPROTOCOL_AllDataRead
(
This
);
}
else
{
read
+=
len
;
This
->
current_position
+=
len
;
This
->
available_bytes
-=
len
;
}
}
}
/* Per MSDN this should be if (read == cb), but native returns S_OK
* if any bytes were read, so we will too */
if
(
read
)
hres
=
S_OK
;
done:
if
(
pcbRead
)
*
pcbRead
=
read
;
return
hres
;
}
static
HRESULT
WINAPI
HttpProtocol_Seek
(
IInternetProtocol
*
iface
,
LARGE_INTEGER
dlibMove
,
...
...
@@ -162,15 +678,29 @@ static HRESULT WINAPI HttpProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER
static
HRESULT
WINAPI
HttpProtocol_LockRequest
(
IInternetProtocol
*
iface
,
DWORD
dwOptions
)
{
HttpProtocol
*
This
=
PROTOCOL_THIS
(
iface
);
FIXME
(
"(%p)->(%08x)
\n
"
,
This
,
dwOptions
);
return
E_NOTIMPL
;
TRACE
(
"(%p)->(%08x)
\n
"
,
This
,
dwOptions
);
if
(
!
InternetLockRequestFile
(
This
->
request
,
&
This
->
lock
))
WARN
(
"InternetLockRequest failed: %d
\n
"
,
GetLastError
());
return
S_OK
;
}
static
HRESULT
WINAPI
HttpProtocol_UnlockRequest
(
IInternetProtocol
*
iface
)
{
HttpProtocol
*
This
=
PROTOCOL_THIS
(
iface
);
FIXME
(
"(%p)
\n
"
,
This
);
return
E_NOTIMPL
;
TRACE
(
"(%p)
\n
"
,
This
);
if
(
This
->
lock
)
{
if
(
!
InternetUnlockRequestFile
(
This
->
lock
))
WARN
(
"InternetUnlockRequest failed: %d
\n
"
,
GetLastError
());
This
->
lock
=
0
;
}
return
S_OK
;
}
#undef PROTOCOL_THIS
...
...
@@ -253,10 +783,14 @@ HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
ret
->
lpInternetProtocolVtbl
=
&
HttpProtocolVtbl
;
ret
->
lpInternetPriorityVtbl
=
&
HttpPriorityVtbl
;
ret
->
ref
=
1
;
ret
->
flags
=
0
;
ret
->
protocol_sink
=
0
;
ret
->
http_negotiate
=
0
;
ret
->
internet
=
ret
->
connect
=
ret
->
request
=
0
;
ret
->
lock
=
0
;
ret
->
current_position
=
ret
->
content_length
=
ret
->
available_bytes
=
0
;
ret
->
priority
=
0
;
ret
->
ref
=
1
;
*
ppobj
=
PROTOCOL
(
ret
);
...
...
This diff is collapsed.
Click to expand it.
dlls/urlmon/tests/protocol.c
+
1
−
3
View file @
dab80a8d
...
...
@@ -1057,9 +1057,7 @@ static BOOL http_protocol_start(LPCWSTR url, BOOL is_first)
SET_EXPECT
(
GetRootSecurityId
);
hres
=
IInternetProtocol_Start
(
http_protocol
,
url
,
&
protocol_sink
,
&
bind_info
,
0
,
0
);
todo_wine
{
ok
(
hres
==
S_OK
,
"Start failed: %08x
\n
"
,
hres
);
}
ok
(
hres
==
S_OK
,
"Start failed: %08x
\n
"
,
hres
);
if
(
FAILED
(
hres
))
return
FALSE
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment