You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1443 lines
36 KiB
1443 lines
36 KiB
/*++
|
|
|
|
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;
|
|
}
|