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