Windows2003-3790/inetcore/wininet/dll/inetapiw.cxx
2020-09-30 16:53:55 +02:00

1444 lines
36 KiB
C++
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
inetapiw.cxx
Abstract:
Contains the wide-character Internet APIs
Contents:
InternetCrackUrlW
InternetCreateUrlW
InternetCanonicalizeUrlW
InternetCombineUrlW
InternetOpenW
InternetConnectW
InternetOpenUrlW
InternetReadFileExW
InternetWriteFileExW
InternetFindNextFileW
InternetQueryOptionW
InternetSetOptionW
InternetGetLastResponseInfoW
InternetSetStatusCallbackW
Author:
Richard L Firth (rfirth) 02-Mar-1995
Environment:
Win32(s) user-mode DLL
Revision History:
02-Mar-1995 rfirth
Created
--*/
#include <wininetp.h>
// because wininet doesnt know about IStream
#define NO_SHLWAPI_STREAM
#include <shlwapi.h>
#include <shlwapip.h>
extern BOOL TransformFtpFindDataToW(LPWIN32_FIND_DATAA pfdA, LPWIN32_FIND_DATAW pfdW);
extern BOOL TransformGopherFindDataToW(LPGOPHER_FIND_DATAA pgfdA, LPGOPHER_FIND_DATAW pgfdW);
// -- FixStrings ------
// Used in InternetCrackUrlW only.
// Either
// (a) If we have an ansi string, AND a unicode buffer, convert from ansi to unicode
// (b) If we have an ansi string, but NO unicode buffer, determine where the ansi string
// occurs in the unicode URL, and point the component there.
VOID
FixStrings(
LPSTR& pszA,
DWORD cbA,
LPWSTR& pszW,
DWORD& ccW,
LPSTR pszUrlA,
LPCWSTR pszUrlW)
{
if (!pszA)
return;
if (pszW)
{
ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA+1, pszW, ccW) - 1;
}
else
{
pszW = (LPWSTR)(pszUrlW + MultiByteToWideChar(CP_ACP, 0,
pszUrlA, (int) (pszA-pszUrlA), NULL, 0));
ccW = MultiByteToWideChar(CP_ACP, 0, pszA, cbA, NULL, 0);
}
}
//
// functions
//
INTERNETAPI_(BOOL) InternetCrackUrlW(
IN LPCWSTR pszUrlW,
IN DWORD dwUrlLengthW,
IN DWORD dwFlags,
IN OUT LPURL_COMPONENTSW pUCW
)
/*++
Routine Description:
Cracks an URL into its constituent parts. Optionally escapes the url-path.
We assume that the user has supplied large enough buffers for the various
URL parts
Arguments:
pszUrl - pointer to URL to crack
dwUrlLength - 0 if pszUrl is ASCIIZ string, else length of pszUrl
dwFlags - flags controlling operation
lpUrlComponents - pointer to URL_COMPONENTS
Return Value:
BOOL
Success - TRUE
Failure - FALSE. Call GetLastError() for more info
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetCrackUrlW",
"%wq, %#x, %#x, %#x",
pszUrlW,
dwUrlLengthW,
dwFlags,
pUCW
));
INET_ASSERT(pszUrlW);
INET_ASSERT(pUCW);
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE;
BOOL fContinue;
DWORD c;
MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
URL_COMPONENTSA UCA;
if (!(pszUrlW && pUCW))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
UCA.dwStructSize = sizeof(URL_COMPONENTSA);
ALLOC_MB(pszUrlW, dwUrlLengthW, mpUrlA);
if (!mpUrlA.psStr) {
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszUrlW, mpUrlA);
for (c=0; c<=5; c++) {
LPWSTR pszWorker;
DWORD ccLen;
MEMORYPACKET* pmpWorker;
switch(c)
{
case 0:
pszWorker = pUCW->lpszScheme;
ccLen = pUCW->dwSchemeLength;
pmpWorker = &mpScheme;
break;
case 1:
pszWorker = pUCW->lpszHostName;
ccLen = pUCW->dwHostNameLength;
pmpWorker = &mpHostName;
break;
case 2:
pszWorker = pUCW->lpszUserName;
ccLen = pUCW->dwUserNameLength;
pmpWorker = &mpUserName;
break;
case 3:
pszWorker = pUCW->lpszPassword;
ccLen = pUCW->dwPasswordLength;
pmpWorker = &mpPassword;
break;
case 4:
pszWorker = pUCW->lpszUrlPath;
ccLen = pUCW->dwUrlPathLength;
pmpWorker = &mpUrlPath;
break;
case 5:
pszWorker = pUCW->lpszExtraInfo;
ccLen = pUCW->dwExtraInfoLength;
pmpWorker = &mpExtraInfo;
break;
}
if (pszWorker) {
ALLOC_MB(pszWorker,ccLen,(*pmpWorker));
if (!pmpWorker->psStr) {
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
} else {
pmpWorker->dwAlloc = ccLen;
}
};
REASSIGN_ALLOC(mpScheme,UCA.lpszScheme,UCA.dwSchemeLength);
REASSIGN_ALLOC(mpHostName, UCA.lpszHostName,UCA.dwHostNameLength);
REASSIGN_ALLOC(mpUserName, UCA.lpszUserName,UCA.dwUserNameLength);
REASSIGN_ALLOC(mpPassword,UCA.lpszPassword,UCA.dwPasswordLength);
REASSIGN_ALLOC(mpUrlPath,UCA.lpszUrlPath,UCA.dwUrlPathLength);
REASSIGN_ALLOC(mpExtraInfo,UCA.lpszExtraInfo,UCA.dwExtraInfoLength);
fResult = InternetCrackUrlA(mpUrlA.psStr, mpUrlA.dwSize, dwFlags, &UCA);
if (fResult) {
FixStrings(UCA.lpszScheme, UCA.dwSchemeLength, pUCW->lpszScheme,
pUCW->dwSchemeLength, mpUrlA.psStr, pszUrlW);
FixStrings(UCA.lpszHostName, UCA.dwHostNameLength, pUCW->lpszHostName,
pUCW->dwHostNameLength, mpUrlA.psStr, pszUrlW);
FixStrings(UCA.lpszUserName, UCA.dwUserNameLength, pUCW->lpszUserName,
pUCW->dwUserNameLength, mpUrlA.psStr, pszUrlW);
FixStrings(UCA.lpszPassword, UCA.dwPasswordLength, pUCW->lpszPassword,
pUCW->dwPasswordLength, mpUrlA.psStr, pszUrlW);
FixStrings(UCA.lpszUrlPath, UCA.dwUrlPathLength, pUCW->lpszUrlPath,
pUCW->dwUrlPathLength, mpUrlA.psStr, pszUrlW);
FixStrings(UCA.lpszExtraInfo, UCA.dwExtraInfoLength, pUCW->lpszExtraInfo,
pUCW->dwExtraInfoLength, mpUrlA.psStr, pszUrlW);
pUCW->nScheme = UCA.nScheme;
pUCW->nPort = UCA.nPort;
pUCW->dwStructSize = sizeof(URL_COMPONENTSW);
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(BOOL) InternetCreateUrlW(
IN LPURL_COMPONENTSW pUCW,
IN DWORD dwFlags,
OUT LPWSTR pszUrlW,
IN OUT LPDWORD pdwUrlLengthW
)
/*++
Routine Description:
Creates an URL from its constituent parts
Arguments:
Return Value:
BOOL
Success - URL written to pszUrl
Failure - call GetLastError() for more info
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetCreateUrlW",
"%#x, %#x, %#x, %#x",
pUCW,
dwFlags,
pszUrlW,
pdwUrlLengthW
));
// INET_ASSERT(pszUrlW);
INET_ASSERT(pUCW);
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE;
MEMORYPACKET mpUrlA, mpHostName, mpUserName, mpScheme, mpPassword, mpUrlPath, mpExtraInfo;
URL_COMPONENTSA UCA;
if (!pdwUrlLengthW
|| (pUCW==NULL)
|| IsBadWritePtr(pUCW, sizeof(*pUCW))
|| (pUCW->dwStructSize != sizeof(*pUCW))
|| (pszUrlW && IsBadWritePtr(pszUrlW, *pdwUrlLengthW*sizeof(WCHAR))))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (pszUrlW)
{
ALLOC_MB(pszUrlW, *pdwUrlLengthW, mpUrlA);
if (!mpUrlA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
mpUrlA.dwSize = mpUrlA.dwAlloc;
UCA.dwStructSize = sizeof(URL_COMPONENTSA);
UCA.nScheme = pUCW->nScheme;
UCA.nPort = pUCW->nPort;
if (pUCW->lpszScheme)
{
ALLOC_MB(pUCW->lpszScheme, pUCW->dwSchemeLength, mpScheme);
if (!mpScheme.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszScheme, mpScheme);
}
REASSIGN_SIZE(mpScheme, UCA.lpszScheme, UCA.dwSchemeLength);
if (pUCW->lpszHostName)
{
ALLOC_MB(pUCW->lpszHostName, pUCW->dwHostNameLength, mpHostName);
if (!mpHostName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszHostName, mpHostName);
}
REASSIGN_SIZE(mpHostName, UCA.lpszHostName, UCA.dwHostNameLength);
if (pUCW->lpszUserName)
{
ALLOC_MB(pUCW->lpszUserName, pUCW->dwUserNameLength, mpUserName);
if (!mpUserName.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszUserName, mpUserName);
}
REASSIGN_SIZE(mpUserName, UCA.lpszUserName, UCA.dwUserNameLength);
if (pUCW->lpszPassword)
{
ALLOC_MB(pUCW->lpszPassword, pUCW->dwPasswordLength, mpPassword);
if (!mpPassword.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszPassword, mpPassword);
}
REASSIGN_SIZE(mpPassword, UCA.lpszPassword, UCA.dwPasswordLength);
if (pUCW->lpszUrlPath)
{
ALLOC_MB(pUCW->lpszUrlPath, pUCW->dwUrlPathLength, mpUrlPath);
if (!mpUrlPath.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszUrlPath, mpUrlPath);
}
REASSIGN_SIZE(mpUrlPath, UCA.lpszUrlPath, UCA.dwUrlPathLength);
if (pUCW->lpszExtraInfo)
{
ALLOC_MB(pUCW->lpszExtraInfo, pUCW->dwExtraInfoLength, mpExtraInfo);
if (!mpExtraInfo.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pUCW->lpszExtraInfo, mpExtraInfo);
}
REASSIGN_SIZE(mpExtraInfo, UCA.lpszExtraInfo, UCA.dwExtraInfoLength);
fResult = InternetCreateUrlA(&UCA, dwFlags, mpUrlA.psStr, &mpUrlA.dwSize);
if (fResult)
{
MAYBE_COPY_ANSI(mpUrlA, pszUrlW, *pdwUrlLengthW);
}
else
{
*pdwUrlLengthW = mpUrlA.dwSize*sizeof(WCHAR);
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
// implemented in inetapia.cxx
DWORD ICUHrToWin32Error(HRESULT);
INTERNETAPI_(BOOL) InternetCanonicalizeUrlW(
IN LPCWSTR pszUrl,
OUT LPWSTR pszBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN DWORD dwFlags
)
/*++
Routine Description:
Combines a relative URL with a base URL to form a new full URL.
Arguments:
pszUrl - pointer to URL to be canonicalize
pszBuffer - pointer to buffer where new URL is written
lpdwBufferLength - size of buffer on entry, length of new URL on exit
dwFlags - flags controlling operation
Return Value:
BOOL - TRUE if successful, FALSE if not
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetCanonicalizeUrlW",
"%wq, %#x, %#x [%d], %#x",
pszUrl,
pszBuffer,
lpdwBufferLength,
lpdwBufferLength ? *lpdwBufferLength : 0,
dwFlags
));
HRESULT hr ;
BOOL bRet;
// We don't need no stinkin asserts
// INET_ASSERT(pszUrl);
// INET_ASSERT(pszBuffer);
// INET_ASSERT(lpdwBufferLength && (*lpdwBufferLength > 0));
//
// the flags for the Url* APIs in shlwapi should be the same
// except that NO_ENCODE is on by default. so we need to flip it
//
dwFlags ^= ICU_NO_ENCODE;
// Check for invalid parameters
if (!pszUrl || !pszBuffer || !lpdwBufferLength
|| IsBadWritePtr(lpdwBufferLength, sizeof(lpdwBufferLength))
|| *lpdwBufferLength == 0
|| IsBadWritePtr(pszBuffer, *lpdwBufferLength*sizeof(WCHAR))
|| IsBadStringPtrW(pszUrl, INTERNET_MAX_URL_LENGTH))
{
hr = E_INVALIDARG;
}
else
{
hr = UrlCanonicalizeW(pszUrl, pszBuffer,
lpdwBufferLength, dwFlags | URL_WININET_COMPATIBILITY);
}
if(FAILED(hr))
{
DWORD dw = ICUHrToWin32Error(hr);
bRet = FALSE;
DEBUG_ERROR(INET, dw);
SetLastError(dw);
}
else
bRet = TRUE;
DEBUG_LEAVE_API(bRet);
return bRet;
}
INTERNETAPI_(BOOL) InternetCombineUrlW(
IN LPCWSTR pszBaseUrl,
IN LPCWSTR pszRelativeUrl,
OUT LPWSTR pszBuffer,
IN OUT LPDWORD lpdwBufferLength,
IN DWORD dwFlags
)
/*++
Routine Description:
Combines a relative URL with a base URL to form a new full URL.
Arguments:
pszBaseUrl - pointer to base URL
pszRelativeUrl - pointer to relative URL
pszBuffer - pointer to buffer where new URL is written
lpdwBufferLength - size of buffer on entry, length of new URL on exit
dwFlags - flags controlling operation
Return Value:
BOOL - TRUE if successful, FALSE if not
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetCombineUrlW",
"%wq, %wq, %#x, %#x [%d], %#x",
pszBaseUrl,
pszRelativeUrl,
pszBuffer,
lpdwBufferLength,
lpdwBufferLength ? *lpdwBufferLength : 0,
dwFlags
));
HRESULT hr ;
BOOL bRet;
// We don't need no stinkin' asserts
// INET_ASSERT(pszBaseUrl);
// INET_ASSERT(pszRelativeUrl);
// INET_ASSERT(lpdwBufferLength);
//
// the flags for the Url* APIs in shlwapi should be the same
// except that NO_ENCODE is on by default. so we need to flip it
//
dwFlags ^= ICU_NO_ENCODE;
// Check for invalid parameters
if (!pszBaseUrl || !pszRelativeUrl || !lpdwBufferLength
|| IsBadWritePtr(lpdwBufferLength, sizeof(*lpdwBufferLength))
|| (pszBuffer && IsBadWritePtr(pszBuffer, *lpdwBufferLength*sizeof(WCHAR)))
|| IsBadStringPtrW(pszBaseUrl, INTERNET_MAX_URL_LENGTH)
|| IsBadStringPtrW(pszRelativeUrl, INTERNET_MAX_URL_LENGTH))
{
hr = E_INVALIDARG;
}
else
{
hr = UrlCombineW(pszBaseUrl, pszRelativeUrl, pszBuffer,
lpdwBufferLength, dwFlags | URL_WININET_COMPATIBILITY);
}
if(FAILED(hr))
{
DWORD dw = ICUHrToWin32Error(hr);
bRet = FALSE;
DEBUG_ERROR(INET, dw);
SetLastError(dw);
}
else
bRet = TRUE;
DEBUG_LEAVE_API(bRet);
return bRet;
}
INTERNETAPI_(HINTERNET) InternetOpenW(
IN LPCWSTR pszAgentW,
IN DWORD dwAccessType,
IN LPCWSTR pszProxyW OPTIONAL,
IN LPCWSTR pszProxyBypassW OPTIONAL,
IN DWORD dwFlags
)
/*++
Routine Description:
description-of-function.
Arguments:
pszAgent -
dwAccessType -
pszProxy -
pszProxyBypass -
dwFlags -
Return Value:
HINTERNET
--*/
{
DEBUG_ENTER_API((DBG_API,
Handle,
"InternetOpenW",
"%wq, %s (%d), %wq, %wq, %#x",
pszAgentW,
InternetMapOpenType(dwAccessType),
dwAccessType,
pszProxyW,
pszProxyBypassW,
dwFlags
));
DWORD dwErr = ERROR_SUCCESS;
HINTERNET hInternet = NULL;
MEMORYPACKET mpAgentA, mpProxyA, mpProxyBypassA;
ALLOC_MB(pszAgentW,0,mpAgentA);
if (!mpAgentA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszAgentW,mpAgentA);
if (pszProxyW)
{
ALLOC_MB(pszProxyW,0,mpProxyA);
if (!mpProxyA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszProxyW,mpProxyA);
}
if (pszProxyBypassW)
{
ALLOC_MB(pszProxyBypassW,0,mpProxyBypassA);
if (!mpProxyBypassA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszProxyBypassW,mpProxyBypassA);
}
hInternet = InternetOpenA(mpAgentA.psStr, dwAccessType, mpProxyA.psStr,
mpProxyBypassA.psStr, dwFlags);
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
INTERNETAPI_(HINTERNET) InternetConnectW(
IN HINTERNET hInternetSession,
IN LPCWSTR pszServerNameW,
IN INTERNET_PORT nServerPort,
IN LPCWSTR pszUserNameW,
IN LPCWSTR pszPasswordW,
IN DWORD dwService,
IN DWORD dwFlags,
IN DWORD_PTR dwContext
)
/*++
Routine Description:
description-of-function.
Arguments:
hInternetSession -
pszServerName -
nServerPort -
pszUserName -
pszPassword -
dwService -
dwFlags -
dwContext -
Return Value:
HINTERNET
--*/
{
DEBUG_ENTER_API((DBG_API,
Handle,
"InternetConnectW",
"%#x, %wq, %d, %wq, %wq, %s (%d), %#08x, %#x",
hInternetSession,
pszServerNameW,
nServerPort,
pszUserNameW,
pszPasswordW,
InternetMapService(dwService),
dwService,
dwFlags,
dwContext
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpServerNameA, mpUserNameA, mpPasswordA;
HINTERNET hInternet = NULL;
if (!pszServerNameW)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(pszServerNameW, 0, mpServerNameA);
if (!mpServerNameA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszServerNameW, mpServerNameA);
if (pszUserNameW)
{
ALLOC_MB(pszUserNameW, 0, mpUserNameA);
if (!mpUserNameA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszUserNameW, mpUserNameA);
}
if (pszPasswordW)
{
ALLOC_MB(pszPasswordW, 0, mpPasswordA);
if (!mpPasswordA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszPasswordW, mpPasswordA);
}
hInternet = InternetConnectA(hInternetSession, mpServerNameA.psStr, nServerPort,
mpUserNameA.psStr, mpPasswordA.psStr, dwService, dwFlags, dwContext);
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
INTERNETAPI_(HINTERNET) InternetOpenUrlW(
IN HINTERNET hInternetSession,
IN LPCWSTR pszUrlW,
IN LPCWSTR pszHeadersW,
IN DWORD dwHeadersLengthW,
IN DWORD dwFlags,
IN DWORD_PTR dwContext
)
/*++
Routine Description:
description-of-function.
Arguments:
hInternetSession -
pszUrl -
pszHeaders -
dwHeadersLength -
dwFlags -
dwContext -
Return Value:
HINTERNET
--*/
{
DEBUG_ENTER_API((DBG_API,
Handle,
"InternetOpenUrlW",
"%#x, %wq, %.80wq, %d, %#08x, %#x",
hInternetSession,
pszUrlW,
pszHeadersW,
dwHeadersLengthW,
dwFlags,
dwContext
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpHeadersA, mpUrlA;
HINTERNET hInternet = NULL;
if (!pszUrlW || (*pszUrlW==L'\0'))
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
ALLOC_MB(pszUrlW, 0, mpUrlA);
if (!mpUrlA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszUrlW, mpUrlA);
if (pszHeadersW)
{
ALLOC_MB(pszHeadersW, (dwHeadersLengthW==-1L? 0 : dwHeadersLengthW), mpHeadersA);
if (!mpHeadersA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszHeadersW, mpHeadersA);
}
hInternet = InternetOpenUrlA(hInternetSession, mpUrlA.psStr, mpHeadersA.psStr,
mpHeadersA.dwSize, dwFlags, dwContext);
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(hInternet);
return hInternet;
}
INTERNETAPI_(BOOL) InternetReadFileExW(
IN HINTERNET hFile,
OUT LPINTERNET_BUFFERSW lpBuffersOut,
IN DWORD dwFlags,
IN DWORD_PTR dwContext
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
INTERNETAPI_(BOOL) InternetWriteFileExW(
IN HINTERNET hFile,
IN LPINTERNET_BUFFERSW lpBuffersIn,
IN DWORD dwFlags,
IN DWORD_PTR dwContext
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
INTERNETAPI_(BOOL) InternetFindNextFileW(
IN HINTERNET hFind,
OUT LPVOID lpvFindData
)
/*++
Routine Description:
This function retrieves the next block of data from the server.
Currently it supports the following protocol data :
FtpFindNextFile
GopherFindNext
Arguments:
hFind - handle that was obtained by a FindFirst call
lpvFindData - pointer to buffer where the next block of data is copied
Return Value:
TRUE if the function successfully returns next block of data.
FALSE otherwise. GetLastError() will return the error code.
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetFindNextFileW",
"%#x, %#x",
hFind,
lpvFindData
));
DWORD dwErr = ERROR_SUCCESS;
HINTERNET hFindMapped;
HINTERNET_HANDLE_TYPE handleType;
BOOL fResult = FALSE;
dwErr = MapHandleToAddress(hFind, (LPVOID *)&hFindMapped, FALSE);
if (dwErr!=ERROR_SUCCESS)
{
goto cleanup;
}
dwErr = RGetHandleType(hFindMapped, &handleType);
DereferenceObject(hFindMapped);
if (dwErr!=ERROR_SUCCESS)
{
goto cleanup;
}
if ((handleType != TypeFtpFindHandle) && (handleType != TypeGopherFindHandle))
{
dwErr = ERROR_INTERNET_INVALID_OPERATION;
goto cleanup;
}
if (handleType == TypeFtpFindHandle)
{
WIN32_FIND_DATAA fdA;
dwErr = ProbeWriteBuffer(lpvFindData, sizeof(WIN32_FIND_DATAW));
if (dwErr!=ERROR_SUCCESS)
{
goto cleanup;
}
if (InternetFindNextFileA(hFind,(LPVOID)&fdA))
fResult = TransformFtpFindDataToW(&fdA,(LPWIN32_FIND_DATAW)lpvFindData);
}
else
{
GOPHER_FIND_DATAA gfdA;
dwErr = ProbeWriteBuffer(lpvFindData, sizeof(GOPHER_FIND_DATAW));
if (dwErr!=ERROR_SUCCESS)
{
goto cleanup;
}
if (InternetFindNextFileA(hFind,(LPVOID)&gfdA))
fResult = TransformGopherFindDataToW(&gfdA,(LPGOPHER_FIND_DATAW)lpvFindData);
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(BOOL) InternetGetLastResponseInfoW(
OUT LPDWORD lpdwErrorCategory,
IN LPWSTR pszBufferW,
IN OUT LPDWORD lpdwBufferLengthW
)
/*++
Routine Description:
description-of-function.
Arguments:
lpdwErrorCategory -
pszBuffer -
lpdwBufferLength -
Return Value:
BOOL
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetGetLastResponseInfoW",
"%#x, %ws, %#x [%d]",
lpdwErrorCategory,
pszBufferW,
lpdwBufferLengthW,
lpdwBufferLengthW ? *lpdwBufferLengthW : 0
));
DWORD dwErr = ERROR_SUCCESS;
BOOL fResult = FALSE;
MEMORYPACKET mpBufferA;
if (pszBufferW)
{
ALLOC_MB(pszBufferW,*lpdwBufferLengthW,mpBufferA);
if (!mpBufferA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
mpBufferA.dwSize = mpBufferA.dwAlloc;
fResult = InternetGetLastResponseInfoA(lpdwErrorCategory, mpBufferA.psStr,
&mpBufferA.dwSize);
if (fResult) {
MAYBE_COPY_ANSI(mpBufferA, pszBufferW, *lpdwBufferLengthW);
} else {
*lpdwBufferLengthW = mpBufferA.dwSize*sizeof(WCHAR);
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(BOOL) InternetCheckConnectionW(
IN LPCWSTR pszUrlW,
IN DWORD dwFlags,
IN DWORD dwReserved
)
/*++
Routine Description:
This routine tells the caller whether he can establish a connection to the
network.
Arguments:
pszUrl this parameter is an indication to the API to attempt
a specific host. The use of this parameter is based on the
flags set in the dwFlags parameter
dwFlags a bitwise OR of the following flags
INTERNET_FLAG_ICC_FORCE_CONNECTION - force a connection if
cannot find one already established
INTERNET_FLAG_ICC_CONNECT_SPECIFIC_HOST - try the connection
to the specific host. If this flag is not set then the
host name is used if a quicker method is not avilable.
dwReserved reserved
Return Value:
TRUE - Success
FALSE - failure, GetLastError returns the error code
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetCheckConnectionW",
"%ws %x",
pszUrlW,
dwFlags
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrlA;
BOOL fResult = FALSE;
if (pszUrlW)
{
ALLOC_MB(pszUrlW,0,mpUrlA);
if (!mpUrlA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszUrlW,mpUrlA);
}
fResult = InternetCheckConnectionA(mpUrlA.psStr, dwFlags, dwReserved);
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(INTERNET_STATUS_CALLBACK) InternetSetStatusCallbackCore(
IN HINTERNET hInternet,
IN INTERNET_STATUS_CALLBACK lpfnInternetCallback,
IN BOOL fType
);
INTERNETAPI_(INTERNET_STATUS_CALLBACK) InternetSetStatusCallbackW(
IN HINTERNET hInternet,
IN INTERNET_STATUS_CALLBACK lpfnInternetCallback
)
/*++
Routine Description:
Sets the status callback function for the DLL or the handle object
Arguments:
hInternet - handle of the object for which we wish to set the
status callback
lpfnInternetCallback - pointer to caller-supplied status function
Return Value:
FARPROC
Success - previous status callback function address
Failure - INTERNET_INVALID_STATUS_CALLBACK. Call GetLastErrorInfo() for
more information:
ERROR_INVALID_PARAMETER
The callback function is invalid
ERROR_INTERNET_INCORRECT_HANDLE_TYPE
Cannot set the callback on the supplied handle (probably
a NULL handle - per-process callbacks no longer
supported)
--*/
{
DEBUG_ENTER((DBG_INET,
Pointer,
"InternetSetStatusCallbackW",
"%#x, %#x",
hInternet,
lpfnInternetCallback
));
INTERNET_STATUS_CALLBACK pfn = InternetSetStatusCallbackCore(hInternet,lpfnInternetCallback,TRUE);
DEBUG_LEAVE(pfn);
return pfn;
}
#ifdef IGCURLW
INTERNETAPI_(BOOL) InternetGetCertByURLW(
IN LPWSTR lpszURL,
IN OUT LPWSTR lpszCertText,
OUT DWORD dwcbCertText
)
{
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
return InternetGetCertByURLA(lpszURL,lpszCertText,dwcbCertText);
}
#endif
INTERNETAPI_(BOOL) InternetShowSecurityInfoByURLW(
IN LPWSTR pszUrlW,
IN HWND hwndRootWindow
)
/*++
Routine Description:
Does a high-level lookup against the Certificate Cache.
Searches by URL (broken down into hostname) for the Certificate,
and returns it in a formatted (&localized) string.
Arguments:
lpszUrl - pointer to URL to crack
lpszCertText - Output of formatted certifcate
dwcbCertText - Size of lpszCertText
Return Value:
BOOL
Success - TRUE
Failure - FALSE. Call GetLastError() for more info
--*/
{
DEBUG_ENTER_API((DBG_INET,
Bool,
"InternetShowSecurityInfoW",
"%wq, %#x",
pszUrlW,
hwndRootWindow
));
BOOL fResult = FALSE;
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpUrlA;
if (pszUrlW)
{
ALLOC_MB(pszUrlW,0,mpUrlA);
if (!mpUrlA.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
UNICODE_TO_ANSI(pszUrlW,mpUrlA);
}
fResult = InternetShowSecurityInfoByURLA(mpUrlA.psStr, hwndRootWindow);
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(BOOL) InternetAlgIdToStringW(
IN ALG_ID ai,
IN LPWSTR lpstr,
IN OUT LPDWORD lpdwstrLength,
IN DWORD dwReserved /* Must be 0 */
)
/*++
Routine Description:
Converts a algid to a user-displayable string.
Arguments:
ai - Algorithm identifiers ( defined in wincrypt.h)
lpstr - Buffer to copy string into.
lpdwstrLength - pass in num of characters, return no of characters copied if successful,
else no of chars required (including null terminator)
dwReserved = Must be 0
Return Value:
DWORD
Win32 or WININET error code.
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetAlgIdToStringW",
"%#x, %wq, %#x, %#x",
ai,
lpstr,
lpdwstrLength,
dwReserved
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpBuffer;
BOOL fResult = FALSE;
if (dwReserved!=0)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (lpstr)
{
mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwstrLength;
mpBuffer.psStr = (LPSTR)ALLOC_BYTES(mpBuffer.dwAlloc*sizeof(CHAR));
if (!mpBuffer.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
if (InternetAlgIdToStringA(ai, (LPSTR)mpBuffer.psStr, &mpBuffer.dwSize, dwReserved))
{
*lpdwstrLength = MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
NULL, 0);
if (*lpdwstrLength*sizeof(WCHAR) <= mpBuffer.dwAlloc && lpstr)
{
MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
lpstr, *lpdwstrLength);
(*lpdwstrLength)--;
fResult = TRUE;
}
else
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
}
}
else
{
dwErr = GetLastError();
if (dwErr == ERROR_INSUFFICIENT_BUFFER)
{
*lpdwstrLength = mpBuffer.dwSize * sizeof(WCHAR);
}
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}
INTERNETAPI_(BOOL) InternetSecurityProtocolToStringW(
IN DWORD dwProtocol,
IN LPWSTR lpstr,
IN OUT LPDWORD lpdwstrLength,
IN DWORD dwReserved /* Must be 0 */
)
/*++
Routine Description:
Converts a security protocol to a user-displayable string.
Arguments:
dwProtocol - Security protocol identifier ( defined in wincrypt.h)
lpstr - Buffer to copy string into.
lpdwstrLength - pass in num of characters, return no of characters copied if successful,
else no of chars required (including null terminator)
dwReserved = Must be 0
Return Value:
DWORD
Win32 or WININET error code.
--*/
{
DEBUG_ENTER_API((DBG_API,
Bool,
"InternetSecurityProtocolToStringW",
"%d, %wq, %#x, %#x",
dwProtocol,
lpstr,
lpdwstrLength,
dwReserved
));
DWORD dwErr = ERROR_SUCCESS;
MEMORYPACKET mpBuffer;
BOOL fResult = FALSE;
if (dwReserved!=0)
{
dwErr = ERROR_INVALID_PARAMETER;
goto cleanup;
}
if (lpstr)
{
mpBuffer.dwAlloc = mpBuffer.dwSize = *lpdwstrLength;
mpBuffer.psStr = (LPSTR)ALLOC_BYTES(mpBuffer.dwAlloc*sizeof(CHAR));
if (!mpBuffer.psStr)
{
dwErr = ERROR_NOT_ENOUGH_MEMORY;
goto cleanup;
}
}
if (InternetSecurityProtocolToStringA(dwProtocol, (LPSTR)mpBuffer.psStr, &mpBuffer.dwSize, dwReserved))
{
*lpdwstrLength = MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
NULL, 0);
if (*lpdwstrLength*sizeof(WCHAR) <= mpBuffer.dwAlloc && lpstr)
{
MultiByteToWideChar(CP_ACP, 0, mpBuffer.psStr, mpBuffer.dwSize + 1,
lpstr, *lpdwstrLength);
(*lpdwstrLength)--;
fResult = TRUE;
}
else
{
dwErr = ERROR_INSUFFICIENT_BUFFER;
}
}
else
{
dwErr = GetLastError();
if (dwErr == ERROR_INSUFFICIENT_BUFFER)
{
*lpdwstrLength = mpBuffer.dwSize * sizeof(WCHAR);
}
}
cleanup:
if (dwErr!=ERROR_SUCCESS) {
SetLastError(dwErr);
DEBUG_ERROR(API, dwErr);
}
DEBUG_LEAVE_API(fResult);
return fResult;
}