382 lines
9.5 KiB
C++
382 lines
9.5 KiB
C++
/*++
|
||
|
||
Copyright (c) 1996 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
inetapiu.cxx
|
||
|
||
Abstract:
|
||
|
||
Contains WinInet API utility & sub-API functions
|
||
|
||
Contents:
|
||
wInternetQueryDataAvailable
|
||
|
||
Author:
|
||
|
||
Richard L Firth (rfirth) 16-Feb-1996
|
||
|
||
Environment:
|
||
|
||
Win32 user-level
|
||
|
||
Revision History:
|
||
|
||
16-Feb-1996 rfirth
|
||
Created
|
||
|
||
--*/
|
||
|
||
#include <wininetp.h>
|
||
#include "inetapiu.h"
|
||
|
||
DWORD
|
||
InbLocalEndCacheWrite(
|
||
IN HINTERNET hFtpFile,
|
||
IN LPSTR lpszFileExtension,
|
||
IN BOOL fNormal
|
||
);
|
||
|
||
DWORD
|
||
InbGopherLocalEndCacheWrite(
|
||
IN HINTERNET hGopherFile,
|
||
IN LPSTR lpszFileExtension,
|
||
IN BOOL fNormal
|
||
);
|
||
|
||
//
|
||
// functions
|
||
//
|
||
|
||
|
||
BOOL
|
||
wInternetQueryDataAvailable(
|
||
IN LPVOID hFileMapped,
|
||
OUT LPDWORD lpdwNumberOfBytesAvailable,
|
||
IN DWORD dwFlags,
|
||
IN DWORD_PTR dwContext
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Part 2 of InternetQueryDataAvailabe. This function is called by the async
|
||
worker thread in order to resume InternetQueryDataAvailable(), and by the
|
||
app as the worker part of the API, post validation
|
||
|
||
We can query available data for handle types that return data, either from
|
||
a socket, or from a cache file:
|
||
|
||
- HTTP request
|
||
- FTP file
|
||
- FTP find
|
||
- FTP find HTML
|
||
- gopher file
|
||
- gopher find
|
||
- gopher find HTML
|
||
|
||
Arguments:
|
||
|
||
hFileMapped - the mapped HINTERNET
|
||
|
||
lpdwNumberOfBytesAvailable - where the number of bytes is returned
|
||
|
||
dwFlags - flags controlling operation
|
||
|
||
dwContext - context value for callbacks
|
||
|
||
Return Value:
|
||
|
||
DWORD
|
||
Success - ERROR_SUCCESS
|
||
|
||
Failure -
|
||
|
||
--*/
|
||
|
||
{
|
||
DEBUG_ENTER((DBG_INET,
|
||
Bool,
|
||
"wInternetQueryDataAvailable",
|
||
"%#x, %#x, %#x, %#x",
|
||
hFileMapped,
|
||
lpdwNumberOfBytesAvailable,
|
||
dwFlags,
|
||
dwContext
|
||
));
|
||
|
||
LPINTERNET_THREAD_INFO lpThreadInfo = InternetGetThreadInfo();
|
||
DWORD error;
|
||
HINTERNET_HANDLE_TYPE handleType;
|
||
|
||
INET_ASSERT(hFileMapped);
|
||
|
||
//
|
||
// as usual, grab the per-thread info block
|
||
//
|
||
|
||
if (lpThreadInfo == NULL) {
|
||
|
||
INET_ASSERT(FALSE);
|
||
|
||
error = ERROR_INTERNET_INTERNAL_ERROR;
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// if this is the async worker thread then set the context, handle, and
|
||
// last-error info in the per-thread data block before we go any further
|
||
// (we already did this on the sync path)
|
||
//
|
||
|
||
if (lpThreadInfo->IsAsyncWorkerThread) {
|
||
_InternetSetContext(lpThreadInfo,
|
||
((INTERNET_HANDLE_OBJECT *)hFileMapped)->GetContext()
|
||
);
|
||
_InternetSetObjectHandle(lpThreadInfo,
|
||
((HANDLE_OBJECT *)hFileMapped)->GetPseudoHandle(),
|
||
hFileMapped
|
||
);
|
||
_InternetClearLastError(lpThreadInfo);
|
||
|
||
//
|
||
// we should only be here in async mode if there was no data immediately
|
||
// available
|
||
//
|
||
|
||
INET_ASSERT(!((INTERNET_HANDLE_OBJECT *)hFileMapped)->IsDataAvailable());
|
||
|
||
}
|
||
|
||
//
|
||
// get the local handle for FTP & gopher
|
||
//
|
||
|
||
HINTERNET hLocal;
|
||
|
||
error = RGetLocalHandle(hFileMapped, &hLocal);
|
||
if (error != ERROR_SUCCESS) {
|
||
goto quit;
|
||
}
|
||
|
||
//
|
||
// we copy the number of bytes available to a local variable first, and
|
||
// only update the caller's variable if we succeed
|
||
//
|
||
|
||
DWORD bytesAvailable;
|
||
|
||
//
|
||
// get the current data available, based on the handle type
|
||
//
|
||
|
||
switch (handleType = ((HANDLE_OBJECT *)hFileMapped)->GetHandleType()) {
|
||
case TypeHttpRequestHandle:
|
||
error = ((HTTP_REQUEST_HANDLE_OBJECT *)hFileMapped)
|
||
->QueryDataAvailable(&bytesAvailable);
|
||
break;
|
||
|
||
case TypeFtpFileHandle:
|
||
case TypeFtpFindHandle:
|
||
error = wFtpQueryDataAvailable(hLocal, &bytesAvailable);
|
||
break;
|
||
|
||
case TypeGopherFileHandle:
|
||
case TypeGopherFindHandle:
|
||
error = wGopherQueryDataAvailable(hLocal, &bytesAvailable);
|
||
break;
|
||
|
||
case TypeFtpFindHandleHtml:
|
||
case TypeGopherFindHandleHtml:
|
||
error = QueryHtmlDataAvailable(hFileMapped, &bytesAvailable);
|
||
if (((INTERNET_CONNECT_HANDLE_OBJECT *)hFileMapped)->
|
||
IsCacheWriteInProgress()) {
|
||
DWORD errorCache = error;
|
||
|
||
if ((errorCache == ERROR_SUCCESS) && (bytesAvailable == 0)) {
|
||
errorCache = ERROR_NO_MORE_FILES;
|
||
}
|
||
if (errorCache != ERROR_SUCCESS) {
|
||
if (handleType == TypeFtpFindHandleHtml) {
|
||
InbLocalEndCacheWrite( hFileMapped,
|
||
"htm",
|
||
(errorCache == ERROR_NO_MORE_FILES)
|
||
);
|
||
}
|
||
else {
|
||
InbGopherLocalEndCacheWrite( hFileMapped,
|
||
"htm",
|
||
(errorCache == ERROR_NO_MORE_FILES)
|
||
);
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
|
||
#ifdef EXTENDED_ERROR_HTML
|
||
|
||
case TypeFtpFileHandleHtml:
|
||
error = QueryHtmlDataAvailable(hFileMapped, &bytesAvailable);
|
||
break;
|
||
|
||
#endif
|
||
|
||
default:
|
||
error = ERROR_INTERNET_INCORRECT_HANDLE_TYPE;
|
||
break;
|
||
}
|
||
|
||
quit:
|
||
|
||
BOOL success;
|
||
|
||
if (error == ERROR_SUCCESS) {
|
||
((INTERNET_HANDLE_OBJECT *)hFileMapped)->SetAvailableDataLength(bytesAvailable);
|
||
*lpdwNumberOfBytesAvailable = bytesAvailable;
|
||
success = TRUE;
|
||
|
||
DEBUG_PRINT(INET,
|
||
INFO,
|
||
("%d bytes available\n",
|
||
bytesAvailable
|
||
));
|
||
|
||
DEBUG_PRINT_API(API,
|
||
INFO,
|
||
("*lpdwNumberOfBytesAvailable (%#x) = %d\n",
|
||
lpdwNumberOfBytesAvailable,
|
||
bytesAvailable
|
||
));
|
||
|
||
} else {
|
||
success = FALSE;
|
||
|
||
DEBUG_ERROR(INET, error);
|
||
|
||
}
|
||
|
||
SetLastError(error);
|
||
|
||
DEBUG_LEAVE(success);
|
||
|
||
return success;
|
||
}
|
||
|
||
|
||
STDAPI_(BOOL) ForceNexusLookupExW(
|
||
IN BOOL fForce,
|
||
IN PWSTR pwszRegUrl, // user supplied buffer ...
|
||
IN OUT PDWORD pdwRegUrlLen, // ... and length (will be updated to actual length
|
||
// on successful return)
|
||
IN PWSTR pwszDARealm, // user supplied buffer ...
|
||
IN OUT PDWORD pdwDARealmLen // ... and length (will be updated to actual length
|
||
// on successful return)
|
||
)
|
||
{
|
||
PP_CONTEXT hPP = 0;
|
||
|
||
hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
|
||
|
||
BOOL RetVal = ::PP_ForceNexusLookup (hPP,
|
||
fForce,
|
||
pwszRegUrl,
|
||
pdwRegUrlLen,
|
||
pwszDARealm,
|
||
pdwDARealmLen );
|
||
|
||
::PP_FreeContext ( hPP );
|
||
|
||
return RetVal;
|
||
|
||
}
|
||
|
||
STDAPI_(VOID) ForceNexusLookup(void)
|
||
{
|
||
PP_CONTEXT hPP = 0;
|
||
|
||
hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
|
||
|
||
::PP_ForceNexusLookup (hPP,
|
||
FALSE, // don't force connection establishment if nexus not reachable
|
||
NULL,
|
||
0,
|
||
NULL,
|
||
0 );
|
||
|
||
::PP_FreeContext ( hPP );
|
||
}
|
||
|
||
|
||
BOOL
|
||
GetMD5Result(PSTR pszChallengeInfo, PSTR pszPassword, PBYTE pbHexHash);
|
||
|
||
|
||
///////////////
|
||
// This routine gets the default passport password and does an MD5 hash of it with
|
||
// the supplied ChallengeInfo and returns the result in hex string format.
|
||
//
|
||
// pwszRealm = realm to get the password for. If NULL, uses default. Ignored if pwszTarget is not null.
|
||
//
|
||
// pwszTarget = target to get the password for. If NULL, uses realm
|
||
//
|
||
// pbHexHash = output buffer to receive the MD5 result in hex string format,
|
||
// MUST BE AT LEAST MD5DIGESTLEN * 2 + 1 IN SIZE
|
||
//
|
||
// Returns TRUE if success, FALSE if failure.
|
||
//
|
||
//
|
||
|
||
STDAPI_(BOOL) CreateMD5SSOHash (
|
||
IN PWSTR pszChallengeInfo,
|
||
IN PWSTR pwszRealm,
|
||
IN PWSTR pwszTarget,
|
||
OUT PBYTE pbHexHash
|
||
)
|
||
{
|
||
PP_CONTEXT hPP = 0;
|
||
BOOL bRetVal = FALSE;
|
||
|
||
hPP = ::PP_InitContext(L"WinInet.Dll", NULL);
|
||
|
||
if ( hPP )
|
||
{
|
||
WCHAR pszPassword[INTERNET_MAX_PASSWORD_LENGTH];
|
||
|
||
// Check for cached creds in the session
|
||
if (::PP_GetCachedCredential ( hPP, pwszRealm, pwszTarget, NULL, pszPassword) )
|
||
{
|
||
DWORD dwChallengeInfoLen = wcslen(pszChallengeInfo) + 1;
|
||
PSTR pszChallengeInfoA = (PSTR) LocalAlloc (LPTR, dwChallengeInfoLen );
|
||
|
||
DWORD dwPasswordLen = wcslen(pszPassword) + 1;
|
||
PSTR pszPasswordA = (PSTR) LocalAlloc (LPTR, dwPasswordLen );
|
||
|
||
if ( pszChallengeInfoA != NULL && pszPasswordA != NULL )
|
||
{
|
||
// convert to asci
|
||
::WideCharToMultiByte(CP_ACP, 0, pszChallengeInfo, -1, pszChallengeInfoA, dwChallengeInfoLen, NULL, NULL);
|
||
::WideCharToMultiByte(CP_ACP, 0, pszPassword, -1, pszPasswordA, dwPasswordLen, NULL, NULL);
|
||
|
||
bRetVal = GetMD5Result ( pszChallengeInfoA, pszPasswordA, pbHexHash );
|
||
|
||
ZeroMemory ( pszPassword, INTERNET_MAX_PASSWORD_LENGTH * sizeof(WCHAR) );
|
||
ZeroMemory ( pszPasswordA, dwPasswordLen );
|
||
|
||
}
|
||
|
||
if ( pszChallengeInfoA )
|
||
LocalFree ( pszChallengeInfoA );
|
||
if ( pszPasswordA )
|
||
LocalFree ( pszPasswordA );
|
||
}
|
||
|
||
::PP_FreeContext ( hPP );
|
||
}
|
||
|
||
return bRetVal;
|
||
|
||
}
|
||
|