|
|
//+-------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1998 - 1999 Microsoft Corporation. All Rights Reserved.
//
// PROGRAM: htmlprop.cxx
//
// PURPOSE: Sits on the Indexing Service HTML filter to translate string
// meta properties into specified data types.
//
// PLATFORM: Windows 2000
//
//--------------------------------------------------------------------------
#define UNICODE
#include <stdio.h>
#include <wchar.h>
#include <windows.h>
#include <oledb.h>
#include <cmdtree.h>
#include <filterr.h>
#include <filter.h>
#include "htmlprop.hxx"
#include "filtreg.hxx"
// The typid of the html filter
CLSID TYPID_HtmlPropIFilter = { 0xc8e2ab80, 0xa1db, 0x11d1, { 0xa8, 0xfb, 0x00, 0xe0, 0x98, 0x00, 0x6e, 0xd3 } };
// The CLSID for the html property filter
CLSID CLSID_HtmlPropIFilter = { 0xf4309e80, 0xa1db, 0x11d1, { 0xa8, 0xfb, 0x00, 0xe0, 0x98, 0x00, 0x6e, 0xd3 } };
// Class of the html property filter
CLSID CLSID_HtmlPropClass = { 0x4cbd1020, 0xa1db, 0x11d1, { 0xa8, 0xfb, 0x00, 0xe0, 0x98, 0x00, 0x6e, 0xd3 } };
// The built-in html filter
CLSID CLSID_HtmlIFilter = { 0xe0ca5340, 0x4534, 0x11cf, { 0xb9, 0x52, 0x00, 0xaa, 0x00, 0x51, 0xfe, 0x20 } };
// The guid for html meta properties
CLSID CLSID_MetaProperty = { 0xd1b5d3f0, 0xc0b3, 0x11cf, { 0x9a, 0x92, 0x00, 0xa0, 0xc9, 0x08, 0xdb, 0xf1 } };
// The guid for html meta properties in string form
const WCHAR * pwcMetaProperty = L"d1b5d3f0-c0b3-11cf-9a92-00a0c908dbf1";
struct SPropertyEntry { WCHAR awcName[cwcMaxName]; // name of the meta property
DBTYPE dbType; // data type of property
};
const SPropertyEntry aTypeEntries[] = { { L"DBTYPE_I1", DBTYPE_I1 }, // 0: signed char
{ L"DBTYPE_UI1", DBTYPE_UI1 }, // 1: unsigned char
{ L"DBTYPE_I2", DBTYPE_I2 }, // 2: 2 byte signed int
{ L"DBTYPE_UI2", DBTYPE_UI2 }, // 3: 2 byte unsigned int
{ L"DBTYPE_I4", DBTYPE_I4 }, // 4: 4 byte signed int
{ L"DBTYPE_UI4", DBTYPE_UI4 }, // 5: 4 byte unsigned int
{ L"DBTYPE_I8", DBTYPE_I8 }, // 6: 8 byte signed int
{ L"DBTYPE_UI8", DBTYPE_UI8 }, // 7: 8 byte unsigned int
{ L"DBTYPE_R4", DBTYPE_R4 }, // 8: 4 byte float
{ L"DBTYPE_R8", DBTYPE_R8 }, // 9: 8 byte float
{ L"DBTYPE_BOOL", DBTYPE_BOOL }, // 12: BOOL (true=-1, false=0)
{ L"DBTYPE_WSTR", DBTYPE_WSTR }, // 14: wide null terminated string
{ L"VT_FILETIME", VT_FILETIME } // 19: I8 filetime
};
const ULONG cTypeEntries = sizeof aTypeEntries / sizeof aTypeEntries[0];
const WCHAR * pwcHTMLPropertyFile = L"htmlprop.ini";
const ULONG maxEntries = 500; SPropertyEntry g_aEntries[ maxEntries ]; ULONG g_cEntries = 0; // count of entries in g_aEntries
long g_cInstances = 0; HMODULE g_hHtmlDll = 0; // module handle for nlhtml.dll
// htmlfilt.dll for IS 1.x and nlhtml.dll for IS 2.x
const WCHAR * pwcHTMLFilter = L"nlhtml.dll";
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::HtmlPropIFilter
//
// Synopsis: Constructor
//
//--------------------------------------------------------------------------
HtmlPropIFilter::HtmlPropIFilter() : _pHtmlFilter( 0 ), _pPersistFile( 0 ), _lRefs( 1 ) { InterlockedIncrement( &g_cInstances ); } //HtmlPropIFilter
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::~HtmlPropIFilter
//
// Synopsis: Destructor
//
//--------------------------------------------------------------------------
HtmlPropIFilter::~HtmlPropIFilter() { InterlockedDecrement( &g_cInstances );
if ( _pHtmlFilter ) _pHtmlFilter->Release();
if ( _pPersistFile ) _pPersistFile->Release(); } //~HtmlPropIFilter
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::QueryInterface
//
// Synopsis: Rebind to other interface
//
// Arguments: [riid] -- IID of new interface
// [ppvObject] -- New interface * returned here
//
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::QueryInterface( REFIID riid, void ** ppvObject) { if ( IID_IFilter == riid ) *ppvObject = (IFilter *)this; else if ( IID_IPersist == riid ) *ppvObject = (IPersist *)(IPersistFile *)this; else if ( IID_IPersistFile == riid ) *ppvObject = (IPersistFile *)this; else if ( IID_IUnknown == riid ) *ppvObject = (IUnknown *)(IPersist *)(IPersistFile *)this; else { *ppvObject = 0; return E_NOINTERFACE; }
AddRef(); return S_OK; } //QueryInterface
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::AddRef
//
// Synopsis: Increments refcount
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE HtmlPropIFilter::AddRef() { return InterlockedIncrement( &_lRefs ); } //AddRef
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::Release
//
// Synopsis: Decrement refcount. Delete if necessary.
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE HtmlPropIFilter::Release() { long lTmp = InterlockedDecrement( &_lRefs );
if ( 0 == lTmp ) delete this; return lTmp; } //Release
//+-------------------------------------------------------------------------
//
// Member: HtmlPropIFilter::Init, public
//
// Synopsis: Initializes instance of property filter
//
// Arguments: [grfFlags] -- flags for filter behavior
// [cAttributes] -- number of attributes in array aAttributes
// [aAttributes] -- array of attributes
// [pFlags] -- flags
//
//----------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::Init( ULONG grfFlags, ULONG cAttributes, FULLPROPSPEC const * aAttributes, ULONG * pFlags ) { return _pHtmlFilter->Init( grfFlags, cAttributes, aAttributes, pFlags ); } //Init
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::GetChunk
//
// Synopsis: Gets the next chunk
//
// Arguments: [pStat] -- Chunk info
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::GetChunk( STAT_CHUNK * pStat ) { SCODE sc = _pHtmlFilter->GetChunk( pStat );
// If we got a chunk, it's a value chunk, and it's a meta property with
// a string identifier, store away the name so it's available when the
// value is retrieved.
if ( ( SUCCEEDED( sc ) ) && ( 0 != ( pStat->flags & CHUNK_VALUE ) ) && ( PRSPEC_LPWSTR == pStat->attribute.psProperty.ulKind ) && ( CLSID_MetaProperty == pStat->attribute.guidPropSet ) && ( 0 != pStat->attribute.psProperty.lpwstr ) && ( wcslen( pStat->attribute.psProperty.lpwstr ) < cwcMaxName ) ) { _fMetaProperty = TRUE; wcscpy( _awcName, pStat->attribute.psProperty.lpwstr ); } else { _fMetaProperty = FALSE; }
return sc; } //GetChunk
//+-------------------------------------------------------------------------
//
// Function: ParseDateTime
//
// Synopsis: Parse the string and return a date/time
// n.b. If the date is ill-formed and this function returns
// an error code, the file will be unfiltered, and can be
// found by using the unfiltered admin query.
// The date parsing is very strict.
// Times are in any time zone you like, but .htx will interpret
// all dates as GMT. You can always use .asp script to munge
// dates as you like.
//
// Arguments: [pwcDate] -- String form of the date/time
// [ft] -- Returns the date/time
//
//--------------------------------------------------------------------------
SCODE ParseDateTime( WCHAR * pwcDate, FILETIME & ft ) { SYSTEMTIME stValue = { 0, 0, 0, 0, 0, 0, 0, 0 };
// Some day add more flexible date formats!
int cItems = swscanf( pwcDate, L"%4hd/%2hd/%2hd %2hd:%2hd:%2hd:%3hd", &stValue.wYear, &stValue.wMonth, &stValue.wDay, &stValue.wHour, &stValue.wMinute, &stValue.wSecond, &stValue.wMilliseconds );
if ( 1 == cItems ) cItems = swscanf( pwcDate, L"%4hd-%2hd-%2hd %2hd:%2hd:%2hd:%3hd", &stValue.wYear, &stValue.wMonth, &stValue.wDay, &stValue.wHour, &stValue.wMinute, &stValue.wSecond, &stValue.wMilliseconds );
if( cItems != 3 && cItems != 6 && cItems != 7) return E_INVALIDARG;
// Make a sensible split for Year 2000
if (stValue.wYear < 30) stValue.wYear += 2000; else if (stValue.wYear < 100) stValue.wYear += 1900;
if( !SystemTimeToFileTime( &stValue, &ft ) ) return HRESULT_FROM_WIN32( GetLastError() );
return S_OK; } //ParseDateTime
//+-------------------------------------------------------------------------
//
// Function: Translate
//
// Synopsis: Translates the string property value to the given type
//
// Arguments: [v] -- The variant to translate
// [dbType] -- The resulting data type
//
//--------------------------------------------------------------------------
SCODE Translate( PROPVARIANT & v, DBTYPE dbType ) { PROPVARIANT varCopy = v; BOOL fChange = TRUE; SCODE sc = S_OK;
WCHAR *p = v.pwszVal;
// The source must be a string variant
if ( 0 == p || VT_LPWSTR != v.vt ) return S_OK;
v.vt = dbType;
// Eat leading white space
while ( ' ' == *p ) p++;
int base = 10;
// Is this a hex number?
if ( '0' == *p && ( 'x' == *(p+1) || 'X' == *(p+1) ) ) { p += 2; base = 16; }
WCHAR * pwc;
// DBTYPE_I1 isn't an official OLE property type, so it isn't supported.
//
// Note: range checking could be added and a failure code could be
// returned if the check failed. That would put the file in the
// unfiltered list.
switch ( dbType ) { case DBTYPE_UI1 : v.bVal = (BYTE) wcstoul( v.pwszVal, &pwc, base ); break; case DBTYPE_I2 : v.iVal = (SHORT) wcstol( v.pwszVal, &pwc, base ); break; case DBTYPE_UI2 : v.uiVal = (USHORT) wcstoul( v.pwszVal, &pwc, base ); break; case DBTYPE_I4 : v.lVal = (LONG) wcstol( v.pwszVal, &pwc, base ); break; case DBTYPE_UI4 : v.ulVal = (ULONG) wcstoul( v.pwszVal, &pwc, base ); break; case DBTYPE_I8 : swscanf( v.pwszVal, L"%I64d", &v.fltVal ); break; case DBTYPE_UI8 : swscanf( v.pwszVal, L"%I64u", &v.fltVal ); break; case DBTYPE_R4 : swscanf( v.pwszVal, L"%f", &v.fltVal ); break; case DBTYPE_R8 : swscanf( v.pwszVal, L"%lf", &v.dblVal ); break; case DBTYPE_BOOL :
// If the first character is t or 1, assume VARIANT_TRUE
if ( 't' == *v.pwszVal || 'T' == *v.pwszVal || '1' == *v.pwszVal ) v.boolVal = VARIANT_TRUE; else v.boolVal = VARIANT_FALSE; break; case VT_FILETIME : sc = ParseDateTime( p, v.filetime ); break; default :
// leave the property as it was
fChange = FALSE; v.vt = varCopy.vt; break; }
// Free the memory for the (now converted) string value
if ( fChange ) PropVariantClear( &varCopy );
return sc; } //Translate
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::GetValue
//
// Synopsis: Retrieves the current value
//
// Arguments: [ppPropValue] -- Where the value is stored
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::GetValue( PROPVARIANT ** ppPropValue ) { SCODE sc = _pHtmlFilter->GetValue( ppPropValue );
// Is this a value that must be translated?
if ( SUCCEEDED( sc ) && _fMetaProperty && 0 != *ppPropValue ) { // lookup the datatype of the translation based on property name
for ( ULONG i = 0; i < g_cEntries; i++ ) { if ( !_wcsicmp( g_aEntries[i].awcName, _awcName ) ) { // found it, so translate it
sc = Translate( **ppPropValue, g_aEntries[i].dbType ); break; } } }
return sc; } //GetValue
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::GetText
//
// Synopsis: Gets text from the filter
//
// Arguments: [pcwcBuffer] -- Returns the # of WCHARs returned
// [awcBuffer] -- Where text is written
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::GetText( ULONG * pcwcBuffer, WCHAR * awcBuffer ) { return _pHtmlFilter->GetText( pcwcBuffer, awcBuffer ); } //GetText
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::BindRegion
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::BindRegion( FILTERREGION origPos, REFIID riid, void ** ppunk ) { return _pHtmlFilter->BindRegion( origPos, riid, ppunk ); } //BindRegion
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::GetClassID
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::GetClassID( CLSID * pClassID ) { *pClassID = CLSID_HtmlPropIFilter; return S_OK; } //GetClassID
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::IsDirty
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::IsDirty() { return S_FALSE; } //IsDirty
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::Load
//
// Synopsis: Loads the file for the filter
//
// Arguments: [pszFileName] -- Name of the file
// [dwMode] -- Mode of the load
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::Load( LPCWSTR pszFileName, DWORD dwMode) { //
// Get html filter class object and class factory
//
IClassFactory * pcf; SCODE sc = E_FAIL;
if ( 0 != g_hHtmlDll ) { LPFNGETCLASSOBJECT pfn = (LPFNGETCLASSOBJECT)GetProcAddress( g_hHtmlDll, "DllGetClassObject" );
if ( 0 != pfn ) sc = (pfn)( CLSID_HtmlIFilter, IID_IClassFactory, (void **)&pcf ); }
if ( SUCCEEDED(sc) ) { // Get an html filter
sc = pcf->CreateInstance( 0, IID_IFilter, (void **)&_pHtmlFilter ); pcf->Release();
if ( SUCCEEDED(sc) ) { // Load the file
sc = _pHtmlFilter->QueryInterface( IID_IPersistFile, (void **) &_pPersistFile );
if ( SUCCEEDED(sc) ) { sc = _pPersistFile->Load( pszFileName, dwMode ); } else { _pHtmlFilter->Release(); _pHtmlFilter = 0; } } }
return sc; } //Load
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::Save
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::Save( LPCWSTR pszFileName, BOOL fRemember ) { return E_FAIL; } //Save
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::SaveCompleted
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::SaveCompleted( LPCWSTR pszFileName ) { return E_FAIL; } //SaveCompleted
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilter::GetcurFile
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilter::GetCurFile( LPWSTR * ppszFileName ) { return _pPersistFile->GetCurFile( ppszFileName ); } //GetCurFile
//+-------------------------------------------------------------------------
//
// Function: ParsePropertyFile
//
// Synopsis: Parses a property file and stores datatypes for html meta
// properties. Property files are in .idq format, with a
// [Names] section.
//
//--------------------------------------------------------------------------
void ParsePropertyFile() { // already parsed the file?
if ( g_cEntries > 0 ) return;
// open the property file in the system32 directory
WCHAR awcFile[ MAX_PATH ]; GetSystemDirectory( awcFile, sizeof awcFile / sizeof WCHAR );
wcscat( awcFile, L"\\" ); wcscat( awcFile, pwcHTMLPropertyFile );
FILE *file = _wfopen( awcFile, L"r" );
if ( 0 != file ) { WCHAR awc[ 500 ]; BOOL fNames = FALSE;
// for each line of the file
while ( fgetws( awc, sizeof awc, file ) ) { int cwc = wcslen( awc ); if ( 0 == cwc ) continue;
// trim off trailing newline
if ( awc[ cwc - 1 ] == '\n' ) { cwc--; awc[cwc] = 0; }
// is this a section line?
if ( '[' == awc[0] ) { fNames = !_wcsicmp( L"[names]", awc ); } else if ( ( '#' != awc[0] ) && fNames ) { // parse the data type
WCHAR *pwcType = wcschr( awc, L'(' );
if ( 0 != pwcType ) { pwcType++; while ( ' ' == *pwcType ) pwcType++;
WCHAR *pwcX = wcstok( pwcType, L", )" );
if ( 0 != pwcType ) { // lookup the type in the list of types
for ( ULONG i = 0; i < cTypeEntries; i++ ) { if ( !_wcsicmp( aTypeEntries[i].awcName, pwcType ) ) break; }
// got the type, so find the guid
if ( i < cTypeEntries ) { // find the property guid
pwcType += 1 + wcslen( pwcType );
WCHAR *pwcName = wcschr( pwcType, '=' );
if ( pwcName ) { pwcName++; while ( ' ' == *pwcName ) pwcName++;
// is this the html guid?
if ( !_wcsnicmp( pwcName, pwcMetaProperty, wcslen( pwcMetaProperty ) ) ) { // find the property name
pwcName = wcschr( pwcName, ' ' ); if ( pwcName ) { // skip white space
while ( ' ' == *pwcName ) pwcName++;
// got it -- save it away if it fits
if ( ( wcslen( pwcName ) < cwcMaxName ) && ( g_cEntries < maxEntries ) ) { wcscpy( g_aEntries[g_cEntries].awcName, pwcName ); g_aEntries[g_cEntries++].dbType = aTypeEntries[i].dbType; } } } } } } } } }
fclose( file ); } } //ParsePropertyFile
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::HtmlPropIFilterCF
//
// Synopsis: HTML Property IFilter class factory constructor
//
//--------------------------------------------------------------------------
HtmlPropIFilterCF::HtmlPropIFilterCF() { _lRefs = 1;
long c = InterlockedIncrement( &g_cInstances );
if ( 0 == g_hHtmlDll && 1 == c ) { // load the html filter dll
g_hHtmlDll = LoadLibrary( pwcHTMLFilter );
// load the property information
ParsePropertyFile(); } } //HtmlPropIFilterCF
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::~HtmlPropIFilterCF
//
// Synopsis: HTML IFilter class factory constructor
//
//--------------------------------------------------------------------------
HtmlPropIFilterCF::~HtmlPropIFilterCF() { long c = InterlockedDecrement( &g_cInstances );
if ( 0 != g_hHtmlDll && 0 == c ) { FreeLibrary( g_hHtmlDll ); g_hHtmlDll = 0; } } //~HtmlPropIFilterCF
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::QueryInterface
//
// Synopsis: Rebind to other interface
//
// Arguments: [riid] -- IID of new interface
// [ppvObject] -- New interface * returned here
//
// Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilterCF::QueryInterface( REFIID riid, void ** ppvObject ) { if ( IID_IClassFactory == riid ) *ppvObject = (IUnknown *) (IClassFactory *) this; else if ( IID_IUnknown == riid ) *ppvObject = (IUnknown *) (IPersist *) this; else { *ppvObject = 0; return E_NOINTERFACE; }
AddRef(); return S_OK; } //QueryInterface
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::AddRef
//
// Synopsis: Increments refcount
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE HtmlPropIFilterCF::AddRef() { return InterlockedIncrement( &_lRefs ); } //AddRef
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::Release
//
// Synopsis: Decrement refcount. Delete if necessary.
//
//--------------------------------------------------------------------------
ULONG STDMETHODCALLTYPE HtmlPropIFilterCF::Release() { long lTmp = InterlockedDecrement( &_lRefs );
if ( 0 == lTmp ) delete this;
return lTmp; } //Release
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::CreateInstance
//
// Synopsis: Creates new HtmlPropIFilter object
//
// Arguments: [pUnkOuter] -- 'Outer' IUnknown
// [riid] -- Interface to bind
// [ppvObject] -- Interface returned here
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilterCF::CreateInstance( IUnknown * pUnkOuter, REFIID riid, void * * ppvObject ) { *ppvObject = 0;
HtmlPropIFilter * pFilter = new HtmlPropIFilter;
if ( 0 == pFilter ) return E_OUTOFMEMORY;
SCODE sc = pFilter->QueryInterface( riid , ppvObject );
pFilter->Release();
return sc; } //CreateInstance
//+-------------------------------------------------------------------------
//
// Method: HtmlPropIFilterCF::LockServer
//
// Synopsis: Force class factory to remain loaded
//
// Arguments: [fLock] -- TRUE if locking, FALSE if unlocking
//
// Returns: S_OK
//
//--------------------------------------------------------------------------
SCODE STDMETHODCALLTYPE HtmlPropIFilterCF::LockServer(BOOL fLock) { if(fLock) InterlockedIncrement( &g_cInstances ); else InterlockedDecrement( &g_cInstances );
return S_OK; } //LockServer
//+-------------------------------------------------------------------------
//
// Function: DllGetClassObject
//
// Synopsis: Ole DLL load class routine
//
// Arguments: [cid] -- Class to load
// [iid] -- Interface to bind to on class object
// [ppvObj] -- Interface pointer returned here
//
// Returns: HTML Property filter class factory
//
//--------------------------------------------------------------------------
extern "C" SCODE STDMETHODCALLTYPE DllGetClassObject( REFCLSID cid, REFIID iid, void ** ppvObj ) { IUnknown * pUnk = 0;
if ( CLSID_HtmlPropIFilter == cid || CLSID_HtmlPropClass == cid ) { pUnk = new HtmlPropIFilterCF;
if ( 0 == pUnk ) return E_OUTOFMEMORY; } else { *ppvObj = 0; return E_NOINTERFACE; }
SCODE sc = pUnk->QueryInterface( iid, ppvObj );
pUnk->Release();
return sc; } //DllGetClassObject
//+-------------------------------------------------------------------------
//
// Method: DllCanUnloadNow
//
// Synopsis: Notifies DLL to unload (cleanup global resources)
//
// Returns: S_OK if it is acceptable for caller to unload DLL.
//
//--------------------------------------------------------------------------
extern "C" SCODE STDMETHODCALLTYPE DllCanUnloadNow( void ) { if ( 0 == g_cInstances ) return S_OK; else return S_FALSE; } //DllCanUnloadNow
SClassEntry const aHtmlPropClasses[] = { { L".hhc", L"hhcfile", L"HHC file", L"{7f73b8f6-c19c-11d0-aa66-00c04fc2eddc}", L"HHC file" }, { L".htm", L"htmlfile", L"HTML file", L"{25336920-03f9-11cf-8fd0-00aa00686f13}", L"HTML file" }, { L".html", L"htmlfile", L"HTML file", L"{25336920-03f9-11cf-8fd0-00aa00686f13}", L"HTML file" }, { L".htx", L"htmlfile", L"HTML file", L"{25336920-03f9-11cf-8fd0-00aa00686f13}", L"HTML file" }, { L".stm", L"htmlfile", L"HTML file", L"{25336920-03f9-11cf-8fd0-00aa00686f13}", L"HTML file" }, { L".htw", L"htmlfile", L"HTML file", L"{25336920-03f9-11cf-8fd0-00aa00686f13}", L"HTML file" }, { L".asp", L"asp_auto_file", L"ASP auto file", L"{bd70c020-2d24-11d0-9110-00004c752752}", L"ASP auto file" }, };
SHandlerEntry const HtmlPropHandler = { L"{c694d910-a439-11d1-a903-00e098006ed3}", L"html property persistent handler", L"{f4309e80-a1db-11d1-a8fb-00e098006ed3}", };
SFilterEntry const HtmlPropFilter = { L"{f4309e80-a1db-11d1-a8fb-00e098006ed3}", L"html property filter", L"HtmlProp.dll", L"Both" };
DEFINE_DLLREGISTERFILTER( HtmlPropHandler, HtmlPropFilter, aHtmlPropClasses )
|