|
|
//+---------------------------------------------------------------------------
//
// 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; }
|