Leaked source code of windows server 2003
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.
 
 
 
 
 
 

3320 lines
94 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1995.
//
// File: transapi.cxx
//
// Contents: API's for internal use
//
// Classes:
//
// Functions:
//
// History: 4-26-96 JohannP (Johann Posch) Created
//
//----------------------------------------------------------------------------
#include <trans.h>
#include "oinet.hxx"
#include <shlwapi.h>
#include <shlwapip.h>
#include <winineti.h>
#include "datasnif.hxx"
#include <winver.h>
#include <mshtml.h>
PerfDbgTag(tagTransApi, "Urlmon", "Log Trans API", DEB_DATA);
static char szMimeKey[] = "MIME\\Database\\Content Type\\";
const ULONG ulMimeKeyLen = ((sizeof(szMimeKey)/sizeof(char))-1);
LPCSTR pszDocObject = "DocObject";
LPCSTR pszInprocServer = "InprocServer32";
LPCSTR pszLocalServer = "LocalServer32";
#define INTERNET_SETTING_KEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
extern LPSTR g_pszUserAgentString;
extern BYTE g_bShortcircuitKnownProtocols;
HMODULE g_hLibPluginOcx = NULL;
HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid);
// borrow from urlmon\download to check if Doc Object handler is installed
// need CLocalComponentInfo & IsControlLocallyInstalled
#ifndef unix
#include "..\download\cdl.h"
#else
#include "../download/cdl.h"
#endif /* unix */
// DocFile properties and constants for extracting CodeBase property
#define DOCFILE_NUMPROPERTIES 3
#define DOCFILE_PROPID_CODEBASE 3
#define DOCFILE_PROPID_MAJORVERSION 4
#define DOCFILE_PROPID_MINORVERSION 5
//
// this new apis should be made public
//
STDAPI URLDownloadW(IUnknown *pUnk, LPCWSTR pwzURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved);
STDAPI URLDownloadA(IUnknown *pUnk, LPCSTR pszURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved);
#define CF_INGNORE_SLASH 0x00000001 //ignore slash when comparing urls
typedef enum tagCLSCTXEX
{
/*
// ole default class context values
CLSCTX_INPROC_SERVER = 0x0001,
CLSCTX_INPROC_HANDLER = 0x0002,
CLSCTX_LOCAL_SERVER = 0x0004,
CLSCTX_INPROC_SERVER16 = 0x0008,
CLSCTX_REMOTE_SERVER = 0x0010,
CLSCTX_INPROC_HANDLER16 = 0x0020,
CLSCTX_INPROC_SERVERX86 = 0x0040,
CLSCTX_INPROC_HANDLERX86 = 0x0080
*/
// new class context values used in GetClassFileOrMime
CLSCTX_INPROC_DOCOBJECT = 0x0100,
CLSCTX_LOCAL_DOCOBJECT = 0x0200,
CLSCTX_INPROC_CONTROL = 0x0400,
CLSCTX_INPROC_X_CONTROL = 0x0800,
CLSCTX_INPROC_PLUGIN = 0x1000
} CLSCTXEX;
#define CLSCTX_DOCOBJECT (CLSCTX_INPROC_DOCOBJECT|CLSCTX_LOCAL_DOCOBJECT)
const GUID CLSID_PluginHost =
{
0x25336921, 0x03F9, 0x11cf, {0x8F, 0xD0, 0x00, 0xAA, 0x00, 0x68, 0x6F, 0x13}
};
const GUID CLSID_MsHtml =
{
0x25336920, 0x03F9, 0x11cf, {0x8F, 0xD0, 0x00, 0xAA, 0x00, 0x68, 0x6F, 0x13}
};
const GUID FMTID_CodeBase =
{
0xfe2d9191, 0x7fba, 0x11d0, {0xb3, 0xc2, 0x00, 0xa0, 0xc9, 0x0a, 0xea, 0x82}
};
//+---------------------------------------------------------------------------
//
// Function: GetClsIDInfo
//
// Synopsis:
//
// Arguments: [pclsid] -- class id
// [ClsCtxIn] -- unused
// [pClsCtx] -- class context of class passed in
//
// Returns: S_OK on success
// E_OUTOFMEMORY
// E_FAIL
//
// History: 7-20-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetClsIDInfo(CLSID *pclsid, DWORD ClsCtxIn, DWORD *pClsCtx)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetClsIDInfo",
"%#x, %#x, %#x",
pclsid, ClsCtxIn, pClsCtx
));
PerfDbgLog(tagTransApi, NULL, "+GetClsIDInfo");
HRESULT hr = E_FAIL;
TransAssert(( pClsCtx && pclsid && !IsEqualGUID(*pclsid, CLSID_NULL) ));
LPSTR pszCls = StringAFromCLSID(pclsid);
if (!pszCls)
{
hr = E_OUTOFMEMORY;
*pClsCtx = 0;
}
else
{
CHAR szCLSID[CLSIDSTR_MAX + 8];
HKEY hClsRegEntry;
CHAR szValue[64];
long lSize;
DWORD dwClsCtx = 0;
strcpy(szCLSID, "CLSID\\");
strcat(szCLSID, pszCls);
if (RegOpenKey(HKEY_CLASSES_ROOT, szCLSID, &hClsRegEntry) == ERROR_SUCCESS)
{
lSize = 64;
HKEY hkeySrv32;
if( RegOpenKey(hClsRegEntry, pszInprocServer, &hkeySrv32)
== ERROR_SUCCESS)
{
dwClsCtx |= CLSCTX_INPROC;
RegCloseKey(hkeySrv32);
}
lSize = 64;
if (RegQueryValue(hClsRegEntry, pszLocalServer, szValue, &lSize) == ERROR_SUCCESS)
{
dwClsCtx |= CLSCTX_LOCAL_SERVER;
}
lSize = 64;
if (RegQueryValue(hClsRegEntry, pszDocObject, szValue, &lSize) == ERROR_SUCCESS)
{
dwClsCtx |= CLSCTX_INPROC_DOCOBJECT;
}
RegCloseKey(hClsRegEntry);
}
if (dwClsCtx)
{
hr = S_OK;
*pClsCtx = dwClsCtx;
}
delete pszCls;
}
PerfDbgLog1(tagTransApi, NULL, "-GetClsIDInfo (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: FindFileExtension
//
// Synopsis:
//
// Arguments: [pszFileName] --
//
// Returns:
//
// History: 2-09-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
LPSTR FindFileExtension(LPSTR pszFileName)
{
DEBUG_ENTER((DBG_TRANSDAT,
String,
"FindFileExtension",
"%.80q",
pszFileName
));
PerfDbgLog1(tagTransApi, NULL, "+FindFileExtension (szFileName:%s)", pszFileName);
LPSTR pStr = NULL;
if (pszFileName)
{
LPSTR lpF = pszFileName + strlen(pszFileName);
if (lpF)
{
while (lpF >= pszFileName)
{
if (*lpF=='.')
{
pStr = lpF;
break;
}
if (*lpF=='/')
{
break;
}
lpF--;
}
}
}
PerfDbgLog1(tagTransApi, NULL, "-FindFileExtension (pStr:%s)", pStr);
DEBUG_LEAVE(pStr);
return pStr;
}
//+---------------------------------------------------------------------------
//
// Function: IsDocFile
//
// Synopsis:
//
// Arguments: [pBuffer] --
//
// Returns: S_OK buffer is begin of docfile
// S_FALSE not begin of docfile
// E_INVALIDARG arguments incorrect
//
// History: 2-09-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT IsDocFile(LPVOID pBuffer, DWORD cbSize)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"IsDocFile",
"%#x, %#x",
pBuffer, cbSize
));
PerfDbgLog(tagTransApi, NULL, "+IsDocFile");
HRESULT hr;
// The byte combination that identifies that a file is a storage of
// some kind
BYTE SIGSTG[] = {0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1};
BYTE CBSIGSTG = sizeof(SIGSTG);
TransAssert(((pBuffer != NULL) && (cbSize != 0) ));
if (!pBuffer || (cbSize == 0))
{
hr = E_INVALIDARG;
}
else
{
hr = (!memcmp(pBuffer, SIGSTG, CBSIGSTG)) ? S_OK : S_FALSE;
}
PerfDbgLog1(tagTransApi, NULL, "-IsDocFile (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetMimeFromExt
//
// Synopsis:
//
// Arguments: [pszExt] --
// [pszMime] --
// [cbMime] --
//
// Returns:
//
// History: 4-23-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetMimeFromExt(LPSTR pszExt, LPSTR pszMime, DWORD *pcbMime)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetMimeFromExt",
"%.80q, %.80q, %#x",
pszExt, pszMime, pcbMime
));
PerfDbgLog1(tagTransApi, NULL, "+GetMimeFromExt (szExt:%s)", pszExt);
HRESULT hr = E_FAIL;
*pszMime = '\0';
TransAssert((pszExt[0] == '.'));
// the entry begins with '.' so it may be a file extension
// query the value (which is the ProgID)
HKEY hMimeKey = NULL;
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, pszExt, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
{
DWORD dwType = 1;
if (RegQueryValueEx(hMimeKey, szContent, NULL, &dwType, (LPBYTE)pszMime, pcbMime) == ERROR_SUCCESS)
{
hr = NOERROR;
}
RegCloseKey(hMimeKey);
}
PerfDbgLog2(tagTransApi, NULL, "-GetMimeFromExt (pszMime:%s, hr:%lx)", pszMime, hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetMimeFileExtension
//
// Synopsis:
//
// Arguments: [pszMime] --
// [pclsid] --
//
// Returns:
//
// History: 2-22-96 JohannP (Johann Posch) Created
//
// Notes: BUGBUG: needs to be optimized!
//
//----------------------------------------------------------------------------
HRESULT GetMimeFileExtension(LPSTR pszMime, LPSTR pszExt, DWORD cbSize)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetMimeFileExtension",
"%.80q, %.80q, %#x",
pszMime, pszExt, cbSize
));
PerfDbgLog1(tagTransApi, NULL, "+GetMimeFileExtension (MimeStr:%s)", pszMime);
HRESULT hr = REGDB_E_CLASSNOTREG;
HKEY hMimeKey = NULL;
DWORD dwError;
DWORD dwType;
char szValue[256];
DWORD dwValueLen = 256;
char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
if ((pszMime == 0) || (pszExt == 0))
{
hr = E_INVALIDARG;
}
else
{
*pszExt = 0;
strcpy(szKey, szMimeKey);
strncat(szKey,pszMime, SZMIMESIZE_MAX);
switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
{
case ERROR_SUCCESS:
hr = NOERROR;
break;
// win32 will return file not found instead of bad key
case ERROR_FILE_NOT_FOUND:
case ERROR_BADKEY:
hr = REGDB_E_CLASSNOTREG;
break;
default:
hr = REGDB_E_READREGDB;
break;
}
if (hr == NOERROR)
{
dwValueLen = 256;
dwError = RegQueryValueEx(hMimeKey
, szExtension
, NULL
, &dwType
, (LPBYTE)szValue
, &dwValueLen);
if ( (dwError == ERROR_SUCCESS)
&& pszExt
&& dwValueLen
&& (dwValueLen <= cbSize) )
{
StrNCpy(pszExt, szValue, dwValueLen);
}
}
}
if (hMimeKey)
{
RegCloseKey(hMimeKey);
}
PerfDbgLog2(tagTransApi, NULL, "-GetMimeFileExtension (hr:%lx, szExt:%s)", hr, pszExt);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetClassMime
//
// Synopsis:
//
// Arguments: [pszMime] --
// [pclsid] --
// [fIgnoreMimeClsid] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetClassMime(LPSTR pszMime, CLSID *pclsid, BOOL fIgnoreMimeClsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetClassMime",
"%.80q, %#x, %B",
pszMime, pclsid, fIgnoreMimeClsid
));
PerfDbgLog1(tagTransApi, NULL, "+GetClassMime (MimeStr:%s)", pszMime);
HRESULT hr = REGDB_E_CLASSNOTREG;
DWORD dwFlags = (fIgnoreMimeClsid) ? MIMEFLAGS_IGNOREMIME_CLASSID: 0;
HKEY hMimeKey = NULL;
DWORD dwClsCtx;
DWORD dwError;
DWORD dwType;
char szValue[256];
DWORD dwValueLen = 256;
char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
if ((pszMime == 0) || (*pszMime == 0))
{
hr = E_INVALIDARG;
}
else
{
strcpy(szKey, szMimeKey);
strcat(szKey, pszMime);
switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
{
case ERROR_SUCCESS:
hr = NOERROR;
break;
// win32 will return file not found instead of bad key
case ERROR_FILE_NOT_FOUND:
case ERROR_BADKEY:
hr = REGDB_E_CLASSNOTREG;
break;
default:
hr = REGDB_E_READREGDB;
break;
}
if (hr == NOERROR)
{
// if fIgnoreMimeClsid is set, ignore the CLSID entry
// in the HKCR\MIME tree.
if (!fIgnoreMimeClsid)
{
dwError = RegQueryValueEx(hMimeKey, szClassID, NULL
, &dwType, (LPBYTE)szValue, &dwValueLen);
hr = REGDB_E_CLASSNOTREG;
if (dwError == ERROR_SUCCESS)
{
WCHAR sz[256];
A2W(szValue,sz,256);
hr = CLSIDFromString(sz, pclsid);
}
if (hr == NOERROR)
{
goto End;
}
}
hr = REGDB_E_CLASSNOTREG;
dwValueLen = 256;
dwError = RegQueryValueEx(hMimeKey
, szExtension
, NULL
, &dwType
, (LPBYTE)szValue
, &dwValueLen);
if (dwError == ERROR_SUCCESS)
{
hr = GetClassFromExt(szValue,pclsid);
//class still not known
// try extension
}
}
}
End:
if (hMimeKey)
{
RegCloseKey(hMimeKey);
}
PerfDbgLog1(tagTransApi, NULL, "-GetClassMime (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetMimeFlags
//
// Synopsis:
//
// Arguments: [pszMime] --
// [pdwFlags] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetMimeFlags(LPCWSTR pwzMime, DWORD *pdwFlags)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetMimeFlags",
"%.80wq, %#x",
pwzMime, pdwFlags
));
TransDebugOut((DEB_DATA, "API _IN GetMimeFlags (MimeStr:%ws)\n", pwzMime));
HRESULT hr = E_FAIL;
HKEY hMimeKey = NULL;
DWORD dwError;
DWORD dwType;
DWORD dwFlags = 0;
char szValue[256];
DWORD dwValueLen = 256;
char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
if ((pwzMime == 0) || (*pwzMime == 0) || !pdwFlags)
{
hr = E_INVALIDARG;
}
else
{
strcpy(szKey, szMimeKey);
W2A(pwzMime, szKey + ulMimeKeyLen, SZMIMESIZE_MAX);
*pdwFlags = 0;
switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
{
case ERROR_SUCCESS:
hr = NOERROR;
break;
// win32 will return file not found instead of bad key
case ERROR_FILE_NOT_FOUND:
case ERROR_BADKEY:
hr = REGDB_E_CLASSNOTREG;
break;
default:
hr = REGDB_E_READREGDB;
break;
}
if (hr == NOERROR)
{
dwValueLen = sizeof(DWORD);
dwError = RegQueryValueEx(hMimeKey, szFlags, NULL
, &dwType, (LPBYTE)&dwFlags, &dwValueLen);
hr = E_FAIL;
if (dwError == ERROR_SUCCESS)
{
*pdwFlags = dwFlags;
hr = NOERROR;
}
}
}
if (hMimeKey)
{
RegCloseKey(hMimeKey);
}
TransDebugOut((DEB_DATA, "API OUT GetMimeFlags (DWFLAGS:%lx, hr:%lx)\n", dwFlags, hr));
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetMimeInfo
//
// Synopsis:
//
// Arguments: [pszMime] --
// [pclsid] --
// [pdwFlags] --
// [pdwMimeFlags] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetMimeInfo(LPSTR pszMime, CLSID *pclsid, DWORD dwFlags, DWORD *pdwMimeFlags)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetMimeInfo",
"%.80q, %#x, %#x, %#x",
pszMime, pclsid, dwFlags, pdwMimeFlags
));
PerfDbgLog1(tagTransApi, NULL, "+GetMimeInfo (MimeStr:%s)", pszMime);
HRESULT hr = REGDB_E_CLASSNOTREG;
BOOL fIgnoreMimeClsid = (dwFlags & MIMEFLAGS_IGNOREMIME_CLASSID);
HKEY hMimeKey = NULL;
DWORD dwError;
DWORD dwType;
char szValue[256];
DWORD dwValueLen = 256;
char szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
if ((pszMime == 0) || (*pszMime == 0))
{
hr = E_INVALIDARG;
}
else
{
strcpy(szKey, szMimeKey);
strcat(szKey, pszMime);
switch (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey))
{
case ERROR_SUCCESS:
hr = NOERROR;
break;
// win32 will return file not found instead of bad key
case ERROR_FILE_NOT_FOUND:
case ERROR_BADKEY:
hr = REGDB_E_CLASSNOTREG;
break;
default:
hr = REGDB_E_READREGDB;
break;
}
if (hr == NOERROR)
{
// if fIgnoreMimeClsid is set, ignore the CLSID entry
// in the HKCR\MIME tree.
if (!fIgnoreMimeClsid)
{
dwError = RegQueryValueEx(hMimeKey, szClassID, NULL
, &dwType, (LPBYTE)szValue, &dwValueLen);
hr = REGDB_E_CLASSNOTREG;
if (dwError == ERROR_SUCCESS)
{
WCHAR sz[256];
A2W(szValue,sz,256);
hr = CLSIDFromString(sz, pclsid);
}
if (hr == NOERROR)
{
goto End;
}
}
hr = REGDB_E_CLASSNOTREG;
dwValueLen = 256;
dwError = RegQueryValueEx(hMimeKey
, szExtension
, NULL
, &dwType
, (LPBYTE)szValue
, &dwValueLen);
if (dwError == ERROR_SUCCESS)
{
hr = GetClassFromExt(szValue,pclsid);
}
if (pdwMimeFlags)
{
DWORD dwFlags = 0;
*pdwMimeFlags = 0;
dwValueLen = sizeof(DWORD);
dwError = RegQueryValueEx(hMimeKey, szFlags, NULL
, &dwType, (LPBYTE)&dwFlags, &dwValueLen);
if (dwError == ERROR_SUCCESS)
{
*pdwMimeFlags = dwFlags;
}
}
}
}
End:
if (hMimeKey)
{
RegCloseKey(hMimeKey);
}
PerfDbgLog1(tagTransApi, NULL, "-GetMimeInfo (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: GetClassFromExt
//
// Synopsis:
//
// Arguments: [pszExt] --
// [pclsid] --
//
// Returns:
//
// History: 2-07-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetClassFromExt(LPSTR pszExt, CLSID *pclsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetClassFromExt",
"%.80q, %#x",
pszExt, pclsid
));
PerfDbgLog1(tagTransApi, NULL, "+GetClassFromExt (szExt:%s)", pszExt);
HRESULT hr = REGDB_E_CLASSNOTREG;
HKEY hkRoot = HKEY_CLASSES_ROOT;
char szFileExt[MAX_PATH];
DWORD cbFileExt = sizeof(szFileExt);
*pclsid = CLSID_NULL;
char szProgID[MAX_PATH];
LONG cbProgID = sizeof(szProgID);
if (pszExt[0] == '\0')
{
goto End;
}
strcpy(szFileExt,pszExt);
TransAssert((szFileExt[0] == '.'));
// the entry begins with '.' so it may be a file extension
// query the value (which is the ProgID)
if (RegQueryValue(hkRoot, szFileExt, szProgID, &cbProgID) == ERROR_SUCCESS)
{
// we got the value (ProgID), now query for the CLSID
// string and convert it to a CLSID
char szClsid[40];
LONG cbClsid = sizeof(szClsid);
strcat(szProgID, "\\Clsid");
if (RegQueryValue(HKEY_CLASSES_ROOT, szProgID, szClsid,&cbClsid) == ERROR_SUCCESS)
{
// make sure the clsid is valid
cbProgID = sizeof(szProgID);
char szClsidEntry[80];
strcpy(szClsidEntry, "Clsid\\");
strcat(szClsidEntry, szClsid);
if (RegQueryValue(HKEY_CLASSES_ROOT, szClsidEntry,szProgID, &cbProgID) == ERROR_SUCCESS)
{
CLSID clsid;
WCHAR sz[256];
A2W(szClsid,sz,256);
hr = CLSIDFromString(sz, pclsid);
if (hr != NOERROR)
{
*pclsid = CLSID_NULL;
hr = REGDB_E_CLASSNOTREG;
}
}
}
}
End:
PerfDbgLog1(tagTransApi, NULL, "-GetClassFromExt (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: IsValidURL
//
// Synopsis:
//
// Arguments: [pBC] --
// [szURL] --
// [dwReserved] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"IsValidURL",
"%#x, %.80wq, %#x",
pBC, szURL, dwReserved
));
HRESULT hr;
PerfDbgLog2(tagTransApi, NULL, "+IsValidURL(pBC:%lx, szURL:%ws)",pBC,szURL);
WCHAR wzUrlStr[MAX_URL_SIZE + 1];
if (szURL == NULL)
{
hr = E_INVALIDARG;
}
else if ( (ConstructURL(pBC, NULL, NULL, (LPWSTR)szURL, wzUrlStr, sizeof(wzUrlStr), CU_CANONICALIZE) == NOERROR)
&& IsOInetProtocol(pBC, wzUrlStr))
{
hr = NOERROR;
}
else
{
hr = S_FALSE;
}
PerfDbgLog3(tagTransApi, NULL, "-IsValidURL(pBC:%lx, szURL:%ws, hr:%lx)",pBC,szURL,hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetUrlScheme
//
// Synopsis:
//
// Arguments: pcwsz -- the URL
// [szURL] --
// [dwReserved] --
//
// Returns: URL_SCHEME_*
//
//----------------------------------------------------------------------------
DWORD
GetUrlScheme(LPCWSTR pcwzUrl)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetUrlScheme",
"%.80wq",
pcwzUrl
));
if(pcwzUrl)
{
PARSEDURLW puW;
puW.cbSize = sizeof(puW);
if(SUCCEEDED(ParseURLW(pcwzUrl, &puW)))
{
DEBUG_LEAVE(puW.nScheme);
return puW.nScheme;
}
}
DEBUG_LEAVE(URL_SCHEME_INVALID);
return URL_SCHEME_INVALID;
}
//+---------------------------------------------------------------------------
//
// Function: GetClassFileOrMime2
//
// Synopsis:
//
// Arguments: [pBC] --
// [wzFilename] --
// [pBuffer] --
// [cbSize] --
// [pwzMime] --
// [dwReserved] --
// [pclsid] --
// [fIgnoreMimeClsid] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI GetClassFileOrMime2(LPBC pBC, LPCWSTR pwzFilename, LPVOID pBuffer, DWORD cbSize,
LPCWSTR pwzMimeIn, DWORD dwReserved, CLSID *pclsid, BOOL fIgnoreMimeClsid)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"GetClassFileOrMime2",
"%#x, %.80wq, %#x, %#x, %.80wq, %#x, %#x, %B",
pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, dwReserved, pclsid, fIgnoreMimeClsid
));
PerfDbgLog1(tagTransApi, NULL, "+GetClassFileOrMime(%lx)",pBC);
HRESULT hr = REGDB_E_CLASSNOTREG;
HRESULT hrPlugin = REGDB_E_CLASSNOTREG;
HRESULT hrClass = REGDB_E_CLASSNOTREG;
char szMime[SZMIMESIZE_MAX];
char szFilename[MAX_PATH];
LPSTR pszMime = NULL;
LPSTR pszFilename = NULL;
LPSTR pszExt = NULL;
LPWSTR pwzMime = (LPWSTR)pwzMimeIn;
DWORD cbMime = SZMIMESIZE_MAX;
CLSID clsidPlugin = CLSID_NULL;
BOOL fDocFile = FALSE;
DWORD dwClsCtx = 0;
DWORD dwFlags = (fIgnoreMimeClsid) ? MIMEFLAGS_IGNOREMIME_CLASSID : 0;
if ( pclsid == NULL
|| (!pwzFilename && (!pBuffer || !cbSize) && !pwzMimeIn))
{
hr = E_INVALIDARG;
goto errRet;
}
*pclsid = CLSID_NULL;
//sniff data here or when setting the mime
if (pBuffer && cbSize)
{
fDocFile = (IsDocFile(pBuffer,cbSize) == S_OK);
if (fDocFile)
{
// do not pass the buffer - no need to sniff data
hr = FindMimeFromData(pBC, pwzFilename, NULL, 0, pwzMimeIn, 0, &pwzMime, 0);
}
else
{
hr = FindMimeFromData(pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, 0, &pwzMime, 0);
}
}
if (pwzMime)
{
// convert the mime
W2A(pwzMime, szMime, SZMIMESIZE_MAX);
pszMime = szMime;
}
if (pwzFilename)
{
W2A(pwzFilename, szFilename, MAX_PATH);
pszFilename = szFilename;
}
// 1. find the class based on the mime
if (pszMime)
{
if (pBC)
{
hr = FindMediaTypeClass(pBC, szMime, pclsid, 0);
}
if (hr != NOERROR)
{
// get the class from the mime string
hr = FindMediaTypeClassInfo(pszMime, pszFilename, pclsid, &dwClsCtx, dwFlags);
}
}
// 2. find class of docfile
if ((hr != NOERROR || IsEqualGUID(*pclsid, CLSID_NULL)) && cbSize && fDocFile)
{
// get class from docfile
hr = GetClassDocFileBuffer(pBuffer, cbSize, pclsid);
}
// 3. use the file to find the class
if ( (hr != NOERROR)
&& pszFilename)
{
pszExt = FindFileExtension(pszFilename);
// use extension and use class mapping
if (pszExt != NULL)
{
char szMimeExt[SZMIMESIZE_MAX];
DWORD cbMimeExt = SZMIMESIZE_MAX;
// get the mime for the file
hr = GetMimeFromExt(pszExt,szMimeExt, &cbMimeExt);
if ( (hr == NOERROR)
&& ( (pszMime && strcmp(pszMime, szMimeExt))
|| !pszMime)
)
{
hr = REGDB_E_CLASSNOTREG;
if (pBC)
{
// check for class mapping
hr = FindMediaTypeClass(pBC, szMimeExt, pclsid, 0);
}
if (hr != NOERROR)
{
// get the class from the mime string
hr = FindMediaTypeClassInfo(szMimeExt, pszFilename, pclsid, &dwClsCtx, dwFlags);
}
}
}
// last call GetClassFile
if ( hr != NOERROR && pwzFilename && (!pwzMime || fDocFile) )
{
hr = GetClassFile(pwzFilename, pclsid);
}
// should never need to use file to locate CLSID_HTMLDocument
if (IsEqualGUID(*pclsid, CLSID_HTMLDocument))
{
*pclsid = CLSID_NULL;
hrClass = REGDB_E_CLASSNOTREG;
}
}
// 4. if available check the class id and
// trigger check for plugin class id if needed
if ( (hr == NOERROR)
&& !IsEqualGUID(*pclsid, CLSID_NULL))
{
hrClass = NOERROR;
if (dwClsCtx == 0)
{
hr = GetClsIDInfo(pclsid, 0, &dwClsCtx);
}
if (hr == NOERROR)
{
if (dwClsCtx & CLSCTX_DOCOBJECT)
{
// server of class is a docobject
hrPlugin = NOERROR;
}
else if (dwClsCtx & CLSCTX_INPROC)
{
// server of class is inproc
// check if the class is mshtml tread it as docobject and stop
// looking for plugin
if (IsEqualGUID(*pclsid, CLSID_MsHtml))
{
hrPlugin = NOERROR;
}
}
else if (dwClsCtx & CLSCTX_LOCAL_SERVER)
{
// server of class is local
}
}
// else
// class is not properly registered
//
}
// 5. check if the download is for a plugin
// if yes get the plugin host class id
if (hrPlugin != NOERROR)
{
if (pszExt == NULL && pszFilename)
{
pszExt = FindFileExtension(pszFilename);
}
// if we have a mime and/or an extension mime check if
// this is a plugin or an ocx
if (pszExt || pszMime)
{
hrPlugin = GetPlugInClsID(pszExt, NULL, pszMime, &clsidPlugin);
}
}
else
{
hrPlugin = E_FAIL;
}
// 6. the plugin class use it
if ( (hrPlugin == NOERROR) && !(dwReserved & GETCLASSFILEORMIME_IGNOREPLUGIN))
{
*pclsid = clsidPlugin;
hr = hrPlugin;
}
// used the class found
else
{
hr = hrClass;
}
if (pwzMime != pwzMimeIn)
{
delete [] pwzMime;
}
TransAssert(( (hr != NOERROR && IsEqualGUID(*pclsid, CLSID_NULL))
|| (hr == NOERROR && !IsEqualGUID(*pclsid, CLSID_NULL)) ));
errRet:
TransAssert((hr == NOERROR || hr == REGDB_E_CLASSNOTREG || hr == E_INVALIDARG));
PerfDbgLog1(tagTransApi, NULL, "-GetClassFileOrMime (hr:%lx)",hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetClassFileOrMime
//
// Synopsis:
//
// Arguments: [pBC] --
// [wzFilename] --
// [pBuffer] --
// [cbSize] --
// [pwzMime] --
// [dwReserved] --
// [pclsid] --
//
// Returns:
//
// History: 4-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI GetClassFileOrMime(LPBC pBC, LPCWSTR pwzFilename, LPVOID pBuffer, DWORD cbSize,
LPCWSTR pwzMimeIn, DWORD dwReserved, CLSID *pclsid)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"GetClassFileOrMime",
"%#x, %.80wq, %#x, %#x, %.80wq, %#x, %#x",
pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn, dwReserved, pclsid
));
HRESULT hr = GetClassFileOrMime2(pBC, pwzFilename, pBuffer, cbSize, pwzMimeIn,
dwReserved, pclsid, FALSE);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetClassDocFileBuffer
//
// Synopsis:
//
// Arguments: [pbuffer] --
// [dwSize] --
// [pclsid] --
//
// Returns:
//
// History: 2-28-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetClassDocFileBuffer(LPVOID pbuffer, DWORD dwSize, CLSID *pclsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetClassDocFileBuffer",
"%#x, %#x, %#x",
pbuffer, dwSize, pclsid
));
PerfDbgLog(tagTransApi, NULL, "+GetClassDocFileBuffer");
HRESULT hr = E_FAIL;
ILockBytes *pilb;
IStorage *pstg;
STATSTG stat;
HGLOBAL hGlobal = 0;
hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_NODISCARD, dwSize);
if (hGlobal)
{
memcpy(hGlobal, pbuffer, dwSize);
hr = CreateILockBytesOnHGlobal(hGlobal,FALSE,&pilb);
if (hr == NOERROR)
{
hr = StgOpenStorageOnILockBytes(pilb,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL,0,&pstg);
if (hr == NOERROR)
{
pstg->Stat(&stat, STATFLAG_NONAME);
pstg->Release();
*pclsid = stat.clsid;
}
else
{
hr = E_FAIL;
}
}
GlobalFree(hGlobal);
}
PerfDbgLog1(tagTransApi, NULL, "-GetClassDocFileBuffer (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT GetCodeBaseFromDocFile(LPBYTE pBuffer, ULONG ulSize, LPWSTR *pwzClassStr,
LPWSTR pwzBaseUrl, DWORD *lpdwVersionMS, DWORD *lpdwVersionLS);
//+---------------------------------------------------------------------------
//
// Method: IsHandlerAvailable
//
// Synopsis:
//
// Arguments: [pClsid] --
// [pMime] --
//
// Returns:
//
// History: 11-07-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT IsHandlerAvailable(LPWSTR pwzUrl, LPWSTR pwzMime, CLSID *pclsid, LPBYTE pBuffer, ULONG cbSize)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"IsHandlerAvailable",
"%.80wq, %.80wq, %#x, %#x, %#x",
pwzUrl, pwzMime, pclsid, pBuffer, cbSize
));
PerfDbgLog(tagTransApi, NULL, "+GetCodeBaseFromDocFile");
HRESULT hr = E_FAIL, hr1;
LPWSTR szDistUnit = 0;
BOOL fIgnoreMimeClsid = FALSE, fHasHandler = FALSE, fDocFile = FALSE;
CLocalComponentInfo lci;
CHAR szKey[SZMIMESIZE_MAX + ulMimeKeyLen];
CHAR szMime[SZMIMESIZE_MAX];
LPSTR pszUrl = 0;
W2A(pwzMime, szMime, SZMIMESIZE_MAX);
pszUrl = DupW2A(pwzUrl); // can potentially be very long
if ((pwzMime == 0) || (*pwzMime == 0))
{
hr = E_INVALIDARG;
}
else
{
HKEY hMimeKey = 0;
*pclsid = CLSID_NULL;
strcpy(szKey, szMimeKey);
strcat(szKey, szMime);
// NOTE: different handlers may be implemented in different ways, for example.
// the abscence of a CLSID does not imply the handler is bad or missing.
// check if mime type exists in "Content Type" branch
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, szKey, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
{
fHasHandler = TRUE;
RegCloseKey(hMimeKey);
hMimeKey = 0;
}
// if not check if extension type has handler
if (!fHasHandler)
{
LPSTR pszExt = FindFileExtension(pszUrl);
// try for handler of extension
if (pszExt && *pszExt == '.')
{
hMimeKey = 0;
// there may be a handler for this extension already
if (RegOpenKeyEx(HKEY_CLASSES_ROOT, pszExt, 0, KEY_QUERY_VALUE, &hMimeKey) == ERROR_SUCCESS)
{
fHasHandler = TRUE;
RegCloseKey(hMimeKey);
}
}
}
// we haven't found a handler yet, in case of DocFile, check if CLSID associated
// with it exists.
if (!fHasHandler && SUCCEEDED(IsDocFile(pBuffer,cbSize)))
{
DWORD dwVersionMS = 0, dwVersionLS = 0;
LPWSTR pwzCodeBase = 0;
hr1 = GetCodeBaseFromDocFile(pBuffer, cbSize, &pwzCodeBase, NULL, &dwVersionMS, &dwVersionLS);
if (pwzCodeBase) {
delete pwzCodeBase;
}
hr1 = GetClassDocFileBuffer(pBuffer, cbSize, pclsid);
if (SUCCEEDED(hr1) && !IsEqualCLSID(*pclsid, CLSID_NULL))
{
StringFromCLSID(*pclsid, &szDistUnit);
hr1 = IsControlLocallyInstalled(NULL, pclsid, szDistUnit, dwVersionMS, dwVersionLS, &lci, NULL);
if (hr1 == S_OK)
{
fHasHandler = TRUE;
}
if (szDistUnit)
{
delete szDistUnit;
}
}
}
}
if (pszUrl)
{
delete [] pszUrl;
}
if (fHasHandler)
{
hr = S_OK;
}
else
{
hr = S_FALSE;
}
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: GetCodeBaseFromDocFile
//
// Synopsis:
//
// Arguments: [pBuffer] --
// [ulSize] --
// [pwzClassStr] --
//
// Returns:
//
// History: 11-07-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetCodeBaseFromDocFile(LPBYTE pBuffer, ULONG ulSize, LPWSTR *pwzClassStr,
LPWSTR pwzBaseUrl, DWORD *lpdwVersionMS, DWORD *lpdwVersionLS)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetCodeBaseFromDocFile",
"%#x, %#x, %#x, %.80wq, %#x, %#x",
pBuffer, ulSize, pwzClassStr, pwzBaseUrl, lpdwVersionMS, lpdwVersionLS
));
PerfDbgLog(tagTransApi, NULL, "+GetCodeBaseFromDocFile");
HRESULT hr = E_FAIL;
ILockBytes *pilb;
IStorage *pstg;
STATSTG stat;
static ULONG cpSpec = DOCFILE_NUMPROPERTIES;
static PROPSPEC rgpSpec[DOCFILE_NUMPROPERTIES] = {
{ PRSPEC_PROPID, DOCFILE_PROPID_CODEBASE },
{ PRSPEC_PROPID, DOCFILE_PROPID_MAJORVERSION },
{ PRSPEC_PROPID, DOCFILE_PROPID_MINORVERSION } };
PROPVARIANT rgVarDisplay[DOCFILE_NUMPROPERTIES];
if (!pwzClassStr || !lpdwVersionMS || !lpdwVersionLS)
{
hr = E_INVALIDARG;
}
else
{
HGLOBAL hGlobal = 0;
hGlobal = GlobalAlloc(GMEM_FIXED | GMEM_NODISCARD, ulSize);
*pwzClassStr = 0;
if (hGlobal)
{
memcpy(hGlobal, pBuffer, ulSize);
hr = CreateILockBytesOnHGlobal(hGlobal,FALSE,&pilb);
if (hr == NOERROR)
{
hr = StgOpenStorageOnILockBytes(pilb,NULL,STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE,
NULL,0,&pstg);
if (hr == NOERROR)
{
IPropertySetStorage *ppss = 0;
hr = pstg->QueryInterface(IID_IPropertySetStorage, (void **)&ppss);
if (SUCCEEDED(hr))
{
IPropertyStorage *pps = 0;
//BUGBUG: there is potential for error here if data structure of
// PropertyStorage is not fully loaded. since we have read only access
// we should be ok.
hr = ppss->Open(FMTID_CodeBase, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, (IPropertyStorage **)&pps);
if (SUCCEEDED(hr))
{
hr = pps->ReadMultiple(cpSpec, rgpSpec, rgVarDisplay);
if (SUCCEEDED(hr))
{
*pwzClassStr = rgVarDisplay[0].pwszVal;
*lpdwVersionMS = rgVarDisplay[1].ulVal;
*lpdwVersionLS = rgVarDisplay[2].ulVal;
}
pps->Release();
}
ppss->Release();
}
pstg->Release();
}
else
{
hr = E_FAIL;
}
}
GlobalFree(hGlobal);
}
}
if (SUCCEEDED(hr) && pwzBaseUrl)
{
LPWSTR pwzNewClassStr = 0;
DWORD dwLen, dwNewLen;
HRESULT hr1;
// we do not know what the combined maximum Url length is, so as
// an upper bound we take twice the combined url's plus 10.
dwLen = 2*(lstrlenW(pwzBaseUrl) + lstrlenW(*pwzClassStr)) + 10;
pwzNewClassStr = new WCHAR[dwLen];
if (pwzNewClassStr)
{
hr1 = CoInternetCombineUrl(pwzBaseUrl, *pwzClassStr, ICU_NO_ENCODE, pwzNewClassStr, dwLen, &dwNewLen, 0);
if (SUCCEEDED(hr1) && dwNewLen)
{
delete [] *pwzClassStr;
*pwzClassStr = pwzNewClassStr;
}
else
{
delete [] pwzNewClassStr;
}
}
}
PerfDbgLog1(tagTransApi, NULL, "-GetCodeBaseFromDocFile (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: UrlMkSetSessionOption
//
// Synopsis:
//
// Arguments: [dwOption] --
// [pBuffer] --
// [dwBufferLength] --
// [dwReserved] --
//
// Returns:
//
// History: 5-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"UrlMkSetSessionOption",
"%#x, %#x, %#x, %#x",
dwOption, pBuffer, dwBufferLength, dwReserved
));
// BUGBUG - Function not threadsafe.
PerfDbgLog(tagTransApi, NULL, "+UrlMkSetSessionOption");
HRESULT hr;
switch(dwOption)
{
// Change the User Agent string for this process.
case URLMON_OPTION_USERAGENT:
{
// Validate buffer, allocate new user agent string,
// delete old if necessary, copy and reference with
// g_pszUserAgentString.
if (!(pBuffer && dwBufferLength))
{
hr = E_INVALIDARG;
break;
}
LPSTR pszTemp = new CHAR[dwBufferLength + 1];
if (!pszTemp)
{
TransAssert(pszTemp && "Allocating memory for User-Agent header failed");
hr = E_OUTOFMEMORY;
break;
}
memcpy(pszTemp, pBuffer, dwBufferLength);
pszTemp[dwBufferLength] = '\0';
if (g_pszUserAgentString)
{
delete [] g_pszUserAgentString;
}
g_pszUserAgentString = pszTemp;
hr = S_OK;
break;
}
// Refresh user agent string from registry for this process.
case URLMON_OPTION_USERAGENT_REFRESH:
{
// Refresh, delete old user agent string if necessary.
// g_pszUserAgentString references refreshed string.
LPSTR pszTemp = g_pszUserAgentString;
// NULL forces GetUserAgentString to refresh from registry.
g_pszUserAgentString = NULL;
g_pszUserAgentString = (LPSTR) GetUserAgentString();
if (!g_pszUserAgentString)
{
g_pszUserAgentString = pszTemp;
hr = S_FALSE;
break;
}
// Need to set this on the session handle also.
if (g_hSession)
InternetSetOption(g_hSession, INTERNET_OPTION_USER_AGENT,
g_pszUserAgentString, strlen(g_pszUserAgentString));
delete [] pszTemp;
hr = S_OK;
break;
}
// Set or reload proxy info from registry.
case INTERNET_OPTION_PROXY:
case INTERNET_OPTION_REFRESH:
{
// InternetSetOption does its own buffer validation.
if (InternetSetOption(NULL, dwOption, pBuffer, dwBufferLength))
{
hr = S_OK;
break;
}
hr = S_FALSE;
break;
}
default:
{
hr = E_INVALIDARG;
break;
}
}
PerfDbgLog1(tagTransApi, NULL, "-UrlMkSetSessionOption (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: UrlMkGetSessionOption
//
// Synopsis:
//
// Arguments: [dwOption] --
// [pBuffer] --
// [dwBufferLength] --
// [dwReserved] --
//
// Returns:
//
// History: 5-06-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI UrlMkGetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength, DWORD *pdwBufferLengthOut, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"UrlMkSetSessionOption",
"%#x, %#x, %#x, %#x",
dwOption, pBuffer, dwBufferLength, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+UrlMkGetSessionOption");
HRESULT hr = E_FAIL;
if( !pdwBufferLengthOut )
{
DEBUG_LEAVE_API(E_INVALIDARG);
return E_INVALIDARG;
}
if (dwOption == URLMON_OPTION_USERAGENT)
{
// get the default user agent string
LPCSTR pszStr = GetUserAgentString();
DWORD cLen = strlen(pszStr);
*pdwBufferLengthOut = cLen + 1;
hr = E_OUTOFMEMORY;
if (cLen < dwBufferLength )
{
if( pBuffer )
{
strcpy((LPSTR)pBuffer, pszStr);
// AOL BUG 66102 - we always return E_FAIL
// hr = NOERROR;
}
else
{
hr = E_INVALIDARG;
}
}
}
else if (dwOption == URLMON_OPTION_URL_ENCODING)
{
if( !pBuffer || dwBufferLength < sizeof(DWORD) )
{
hr = E_INVALIDARG;
}
else
{
DWORD dwEncoding = URL_ENCODING_NONE;
BOOL fDefault = FALSE;
DWORD dwUrlEncodingDisableUTF8;
DWORD dwSize = sizeof(DWORD);
if( ERROR_SUCCESS == SHRegGetUSValue(
INTERNET_SETTING_KEY,
"UrlEncoding",
NULL,
(LPBYTE) &dwUrlEncodingDisableUTF8,
&dwSize,
FALSE,
(LPVOID) &fDefault,
sizeof(fDefault) ) )
{
if( dwUrlEncodingDisableUTF8)
dwEncoding = URL_ENCODING_DISABLE_UTF8;
else
dwEncoding = URL_ENCODING_ENABLE_UTF8;
}
hr = NOERROR;
*pdwBufferLengthOut = sizeof(DWORD);
memcpy(pBuffer, (LPVOID)(&dwEncoding), sizeof(DWORD));
}
}
else
{
hr = E_INVALIDARG;
}
PerfDbgLog1(tagTransApi, NULL, "-UrlMkGetSessionOption (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: GetPlugInClsID
//
// Synopsis: load the plugin ocx; get the FindPluginByExtA address
// call the FindPluginByExtA api
//
// Arguments: [pszExt] --
// [szMime] --
// [pclsid] --
//
// Returns: NOERROR and plugin class id if file is handled by plugin
// REGDB_E_CLASSNOTREG otherwise
//
// History: 7-16-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT GetPlugInClsID(LPSTR pszExt, LPSTR pszName, LPSTR pszMime, CLSID *pclsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"GetPlugInClsID",
"%.80q, %.80q, %.80q, %#x",
pszExt, pszName, pszMime, pclsid
));
HRESULT hr = REGDB_E_CLASSNOTREG;
PerfDbgLog3(tagTransApi, NULL, "+GetPlugInClsID (pszExt:%s, pszName:%s, pszMime:%s)", pszExt, pszName, pszMime);
typedef BOOL (WINAPI * pfnFINDPLUGINBYEXT)(char *szExt, char *szName, char *szMime);
static pfnFINDPLUGINBYEXT pfnFindPlugin = NULL;
static BOOL fPluginLoaded = FALSE;
static BOOL fGotProcAddr = FALSE;
if (!fPluginLoaded)
{
g_hLibPluginOcx = LoadLibraryA("plugin.ocx");
fPluginLoaded = TRUE;
}
if (g_hLibPluginOcx != NULL)
{
if (!fGotProcAddr)
{
pfnFindPlugin = (pfnFINDPLUGINBYEXT)GetProcAddress(g_hLibPluginOcx, "FindPluginByExtA");
fGotProcAddr = TRUE;
if (pfnFindPlugin == NULL)
{
DbgLog(tagTransApi, NULL, "Failed to find entry point FindPluginByExt in plugin.ocx");
}
}
if (pfnFindPlugin && pfnFindPlugin(pszExt, pszName, pszMime))
{
hr = S_OK;
}
}
else
{
DbgLog(tagTransApi, NULL, "Failed to find plugin.ocx");
}
if (hr == S_OK)
{
*pclsid = CLSID_PluginHost;
}
PerfDbgLog1(tagTransApi, NULL, "-GetPlugInClsID (hr:%lx)", hr);
DEBUG_LEAVE(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: StringAFromCLSID
//
// Synopsis: returns an ansi string of given class id
//
// Arguments: [pclsid] -- the class id
//
// Returns: pointer to class id string or
// NULL if out of memory
//
// History: 7-20-96 JohannP (Johann Posch) Created
//
// Notes: string pointer has to be deleted with delete (operator)
//
//----------------------------------------------------------------------------
LPSTR StringAFromCLSID(CLSID *pclsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"StringAFromCLSID",
"%#x",
pclsid
));
LPOLESTR pwzStr;
LPSTR pszStr = NULL;
TransAssert((pclsid));
StringFromCLSID(*pclsid, &pwzStr);
if (pwzStr)
{
pszStr = SzDupWzToSz(pwzStr, TRUE);
delete pwzStr;
}
DEBUG_LEAVE(pszStr);
return pszStr;
}
//+---------------------------------------------------------------------------
//
// Function: CLSIDFromStringA
//
// Synopsis:
//
// Arguments: [pszClsid] --
// [pclsid] --
//
// Returns:
//
// History: 11-20-1996 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
HRESULT CLSIDFromStringA(LPSTR pszClsid, CLSID *pclsid)
{
DEBUG_ENTER((DBG_TRANSDAT,
Hresult,
"CLSIDFromStringA",
"%.80q, %#x",
pszClsid, pclsid
));
WCHAR sz[CLSIDSTR_MAX];
A2W(pszClsid,sz,CLSIDSTR_MAX);
HRESULT hr = CLSIDFromString(sz, pclsid);
DEBUG_LEAVE(hr);
return hr;
}
#include "ocidl.h"
#ifndef unix
#include "..\urlhlink\urlhlink.h"
#else
#include "../urlhlink/urlhlink.h"
#endif /* unix */
#define IS_E_PENDING(hr) (hr == E_PENDING)
//+---------------------------------------------------------------------------
//
// Function: URLDownloadA
//
// Synopsis:
//
// Arguments: [pUnk] --
// [szURL] --
// [pBindInfo] --
// [pBSCB] --
// [dwReserved] --
//
// Returns:
//
// History: 7-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI URLDownloadA(IUnknown *pUnk, LPCSTR pszURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"URLDownloadA",
"%#x, %.80q, %#x, %#x, %#x",
pUnk, pszURL, pBindInfo, pBSCB, dwReserved
));
PerfDbgLog1(tagTransApi, NULL, "+URLDownloadA (pszUrl:%s)", pszURL);
HRESULT hr = NOERROR;
LPCWSTR pwzUrl = DupA2W((LPSTR) pszURL);
if (pwzUrl)
{
hr = URLDownloadW(pUnk,pwzUrl,pBindInfo,pBSCB, 0);
}
PerfDbgLog1(tagTransApi, NULL, "-URLDownloadA (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: URLDownloadW
//
// Synopsis:
//
// Arguments: [pUnk] --
// [pwzURL] --
// [pBindInfo] --
// [pBSCB] --
// [dwReserved] --
//
// Returns:
//
// History: 7-27-96 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI URLDownloadW(IUnknown *pUnk, LPCWSTR pwzURL, DWORD pBindInfo, IBindStatusCallback *pBSCB, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"URLDownloadW",
"%#x, %.80wq, %#x, %#x, %#x",
pUnk, pwzURL, pBindInfo, pBSCB, dwReserved
));
PerfDbgLog1(tagTransApi, NULL, "+URLDownloadW (pwzUrl:%ws)", pwzURL);
HRESULT hr;
IOleObject * pOleObject = 0;
IServiceProvider * pServiceProvider = 0;
IMoniker * pmkr = 0;
IBindCtx * pBndCtx = 0;
IBindHost * pBindHost = 0;
IStream * pstrm = 0;
// Don't bother if we don't have a caller...
if( pUnk )
{
// By convention the we give the caller first crack at service
// provider. The assumption here is that if they implement it
// they have the decency to forward QS's to their container.
hr = pUnk->QueryInterface( IID_IServiceProvider,
(void**)&pServiceProvider );
if( FAILED(hr) )
{
// Ok, now try the 'slow way' : maybe the object is an 'OLE' object
// that knows about it's client site:
hr = pUnk->QueryInterface( IID_IOleObject, (void**)&pOleObject );
if( SUCCEEDED(hr) )
{
IOleClientSite * pClientSite = 0;
hr = pOleObject->GetClientSite(&pClientSite);
if( SUCCEEDED(hr) )
{
// Now see if we have a service provider at that site
hr = pClientSite->QueryInterface
( IID_IServiceProvider,
(void**)&pServiceProvider );
}
if( pClientSite )
pClientSite->Release();
}
else
{
// Ok, it's not an OLE object, maybe it's one of these
// new fangled 'ObjectWithSites':
IObjectWithSite * pObjWithSite = 0;
hr = pUnk->QueryInterface( IID_IObjectWithSite,
(void**)&pObjWithSite );
if( SUCCEEDED(hr) )
{
// Now see if we have a service provider at that site
hr = pObjWithSite->GetSite(IID_IServiceProvider,
(void**)&pServiceProvider);
}
if( pObjWithSite )
pObjWithSite->Release();
}
if( pOleObject )
pOleObject->Release();
}
// BUGBUG: In the code above we stop looking at one level up --
// this may be too harsh and we should loop on client sites
// until we get to the top...
if( !pServiceProvider )
hr = E_UNEXPECTED;
// Ok, we have a service provider, let's see if BindHost is
// available. (Here there is some upward delegation going on
// via service provider).
if( SUCCEEDED(hr) )
hr = pServiceProvider->QueryService( SID_SBindHost, IID_IBindHost,
(void**)&pBindHost );
if( pServiceProvider )
pServiceProvider->Release();
pmkr = 0;
}
if (pBindHost)
{
// This allows the container to actually drive the download
// by creating it's own moniker.
hr = pBindHost->CreateMoniker( LPOLESTR(pwzURL),NULL, &pmkr,0 );
if( SUCCEEDED(hr) )
{
// This allows containers to hook the download for
// doing progress and aborting
hr = pBindHost->MonikerBindToStorage(pmkr, NULL, pBSCB, IID_IStream,(void**)&pstrm);
}
pBindHost->Release();
}
else
{
// If you are here, then either the caller didn't pass
// a 'caller' pointer or the caller is not in a BindHost
// friendly environment.
hr = CreateURLMoniker( 0, pwzURL, &pmkr );
if( SUCCEEDED(hr) )
{
hr = CreateAsyncBindCtx( 0,pBSCB,0, &pBndCtx );
}
if (SUCCEEDED(hr))
{
hr = pmkr->BindToStorage( pBndCtx, NULL, IID_IStream, (void**)&pstrm );
}
}
if( pstrm )
pstrm->Release();
if( pmkr )
pmkr->Release();
if( pBndCtx )
pBndCtx->Release();
PerfDbgLog1(tagTransApi, NULL, "-URLDownloadW (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: FindMimeFromData
//
// Synopsis:
//
// Arguments: [pBC] --
// [pwzURL] --
// [pBuffer] --
// [cbSize] --
// [dwReserved] --
//
// Returns:
//
// History: 3-28-97 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI FindMimeFromData(
LPBC pBC, // bind context - can be NULL
LPCWSTR pwzUrl, // url - can be null
LPVOID pBuffer, // buffer with data to sniff - can be null (pwzUrl must be valid)
DWORD cbSize, // size of buffer
LPCWSTR pwzMimeProposed, // proposed mime if - can be null
DWORD dwMimeFlags, // will be determined
LPWSTR *ppwzMimeOut, // the suggested mime
DWORD dwReserved) // must be 0
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"FindMimeFromData",
"%#x, %.80wq, %#x, %#x, %.80wq, %#x, %.80wq, %#x",
pBC, pwzUrl, pBuffer, cbSize, pwzMimeProposed, dwMimeFlags, ppwzMimeOut, dwReserved
));
LPCWSTR wzMimeFromData = 0;
HRESULT hr = E_FAIL;
PerfDbgLog1(tagTransApi, NULL, "+FindMimeFromData (sugg: %ws)", pwzMimeProposed ? pwzMimeProposed : L"NULL");
if ( !ppwzMimeOut
|| (!pwzUrl && !pBuffer))
{
hr = E_INVALIDARG;
}
else if( pBuffer || pwzMimeProposed )
{
CContentAnalyzer ca;
wzMimeFromData = ca.FindMimeFromData(pwzUrl,(char*) pBuffer, cbSize, pwzMimeProposed, dwMimeFlags);
if (wzMimeFromData)
{
*ppwzMimeOut = OLESTRDuplicate(wzMimeFromData);
if (*ppwzMimeOut)
{
hr = NOERROR;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
else
{
// file extension is the only solution
LPSTR pszExt = NULL;
CHAR szUrl[MAX_PATH];
CHAR szMime[MAX_PATH];
DWORD cbMime = MAX_PATH;
W2A(pwzUrl, szUrl, MAX_PATH);
pszExt = FindFileExtension(szUrl);
if( pszExt )
{
hr = GetMimeFromExt(pszExt, szMime, &cbMime);
}
else
{
hr = E_FAIL;
}
if( SUCCEEDED(hr) )
{
*ppwzMimeOut = DupA2W(szMime);
if (*ppwzMimeOut)
{
hr = NOERROR;
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
PerfDbgLog1(tagTransApi, NULL, "-FindMimeFromData (actual: %ws)", wzMimeFromData ? wzMimeFromData : L"NULL" );
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetParseUrl
//
// Synopsis:
//
// Arguments: [pwzUrl] --
// [ParseAction] --
// [dwFlags] --
// [pszResult] --
// [cchResult] --
// [dwReserved] --
//
// Returns:
//
// History: 4-13-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetParseUrl(
LPCWSTR pwzUrl,
PARSEACTION ParseAction,
DWORD dwFlags,
LPWSTR pszResult,
DWORD cchResult,
DWORD *pcchResult,
DWORD dwReserved
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetParseUrl",
"%.80wq, %#x, %#x, %#x, %#x, %#x, %#x",
pwzUrl, ParseAction, dwFlags, pszResult, cchResult, pcchResult, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetParseUrl");
COInetSession *pOInetSession = 0;
HRESULT hr = INET_E_DEFAULT_ACTION;
if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl))
{
hr = GetCOInetSession(0, &pOInetSession,0);
if (hr == NOERROR)
{
hr = pOInetSession->ParseUrl(pwzUrl, ParseAction, dwFlags, pszResult, cchResult, pcchResult, dwReserved);
pOInetSession->Release();
}
}
if (hr == INET_E_DEFAULT_ACTION)
{
hr = E_FAIL;
switch (ParseAction)
{
case PARSE_CANONICALIZE :
*pcchResult = cchResult;
hr = UrlCanonicalizeW(pwzUrl, pszResult, pcchResult, dwFlags);
break;
case PARSE_SCHEMA :
*pcchResult = cchResult;
hr = UrlGetPartW(pwzUrl, pszResult, pcchResult, URL_PART_SCHEME, 0);
break;
break;
case PARSE_SITE :
break;
case PARSE_DOMAIN :
*pcchResult = cchResult;
hr = UrlGetPartW(pwzUrl, pszResult, pcchResult, URL_PART_HOSTNAME, 0);
TransAssert(hr != E_POINTER);
break;
break;
case PARSE_FRIENDLY :
break;
case PARSE_SECURITY_URL :
// should return "schema:host" for all protocols
break;
case PARSE_ROOTDOCUMENT :
{
PARSEDURLW puW;
puW.cbSize = sizeof(PARSEDURLW);
if (SUCCEEDED(ParseURLW(pwzUrl, &puW)) && IsHierarchicalScheme(puW.nScheme))
{
DWORD cchRequired = 1;
// The first URLGetPartW call is just to get the number of chars required for the hostname.
// This is not as efficient but keeps the code simpler.
if ((UrlGetPartW(pwzUrl, pszResult, &cchRequired, URL_PART_HOSTNAME, 0)) == E_POINTER)
{
cchRequired += (puW.cchProtocol + 3);
if (cchResult >= cchRequired)
{
LPWSTR pszCopyTo = pszResult;
*pcchResult = cchRequired - 1; // don't include terminating NULL char.
memcpy(pszCopyTo, puW.pszProtocol, puW.cchProtocol * sizeof(WCHAR));
pszCopyTo += puW.cchProtocol;
memcpy(pszCopyTo, L"://", 3 * sizeof(WCHAR));
pszCopyTo += 3;
DWORD cchHost = (DWORD) (cchResult - (pszCopyTo - pszResult));
hr = UrlGetPartW(pwzUrl, pszCopyTo, &cchHost, URL_PART_HOSTNAME, 0);
}
else
{
*pcchResult = cchRequired;
hr = E_OUTOFMEMORY;
}
}
}
}
break;
case PARSE_DOCUMENT :
break;
case PARSE_ANCHOR :
break;
case PARSE_ENCODE :
case PARSE_UNESCAPE :
*pcchResult = cchResult;
hr = UrlUnescapeW((LPWSTR)pwzUrl, pszResult, pcchResult, dwFlags);
break;
case PARSE_ESCAPE :
case PARSE_DECODE :
*pcchResult = cchResult;
hr = UrlEscapeW(pwzUrl, pszResult, pcchResult, dwFlags);
break;
case PARSE_PATH_FROM_URL :
*pcchResult = cchResult;
hr = PathCreateFromUrlW(pwzUrl, pszResult, pcchResult, dwFlags);
break;
case PARSE_URL_FROM_PATH :
*pcchResult = cchResult;
hr = UrlCreateFromPathW(pwzUrl, pszResult, pcchResult, dwFlags);
break;
case PARSE_LOCATION :
{
hr = E_FAIL;
*pcchResult = 0;
LPCWSTR pwzStr = UrlGetLocationW(pwzUrl); //, pszResult, pcchResult, dwFlags);
if (pwzStr)
{
DWORD dwlen = wcslen(pwzStr);
if (dwlen < cchResult)
{
wcscpy(pszResult, pwzStr);
*pcchResult = dwlen;
hr = NOERROR;
}
else
{
// buffer too small
}
}
}
break;
case PARSE_MIME :
default:
hr = E_FAIL;
}
}
PerfDbgLog1(tagTransApi, NULL, "-CoInternetParseUrl (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Method: IsHierarchicalScheme
//
// Synopsis:
//
// Arguments: [dwScheme] --
//
// Returns:
//
// History: 6-16-1997 Sanjays (Sanjay Shenoy) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL IsHierarchicalScheme(DWORD dwScheme)
{
DEBUG_ENTER((DBG_TRANSDAT,
Bool,
"IsHierarchicalScheme",
"%#x",
dwScheme
));
BOOL bReturn;
switch ( dwScheme )
{
case URL_SCHEME_HTTP:
case URL_SCHEME_FTP:
case URL_SCHEME_HTTPS:
case URL_SCHEME_NEWS:
case URL_SCHEME_GOPHER:
case URL_SCHEME_NNTP:
case URL_SCHEME_TELNET:
case URL_SCHEME_SNEWS:
bReturn = TRUE;
break;
default:
bReturn = FALSE;
break;
}
DEBUG_LEAVE(bReturn);
return bReturn;
}
//+---------------------------------------------------------------------------
//
// Method: IsHierarchicalUrl
//
// Synopsis:
//
// Arguments: [pwszUrl] --
//
// Returns:
//
// History: 6-16-1997 Sanjays (Sanjay Shenoy) Created
//
// Notes:
//
//----------------------------------------------------------------------------
BOOL IsHierarchicalUrl(LPCWSTR pwszUrl)
{
DEBUG_ENTER((DBG_TRANSDAT,
Bool,
"IsHierarchicalUrl",
"%.80wq",
pwszUrl
));
DWORD dwScheme = URL_SCHEME_INVALID;
if(pwszUrl)
{
PARSEDURLW pu;
pu.cbSize = sizeof(pu);
if(SUCCEEDED(ParseURLW(pwszUrl, &pu)))
dwScheme = pu.nScheme;
}
BOOL fRet = IsHierarchicalScheme(dwScheme);
DEBUG_LEAVE(fRet);
return fRet;
}
//+---------------------------------------------------------------------------
//
// Method: CoInternetGetSecurityUrl
//
// Synopsis:
//
// Arguments: [pwszUrl] --
// [ppszSecUrl] --
// [psuAction]
// [dwReserved]
// Returns:
//
// History: 4-28-1997 Sanjays (Sanjay Shenoy) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetGetSecurityUrl(
LPCWSTR pwszUrl,
LPWSTR *ppwszSecUrl, // out argument.
PSUACTION psuAction,
DWORD dwReserved
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetGetSecurityUrl",
"%.80wq, %#x, %#x, %#x",
pwszUrl, ppwszSecUrl, psuAction, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetGetSecurityUrl");
COInetSession *pOInetSession = NULL;
if (pwszUrl == NULL || ppwszSecUrl == NULL)
{
DEBUG_LEAVE_API(E_INVALIDARG);
return E_INVALIDARG;
}
if (psuAction != PSU_DEFAULT && psuAction != PSU_SECURITY_URL_ONLY)
{
DEBUG_LEAVE_API(E_NOTIMPL);
return E_NOTIMPL;
}
LPWSTR pwszSecUrl = (LPWSTR) pwszUrl;
*ppwszSecUrl = NULL;
BOOL bAllocSecUrl = FALSE; // Should we free pwszSecUrl?
HRESULT hr = S_OK;
// Step 1
// If this is a custom protocol, give it a chance to return back the
// security URL first.
hr = GetCOInetSession(0, &pOInetSession, 0);
if (hr == NOERROR)
{
DWORD dwId;
// It is important to loop here. The URL returned by a pluggable protocol by calling
// PARSE_SECURITY_URL might be another pluggable protocol.
while ( !g_bShortcircuitKnownProtocols || ((dwId = IsKnownProtocol(pwszSecUrl)) == DLD_PROTOCOL_NONE)
|| (dwId == DLD_PROTOCOL_STREAM)) // Special case mk: hack since there could be a
// namespace handler defined for it.
{
// Allocate as much memory as the url. This should be a good upper limit in most all cases.
DWORD cchIn = lstrlenW(pwszSecUrl) + 1;
DWORD cchOut = 0;
LPWSTR pwszTmp = new WCHAR[cchIn];
if (pwszTmp != NULL)
hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_URL, 0, pwszTmp, cchIn, &cchOut, 0);
else
hr = E_OUTOFMEMORY;
// Not enough memory.
if (hr == S_FALSE)
{
// Plug prot claims it needs more memory but asks us for a buffer of a
// smaller size.
TransAssert(cchIn < cchOut);
if (cchIn >= cchOut)
{
hr = E_UNEXPECTED;
}
else
{
cchIn = cchOut;
delete [] pwszTmp;
pwszTmp = new WCHAR[cchIn];
if ( pwszTmp != NULL )
{
hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_URL, 0, pwszTmp, cchIn, &cchOut, 0);
TransAssert(hr != S_FALSE);
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
if (SUCCEEDED(hr))
{
// If for some reason the pluggable protocol just returned back
// the original string, don't go into an infinite loop.
if (0 == StrCmpW(pwszSecUrl, pwszTmp))
{
delete [] pwszTmp;
break;
}
if (bAllocSecUrl)
delete [] pwszSecUrl;
pwszSecUrl = pwszTmp;
bAllocSecUrl = TRUE;
}
else
{
if (hr == INET_E_DEFAULT_ACTION || hr == E_NOTIMPL)
{
// This implies the pluggable protocol just wants us to use the
// base url as the security url.
hr = S_OK;
}
delete [] pwszTmp;
break;
}
}
}
else
{
// Some protocols don't support the IInternetProtocolInfo interface.
// We will do the best we can.
hr = S_OK;
}
// End of Step 1.
// At this point we have the security URL. We are done if the PSUACTION
// indicated we should only be getting the security URL.
if (psuAction == PSU_SECURITY_URL_ONLY)
{
if (SUCCEEDED(hr))
{
// If we didn't allocate memory for pwszSecUrl i.e. it is the same as the
// input string, we have to do that before returning it back.
if (!bAllocSecUrl)
{
*ppwszSecUrl = new WCHAR [(lstrlenW(pwszSecUrl) + 1)];
if (*ppwszSecUrl != NULL)
StrCpyW(*ppwszSecUrl, pwszSecUrl);
else
hr = E_OUTOFMEMORY;
}
else
{
*ppwszSecUrl = pwszSecUrl;
}
}
}
else
{
TransAssert(psuAction == PSU_DEFAULT);
// Step 2.
// If URL after Step 1 is still not well known ask the protocol handler to simplify
// it it is well known call UrlGetPart in shlwapi.
LPWSTR pwszRet = NULL;
if (SUCCEEDED(hr))
{
if (pwszSecUrl == NULL)
{
TransAssert(FALSE); // This has to be due to a bug in Step 1.
pwszSecUrl = (LPWSTR) pwszUrl; // recover as best as we can.
}
// Since Step 2 is just supposed to strip off parts we can safely assume that
// the out string will be smaller than the input string.
DWORD cchIn = lstrlenW(pwszSecUrl) + 1;
DWORD cchOut = 0;
pwszRet = new WCHAR[cchIn];
if (pwszRet == NULL)
{
hr = E_OUTOFMEMORY;
}
else if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwszSecUrl))
{
TransAssert(pOInetSession);
if (pOInetSession)
hr = pOInetSession->ParseUrl(pwszSecUrl, PARSE_SECURITY_DOMAIN, 0, pwszRet, cchIn, &cchOut, 0);
else
hr = INET_E_DEFAULT_ACTION ; // no protocol info ==> use default
TransAssert(hr != S_FALSE); // Should never require more memory
if (hr == INET_E_DEFAULT_ACTION || hr == E_NOTIMPL)
{
StrCpyW(pwszRet, pwszSecUrl);
hr = S_OK;
}
}
else // Known protocol call shlwapi.
{
if (IsHierarchicalUrl(pwszSecUrl))
{
hr = UrlGetPartW(pwszSecUrl, pwszRet, &cchIn, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
TransAssert(hr != E_POINTER);
}
else
{
// Just copy the string from step 1, we can't do any meaningful processing.
hr = INET_E_DEFAULT_ACTION;
}
// If UrlGetPart didn't process it, just pass the original string back.
if (!SUCCEEDED(hr))
{
hr = S_OK;
StrCpyW(pwszRet, pwszSecUrl);
}
}
}
// End of Step 2.
if (bAllocSecUrl)
delete [] pwszSecUrl;
if (SUCCEEDED(hr))
{
TransAssert(pwszRet != NULL);
*ppwszSecUrl = pwszRet;
}
}
PerfDbgLog1(tagTransApi, NULL, "-CoInternetGetSecurityUrl (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetCombineUrl
//
// Synopsis:
//
// Arguments: [pwzBaseUrl] --
// [pwzRelativeUrl] --
// [dwFlags] --
// [pszResult] --
// [cchResult] --
// [dwReserved] --
//
// Returns:
//
// History: 4-13-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetCombineUrl(
LPCWSTR pwzBaseUrl,
LPCWSTR pwzRelativeUrl,
DWORD dwFlags,
LPWSTR pszResult,
DWORD cchResult,
DWORD *pcchResult,
DWORD dwReserved
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetCombineUrl",
"%.80wq, %.80wq, %#x, %#x, %#x, %#x, %#x",
pwzBaseUrl, pwzRelativeUrl, dwFlags, pszResult, cchResult, pcchResult, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetCombineUrl");
COInetSession *pOInetSession = 0;
HRESULT hr = INET_E_DEFAULT_ACTION;
if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzBaseUrl))
{
hr = GetCOInetSession(0, &pOInetSession,0);
if (hr == NOERROR)
{
hr = pOInetSession->CombineUrl(pwzBaseUrl, pwzRelativeUrl, dwFlags, pszResult, cchResult, pcchResult, dwReserved);
pOInetSession->Release();
}
}
if (hr == INET_E_DEFAULT_ACTION)
{
DWORD dwRes = cchResult;
hr = UrlCombineW(pwzBaseUrl, pwzRelativeUrl, pszResult, &dwRes, dwFlags);
*pcchResult = dwRes;
}
PerfDbgLog1(tagTransApi, NULL, "-CoInternetCombineUrl (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetCompareUrl
//
// Synopsis:
//
// Arguments: [pwzUrl1] --
// [pwzUrl2] --
// [dwFlags] --
//
// Returns:
//
// History: 4-13-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetCompareUrl(
LPCWSTR pwzUrl1,
LPCWSTR pwzUrl2,
DWORD dwFlags
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetCompareUrl",
"%.80wq, %.80wq, %#x",
pwzUrl1, pwzUrl2, dwFlags
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetCompareUrl");
COInetSession *pOInetSession = 0;
HRESULT hr = INET_E_DEFAULT_ACTION;
if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl1))
{
hr = GetCOInetSession(0, &pOInetSession,0);
if (hr == NOERROR)
{
hr = pOInetSession->CompareUrl(pwzUrl1, pwzUrl2, dwFlags);
pOInetSession->Release();
}
}
if (hr == INET_E_DEFAULT_ACTION)
{
int iRes = UrlCompareW(pwzUrl1, pwzUrl2, dwFlags & CF_INGNORE_SLASH);
if (iRes == 0)
{
hr = S_OK;
}
else
{
hr = S_FALSE;
}
}
PerfDbgLog1(tagTransApi, NULL, "-CoInternetCompareUrl (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetQueryInfo
//
// Synopsis:
//
// Arguments: [pwzUrl] --
// [dwOptions] --
// [pvBuffer] --
// [cbBuffer] --
// [pcbBuffer] --
// [dwReserved] --
//
// Returns:
//
// History: 4-14-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetQueryInfo(
LPCWSTR pwzUrl,
QUERYOPTION QueryOption,
DWORD dwQueryFlags,
LPVOID pvBuffer,
DWORD cbBuffer,
DWORD *pcbBuffer,
DWORD dwReserved
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetQueryInfo",
"%.80wq, %#x, %#x, %#x, %#x, %#x, %#x",
pwzUrl, QueryOption, dwQueryFlags, pvBuffer, cbBuffer, pcbBuffer, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetQueryInfo");
COInetSession *pOInetSession = 0;
HRESULT hr = INET_E_DEFAULT_ACTION;
if (!g_bShortcircuitKnownProtocols || !IsKnownProtocol(pwzUrl))
{
hr = GetCOInetSession(0, &pOInetSession,0);
if (hr == NOERROR)
{
hr = pOInetSession->QueryInfo(pwzUrl, QueryOption, dwQueryFlags, pvBuffer, cbBuffer, pcbBuffer, dwReserved);
pOInetSession->Release();
}
}
if (hr == INET_E_DEFAULT_ACTION)
{
switch (QueryOption)
{
case QUERY_USES_NETWORK:
case QUERY_USES_CACHE:
{
if (!pvBuffer || cbBuffer < sizeof(DWORD))
{
DEBUG_LEAVE_API(E_FAIL);
return E_FAIL;
}
if (pcbBuffer)
{
*pcbBuffer = sizeof(DWORD);
}
switch (GetUrlScheme(pwzUrl))
{
case URL_SCHEME_FILE:
case URL_SCHEME_NEWS:
case URL_SCHEME_NNTP:
case URL_SCHEME_MK:
case URL_SCHEME_SHELL:
case URL_SCHEME_SNEWS:
case URL_SCHEME_LOCAL:
*((DWORD *)pvBuffer) = FALSE;
DEBUG_LEAVE_API(S_OK);
return S_OK;
case URL_SCHEME_FTP:
case URL_SCHEME_HTTP:
case URL_SCHEME_GOPHER:
case URL_SCHEME_TELNET:
case URL_SCHEME_WAIS:
case URL_SCHEME_HTTPS:
*((DWORD *)pvBuffer) = TRUE;
DEBUG_LEAVE_API(S_OK);
return S_OK;
default:
DEBUG_LEAVE_API(E_FAIL);
return E_FAIL;
}
}
break;
case QUERY_IS_CACHED:
case QUERY_IS_INSTALLEDENTRY:
case QUERY_IS_CACHED_OR_MAPPED:
{
char szUrl[MAX_URL_SIZE];
DWORD dwFlags = 0;
if(QueryOption == QUERY_IS_INSTALLEDENTRY)
{
dwFlags = INTERNET_CACHE_FLAG_INSTALLED_ENTRY;
}
else if(QueryOption == QUERY_IS_CACHED_OR_MAPPED)
{
dwFlags = INTERNET_CACHE_FLAG_ENTRY_OR_MAPPING;
}
// Otherwise let the flags remain as 0
if (!pvBuffer || cbBuffer < sizeof(DWORD))
{
DEBUG_LEAVE_API(E_FAIL);
return E_FAIL;
}
if (pcbBuffer)
{
*pcbBuffer = sizeof(DWORD);
}
W2A(pwzUrl, szUrl, MAX_URL_SIZE);
char *pchLoc = StrChr(szUrl, TEXT('#'));
if (pchLoc)
*pchLoc = TEXT('\0');
*((DWORD *)pvBuffer) = GetUrlCacheEntryInfoEx(szUrl, NULL, NULL, NULL, NULL, NULL, dwFlags);
DEBUG_LEAVE_API(S_OK);
return S_OK;
}
break;
case QUERY_CAN_NAVIGATE:
{
//Bug#107130 - If we couldn't find the NEWS protocol, or it refused to answer this query,
// trident assumes that it CAN navigate, and leads to above bug.
// If we couldn't load this protocol, or it delegated to us, we now give Trident what they want.
if (URL_SCHEME_NEWS == GetUrlScheme(pwzUrl))
{
if (!pvBuffer || cbBuffer < sizeof(DWORD))
{
DEBUG_LEAVE_API(E_FAIL);
return E_FAIL;
}
if (pcbBuffer)
{
*pcbBuffer = sizeof(DWORD);
}
*((DWORD *)pvBuffer) = FALSE;
DEBUG_LEAVE_API(S_OK);
return S_OK;
}
}
break;
default:
// do not know what do to
hr = E_FAIL;
}
}
PerfDbgLog1(tagTransApi, NULL, "-CoInternetQueryInfo (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetGetProtocolFlags
//
// Synopsis:
//
// Arguments: [pwzUrl] --
// [pdwFlags] --
// [dwReserved] --
//
// Returns:
//
// History: 4-14-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetGetProtocolFlags(
LPCWSTR pwzUrl,
DWORD *pdwFlags,
DWORD dwReserved
)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetGetProtocolFlags",
"%.80wq, %#x, %#x",
pwzUrl, pdwFlags, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetGetProtocolFlags");
COInetSession *pOInetSession = 0;
HRESULT hr = E_NOTIMPL;
PerfDbgLog1(tagTransApi, NULL, "-CoInternetGetProtocolFlags (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetCreateSecurityManager
//
// Synopsis:
//
// Arguments: [pSP] --
// [pSM] --
// [dwReserved] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetCreateSecurityManager(IServiceProvider *pSP, IInternetSecurityManager **ppSM, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetCreateSecurityManager",
"%#x, %#x, %#x",
pSP, ppSM, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetCreateUrlSecurityManager");
HRESULT hr = NOERROR;
hr = InternetCreateSecurityManager(0, IID_IInternetSecurityManager, (void **)ppSM, dwReserved);
PerfDbgLog1(tagTransApi, NULL, "-CoInternetCreateUrlSecurityManager (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: CoInternetCreateZoneManager
//
// Synopsis:
//
// Arguments: [pSP] --
// [ppZM] --
// [dwReserved] --
//
// Returns:
//
// History: 4-28-1997 JohannP (Johann Posch) Created
//
// Notes:
//
//----------------------------------------------------------------------------
STDAPI CoInternetCreateZoneManager(IServiceProvider *pSP, IInternetZoneManager **ppZM, DWORD dwReserved)
{
DEBUG_ENTER_API((DBG_API,
Hresult,
"CoInternetCreateZoneManager",
"%#x, %#x, %#x",
pSP, ppZM, dwReserved
));
PerfDbgLog(tagTransApi, NULL, "+CoInternetCreateUrlZoneManager");
HRESULT hr;
hr = InternetCreateZoneManager(0, IID_IInternetZoneManager, (void **) ppZM, dwReserved);
PerfDbgLog1(tagTransApi, NULL, "-CoInternetCreateUrlZoneManager (hr:%lx)", hr);
DEBUG_LEAVE_API(hr);
return hr;
}
BOOL PDFNeedProgressiveDownload()
{
DEBUG_ENTER((DBG_TRANSDAT,
Bool,
"PDFNeedProgressiveDownload",
NULL
));
HKEY hClsRegEntry;
CHAR szInProc[CLSIDSTR_MAX + 64];
CHAR szPath[MAX_PATH];
long lSize;
BOOL fRet = TRUE;
BYTE* pVerBuffer = NULL;
DWORD cbFileVersionBufSize;
DWORD dwTemp;
unsigned uiLength = 0;
VS_FIXEDFILEINFO *lpVSFixedFileInfo;
strcpy(szInProc,
"CLSID\\{CA8A9780-280D-11CF-A24D-444553540000}\\InProcServer32");
if( ERROR_SUCCESS != RegOpenKey(
HKEY_CLASSES_ROOT, szInProc, &hClsRegEntry) )
{
goto Exit;
}
// now we are at HKCR\CLSID\xxx-yyyy\InProcServer32
// we need to get the path to the ocx
lSize = MAX_PATH;
if( ERROR_SUCCESS != RegQueryValue(
hClsRegEntry, NULL, szPath, &lSize) )
{
RegCloseKey(hClsRegEntry);
goto Exit;
}
// done with key
RegCloseKey(hClsRegEntry);
// we have the path now
if((cbFileVersionBufSize = GetFileVersionInfoSize( szPath, &dwTemp)) == 0 )
{
goto Exit;
}
pVerBuffer = new BYTE[cbFileVersionBufSize];
if( !pVerBuffer )
{
goto Exit;
}
if( !GetFileVersionInfo(szPath, 0, cbFileVersionBufSize, pVerBuffer) )
{
goto Exit;
}
if( !VerQueryValue(
pVerBuffer, TEXT("\\"),(LPVOID*)&lpVSFixedFileInfo, &uiLength) )
{
goto Exit;
}
if( lpVSFixedFileInfo->dwFileVersionMS == 0x00010003 &&
lpVSFixedFileInfo->dwFileVersionLS < 170 )
{
// this is 3.0 or 3.01, we should disable progressive download
fRet = FALSE;
}
Exit:
if( pVerBuffer != NULL)
delete [] pVerBuffer;
DEBUG_LEAVE(fRet);
return fRet;
}