2025-04-27 07:49:33 -04:00

2375 lines
44 KiB
C++

// req.cpp : Implementation of Creq
#include "stdafx.h"
#include "meta2.h"
#include "req.h"
#include "metakey.h"
#include "name.h"
#include "nntpmeta.h"
#include "smtpinet.h"
#include <stdio.h>
#include "search.h"
#include "search_i.c"
//
// Prog ID or the query object
//
#define QUERY_OBJ_ID L"qry.qry.1"
//
// some compile time constants
//
#define REQDB_ROOT L"/LM/NNTPSVC/1/REQDB" // database root key
#define REQDB_ROOT_PARENT L"/LM/NNTPSVC/1" // nntpsvc root key
#define REQDB_ROOT_NAME L"REQDB" // database's root key name
#define DB_ERROR E_FAIL // set to m_dwErrorCode for unspecified errors
// that has no system error codes
#define MAIL_KEY L"/LM/SMTPSVC/1/PARAMETERS" // smtpsvc key
#define MAIL_ROOT L"/LM/SMTPSVC/1" // smtpsvc root key
#define NEWS_ROOT L"/LM/NNTPSVC/1" // nntpsvc root key
/////////////////////////////////////////////////////////////////////////////
// Creq
STDMETHODIMP Creq::OnStartPage (IUnknown* pUnk)
{
if(!pUnk)
return E_POINTER;
CComPtr<IScriptingContext> spContext;
HRESULT hr;
// Get the IScriptingContext Interface
hr = pUnk->QueryInterface(IID_IScriptingContext, (void **)&spContext);
if(FAILED(hr))
return hr;
// Get Request Object Pointer
hr = spContext->get_Request(&m_piRequest);
if(FAILED(hr))
{
spContext.Release();
return hr;
}
// Get Response Object Pointer
hr = spContext->get_Response(&m_piResponse);
if(FAILED(hr))
{
m_piRequest.Release();
return hr;
}
// Get Server Object Pointer
hr = spContext->get_Server(&m_piServer);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
return hr;
}
// Get Session Object Pointer
hr = spContext->get_Session(&m_piSession);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
return hr;
}
// Get Application Object Pointer
hr = spContext->get_Application(&m_piApplication);
if(FAILED(hr))
{
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
m_piSession.Release();
return hr;
}
m_bOnStartPageCalled = TRUE;
return S_OK;
}
STDMETHODIMP Creq::OnEndPage ()
{
m_bOnStartPageCalled = FALSE;
// Release all interfaces
m_piRequest.Release();
m_piResponse.Release();
m_piServer.Release();
m_piSession.Release();
m_piApplication.Release();
return S_OK;
}
BOOL
Creq::CreateKey( LPWSTR wszKeyName,
BOOL fGuidGiven )
/*++
Routine Description:
Create a meta base key. A GUID string is assigned to be key name.
Arguments:
wszKeyName - OUT The key name that is assigned by guid, if NULL is
passed, then it's not filled with that key name.
fGuidGiven - IN if to use the given guid
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::CreateKey");
if ( m_fInitOk == FALSE || m_pMK == NULL ) {
m_dwErrorCode = DB_ERROR;
ErrorTrace(0, "Create key before open");
return FALSE;
}
LPWSTR wszGuid;
HRESULT hResult;
//
// if the guid is given, don't bother to generate one
//
if ( fGuidGiven ) {
wszGuid = wszKeyName;
goto after_gen_guid;
}
// Prepare for the Guid
//
if ( ! GenGUID( &wszGuid ) ) {
DebugTrace(0, "false");
return FALSE;
}
//
// fill in the key name
//
if ( wszKeyName )
wcscpy( wszKeyName, wszGuid );
after_gen_guid:
//
// Open root key
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT,
METADATA_PERMISSION_WRITE );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Can't open metabase. Error code: %x", hResult );
return FALSE;
}
//
// Create the key
//
hResult = m_pMK->CreateChild( wszGuid );
if ( FAILED( hResult) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Create key fail. Error: %x", m_dwErrorCode);
return FALSE;
}
//
// close the root key
//
//m_pMK->Save();
m_pMK->Close();
//
// Create key also opens that key at last, as will be a convenient
// feature for users
//
if ( !OpenKey( wszGuid, FALSE ) ) {
ErrorTrace(0, "Open after create fail");
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::OpenKey( LPWSTR wszGuid,
BOOL fReadOnly )
/*++
Routine Description:
Open a request key. The open automatically closes what is opened
previously. This is done in function Open.
Arguments:
wszGuid - IN Key name, which is a guid
fReadOnly - IN True - open with read permission, FALSE - open with write
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::OpenKey");
WCHAR wszBuf[_MAX_PATH+1];
HRESULT hResult;
DWORD dwPermit;
//
// get the full path of the key name
//
wsprintf(wszBuf, L"%s/%s", REQDB_ROOT, wszGuid);
//
// Set permission
//
dwPermit = fReadOnly ? METADATA_PERMISSION_READ :
METADATA_PERMISSION_WRITE;
//
// open it
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
wszBuf,
dwPermit );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Open req key error: %x", m_dwErrorCode);
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::OpenRootKey()
/*++
Routine Description:
Open the root key. The open automatically closes what is opened
previously. This is done in function Open.
Arguments:
fReadOnly - IN True - open with read permission, FALSE - open with write
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::OpenRootKey");
HRESULT hr;
DWORD dwPermit;
//
// Set permission
//
dwPermit = METADATA_PERMISSION_READ |
METADATA_PERMISSION_WRITE;
//
// open it
//
hr = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT,
dwPermit );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Open req key error: %x", m_dwErrorCode);
TraceFunctLeave();
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
void
Creq::CloseKey( BOOL fNeedSave)
/*++
Routine Description:
Close a key.
Arguments:
None
Return Value:
None
--*/
{
TraceFunctEnter("Creq::CloseKey");
_ASSERT(m_pMK);
if ( fNeedSave )
m_pMK->Save();
m_pMK->Close();
TraceFunctLeave();
}
BOOL
Creq::DeleteKey( LPWSTR wszGuid )
/*++
Routine Description:
Delete a key, given the guid.
Arguments:
wszGuid - IN guid string
Return Value:
TRUE if success, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::DeleteKey");
_ASSERT(m_pMK);
WCHAR wszBuf[_MAX_PATH];
HRESULT hResult;
//
// check if the key already exists
//
swprintf(wszBuf, L"%s/%s", REQDB_ROOT, wszGuid);
hResult = m_pMK->Open( wszBuf );
if ( FAILED( hResult ) ) {
ErrorTrace( 0, "Key to delete doesn't exist");
return TRUE; // this is not an error
}
m_pMK->Close();
//
// open db root key, in order to delete child
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT,
METADATA_PERMISSION_WRITE );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Open root key error: %x", m_dwErrorCode);
return FALSE;
}
//
// delete
//
hResult = m_pMK->DestroyChild( wszGuid );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Delete req key fail: %x", m_dwErrorCode);
m_pMK->Close();
return FALSE;
}
//m_pMK->Save();
m_pMK->Close();
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::EnumKeyInit()
/*++
Routine Description:
Initialization for enumerating a key.
Arguments:
None
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::EnumKeyInit");
_ASSERT(m_pMK);
HRESULT hResult;
//
// Open root key
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT,
METADATA_PERMISSION_READ );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Open root key error: %x", m_dwErrorCode);
return FALSE;
}
m_pMK->BeginChildEnumeration();
m_pMK->Close();
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::OpenNextKey( LPWSTR wszGuid )
/*++
Routine Description:
Open next request key in the enumeration.
Arguments:
None
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::OpenNextKey");
_ASSERT(m_pMK);
HRESULT hResult;
WCHAR wszBuf[_MAX_PATH+1];
WCHAR wszBuf2[_MAX_PATH+1];
//
// Open root key
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT,
METADATA_PERMISSION_READ );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Open root key error: %x", m_dwErrorCode);
return FALSE;
}
//
// Get next key name
//
hResult = m_pMK->NextChild( wszBuf );
m_pMK->Close();
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Enumerate next key error: %x", m_dwErrorCode);
return FALSE;
}
if ( wszGuid )
wcscpy( wszGuid, wszBuf );
//
// get next key full name
//
wsprintf(wszBuf2, L"%s/%s", REQDB_ROOT, wszBuf);
//
// Open this next key
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
wszBuf2,
METADATA_PERMISSION_READ );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Open req key error: %x", m_dwErrorCode);
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::GenGUID(LPWSTR *wszGuid)
/*++
Routine Description:
Generate a Globally unique id.
wszGuid's memory should be pre-allocated
Arguments:
wszGuid - OUT string format of the UUID
Return Value:
True if success, false otherwise
--*/
{
TraceFunctEnter("Creq::GenGUID");
GUID guidData;
//
// Create guid
//
HRESULT hResult = CoCreateGuid(&guidData);
if ( FAILED( hResult) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Can't create uuid. Error code: %x", m_dwErrorCode);
return FALSE;
}
//
// convert to string
//
RPC_STATUS rpcStatus = UuidToString(&guidData, wszGuid);
if ( rpcStatus != RPC_S_OK ) {
m_dwErrorCode = rpcStatus;
ErrorTrace(0, "UUID conversion fail. rpc status: %x", m_dwErrorCode);
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::OpenDatabase()
/*++
Routine Description:
Everyone who is trying to use this database must call this function
to perform some initialization.
Arguments:
None
Return Value:
HRESULT error code.
--*/
{
TraceFunctEnter("Creq::OpenDatabase");
if ( m_fInitOk == TRUE ) {
m_dwErrorCode = ERROR_ALREADY_INITIALIZED;
ErrorTrace(0, "Try to open data base twice without closing");
return FALSE;
}
// local variables
HRESULT hResult;
DWORD cMacName = MAX_COMPUTERNAME_LENGTH+1;
//
// get the machine name, assume the metabase we are using is local
//
if ( ! GetComputerName( m_wszMachineName, &cMacName ) ) {
m_dwErrorCode = GetLastError();
ErrorTrace(0, "Can't get computer name. Error code: %x", m_dwErrorCode);
return FALSE;
}
//
// obtain metabase object for root key
//
hResult = CreateMetabaseObject ( m_wszMachineName, &m_pMeta );
if ( FAILED(hResult) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Can't create meta object. Error code: %x", m_dwErrorCode);
return FALSE;
}
//
// allocate memory for m_pMK
//
_ASSERT(m_pMeta);
m_pMK = new CMetabaseKey(m_pMeta);
if ( !m_pMK ) {
m_dwErrorCode = GetLastError();
ErrorTrace(0, "Not enough memory space");
return FALSE;
}
//
// Test if the root key exists, if not, have to create it
//
hResult = m_pMK->Open( REQDB_ROOT );
if ( FAILED( hResult ) ) {
if ( !CreateRootKey() )
return FALSE;
} else
m_pMK->Close();
//
// Set default properties at the root key
//
if ( !SelfConfig() )
return FALSE;
m_fInitOk = TRUE;
TraceFunctLeave();
return TRUE;
}
void
Creq::CloseDatabase()
/*++
Routine Description:
A chance to clean up. Client should call it at the end.
Arguments:
None
Return Value:
HRESULT error code.
--*/
{
TraceFunctEnter("Creq::CloseDatabase");
_ASSERT( m_fInitOk == TRUE );
_ASSERT( m_pMK );
m_fInitOk = FALSE;
m_pMK->Close();
m_pMK->Save();
delete m_pMK;
m_pMK = NULL;
m_pMeta->Release();
TraceFunctLeave();
}
BOOL
Creq::CreateRootKey()
/*++
Routine Description:
Create root key for the database, this is only done once.
Arguments:
None
Return Value:
TRUE if succeed, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::CreateRootKey");
_ASSERT( m_pMK );
HRESULT hResult;
//
// First open parent key
//
hResult = m_pMK->Open ( METADATA_MASTER_ROOT_HANDLE,
REQDB_ROOT_PARENT,
METADATA_PERMISSION_WRITE);
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Unable to open DB's parent key. Errorcode: %x", m_dwErrorCode);
return FALSE;
}
//
// Now create
//
hResult = m_pMK->CreateChild( REQDB_ROOT_NAME );
if ( FAILED( hResult ) ) {
m_dwErrorCode = hResult;
ErrorTrace(0, "Unable to create root key for DB. Error: %x", m_dwErrorCode);
return FALSE;
}
//
// Close parant key
//
//m_pMK->Save();
m_pMK->Close();
return TRUE;
}
void
Creq::Uni2Char(
LPSTR lpszDest,
LPWSTR lpwszSrc ) {
/*++
Routine Description:
Convert a unicode string into char string. Destination
string should be preallocated and length of _MAX_PATH
should be prepared.
Arguments:
lpszDest - Destination char string
lpwszSrc - Source wide char string
Return Value:
None
--*/
WideCharToMultiByte( CP_ACP,
0,
lpwszSrc,
-1,
lpszDest,
_MAX_PATH,
NULL,
NULL );
}
void
Creq::Char2Uni(
LPWSTR lpwszDest,
LPSTR lpszSrc ) {
/*++
Routine Description:
Convert a char string into unicode string. Destination
string should be preallocated and length of _MAX_PATH
should be prepared.
Arguments:
lpwszDest - Destination wide char string
lpszSrc - Source char string
Return Value:
None
--*/
MultiByteToWideChar ( CP_ACP,
0,
lpszSrc,
-1,
lpwszDest,
_MAX_PATH );
}
BOOL
Creq::RequestExist(LPWSTR wszGuid)
/*++
Routine Description:
Test if the specified key or request exists.
Arguments:
wszGuid - IN guid to tests against ( required )
Return Value:
TRUE on success, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::TestRequestExist");
_ASSERT( wszGuid );
ResetErrorCode();
WCHAR wszBuf[_MAX_PATH+1];
HRESULT hResult;
swprintf(wszBuf, L"%s/%s", REQDB_ROOT, wszGuid);
hResult = m_pMK->Open( wszBuf );
if ( FAILED( hResult ) ) { // doesn't exist
m_dwErrorCode = hResult;
DebugTrace(0, "Key doesn't exist");
return FALSE;
}
m_pMK->Close();
return TRUE;
}
BOOL
Creq::SetProperty( LPWSTR wszName,
LPWSTR wszVal )
/*++
Routine Description:
Set a property to the request in the metabase. The
request should have already been opened.
Right now all the properties are strings.
Arguments:
wszName - IN Property name
wszVal - IN Property value
Return Value:
TRUE on success, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::SetProperty");
_ASSERT( wszName );
_ASSERT( wszVal );
HRESULT hr;
DWORD dwPropID;
dwPropID = ID ( m_ptblTable[wszName] );
hr = m_pMK->SetString( dwPropID,
wszVal );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Set property fail: %x", hr );
TraceFunctLeave();
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
BOOL
Creq::GetProperty( LPWSTR wszName,
LPWSTR wszVal )
/*++
Routine Description:
Get the property from the metabase. The request
should already have been opened.
Right now all properties are string. _MAX_PATH's
space should be prepared for the buffer.
Arguments:
wszName - IN Property name to get
wszVal - OUT address to fill in the property string
Return Value:
TRUE on success, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::GetProperty");
HRESULT hr;
DWORD dwPropID;
_ASSERT( wszName );
_ASSERT( wszVal );
//
// Get property ID
//
dwPropID = ID( m_ptblTable[wszName] );
hr = m_pMK->GetString( dwPropID,
wszVal,
MAX_PROP_LEN*sizeof(WCHAR) );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Get property fail: %x", hr );
TraceFunctLeave();
return FALSE;
}
TraceFunctLeave();
return TRUE;
}
STDMETHODIMP Creq::test()
{
HRESULT hr;
IDispatch *ppi;
BOOL fsuc;
Iqry *pi;
hr = ItemInit();
if ( FAILED( hr ) )
return hr;
hr = ItemNext(&ppi, &fsuc);
if ( FAILED( hr) )
return hr;
while ( fsuc ) {
pi = (Iqry *)ppi;
if ( FAILED( hr ) )
return hr;
//hr = pi->put_EmailAddress(L"yan@rdrc.rpi.edu");
hr = pi->DoQuery();
if ( FAILED ( hr ))
return hr;
hr = ItemNext( &ppi, &fsuc );
if ( FAILED( hr ) )
return hr;
}
//hr = Save(ppi);
hr = ItemClose();
if ( FAILED( hr ) )
return hr;
pi->Release();
return S_OK;
}
BOOL
Creq::SelfConfig()
/*++
Routine Description:
Set some default values to the root key. These values
may be changed by accessing querybase object's property.
But it's set here in case the user doesn't want to
bother himself with that.
Arguments:
None.
Return Value:
TRUE if success, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::SelfConfig");
WCHAR wszBuf[MAX_PROP_LEN+1];
WCHAR wszMailPickupDir[_MAX_PATH];
WCHAR wszNewsPickupDir[_MAX_PATH];
WCHAR wszTemplateFile[_MAX_PATH];
//
// Open root key
//
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key error");
goto fail;
}
//
// Set properties, if doesn't exist
//
if ( !GetProperty(QUERY_STRING_NAME, wszBuf ) )
if ( !SetProperty(QUERY_STRING_NAME, L"") )
goto fail;
if ( !GetProperty(EMAIL_ADDRESS_NAME, wszBuf) )
if ( !SetProperty(EMAIL_ADDRESS_NAME, L"") )
goto fail;
if ( !GetProperty(NEWS_GROUP_NAME, wszBuf) )
if ( !SetProperty(NEWS_GROUP_NAME, L"") )
goto fail;
if ( !GetProperty(LAST_SEARCH_DATE_NAME, wszBuf) )
if ( !SetProperty(LAST_SEARCH_DATE_NAME, L"97/7/1 0:0:0") )
goto fail;
if ( !GetProperty(REPLY_MODE_NAME, wszBuf) )
if ( !SetProperty(REPLY_MODE_NAME, L"mail") )
goto fail;
if ( !GetProperty(FROM_LINE_NAME, wszBuf) )
if ( !SetProperty(FROM_LINE_NAME, L"SearchMaster") )
goto fail;
if ( !GetProperty(SUBJECT_LINE_NAME, wszBuf) )
if ( !SetProperty(SUBJECT_LINE_NAME, L"News Search Update") )
goto fail;
if ( !GetProperty(EDIT_URL_NAME, wszBuf) ) {
// assume it to be default web address
_ASSERT( m_wszMachineName );
wsprintf( wszBuf, L"http://%s/News/search/edit.asp", m_wszMachineName );
if ( !SetProperty(EDIT_URL_NAME, wszBuf ) )
goto fail;
}
if ( !GetProperty(MAIL_PICKUP_DIR_NAME, wszBuf) ) {
//
// Get the dir from meta base
//
if ( !ReadMetaValue( MAIL_KEY,
MD_MAIL_PICKUP_DIR,
wszMailPickupDir ) )
if ( !ReadMetaValue( MAIL_ROOT,
MD_MAIL_PICKUP_DIR,
wszMailPickupDir ) )
wcscpy( wszMailPickupDir, L"" );
//
// should keep the root key open
//
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key fail");
goto fail;
}
if ( !SetProperty(MAIL_PICKUP_DIR_NAME,
wszMailPickupDir) )
goto fail;
}
if ( !GetProperty(QUERY_SERVER_NAME, wszBuf) )
if ( !SetProperty(QUERY_SERVER_NAME, m_wszMachineName ) )
goto fail;
if ( !GetProperty(QUERY_CATALOG_NAME, wszBuf) )
if ( !SetProperty(QUERY_CATALOG_NAME, L"Web") )
goto fail;
if ( !GetProperty(MESSAGE_TEMPLATE_TEXT_NAME, wszBuf) )
if ( !SetProperty( MESSAGE_TEMPLATE_TEXT_NAME,
L"" ) )
goto fail;
if ( !GetProperty(MESSAGE_TEMPLATE_FILE_NAME, wszBuf) ) {
//
// get system directory
//
if ( GetSystemDirectory( wszTemplateFile,
_MAX_PATH ) <= 0 ) {
ErrorTrace( 0,
"Unable to get system directory: %d",
GetLastError() );
goto fail;
}
//
// apend something
//
wcscat( wszTemplateFile, L"\\inetsrv\\big.tem" );
if ( !SetProperty( MESSAGE_TEMPLATE_FILE_NAME, wszTemplateFile ) )
goto fail;
}
if ( !GetProperty(URL_TEMPLATE_TEXT_NAME, wszBuf) )
if ( !SetProperty( URL_TEMPLATE_TEXT_NAME,
L"") )
goto fail;
if ( !GetProperty(URL_TEMPLATE_FILE_NAME, wszBuf) ) {
//
// get system directory
//
if ( GetSystemDirectory( wszTemplateFile,
_MAX_PATH ) <= 0 ) {
ErrorTrace( 0,
"Unable to get system directory: %d",
GetLastError() );
goto fail;
}
//
// append something
//
wcscat( wszTemplateFile, L"\\inetsrv\\small.tem" );
if ( !SetProperty( URL_TEMPLATE_FILE_NAME, wszTemplateFile) )
goto fail;
}
if ( !GetProperty(SEARCH_FREQUENCY_NAME, wszBuf) )
if ( !SetProperty( SEARCH_FREQUENCY_NAME, L"1") )
goto fail;
if ( !GetProperty(IS_BAD_QUERY_NAME, wszBuf) )
if ( !SetProperty( IS_BAD_QUERY_NAME, L"0") )
goto fail;
if ( !GetProperty(NEWS_SERVER_NAME, wszBuf) )
if ( !SetProperty( NEWS_SERVER_NAME, m_wszMachineName) )
goto fail;
if ( !GetProperty(NEWS_PICKUP_DIR_NAME, wszBuf) ) {
//
// get it from metabase
//
if ( !ReadMetaValue( NEWS_ROOT,
MD_PICKUP_DIRECTORY,
wszNewsPickupDir ) )
wcscpy( wszNewsPickupDir, L"" );
//
// should keep the root key open
//
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key fail");
goto fail;
}
if ( !SetProperty( NEWS_PICKUP_DIR_NAME,
wszNewsPickupDir ) )
goto fail;
}
CloseKey();
TraceFunctLeave();
return TRUE;
fail:
CloseKey();
ErrorTrace(0, "Write default properties fail");
TraceFunctLeave();
return FALSE;
}
STDMETHODIMP Creq::get_property( BSTR bstrName,
BSTR * pVal)
/*++
Routine Description:
Property interface, reading one property
Arguments:
IN BSTR bstrName - name of the property
OUT BSTR pVal - Address to fill address of property value
the space is allocated on the server side,
and will only be valid before next call.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::get_property");
_ASSERT( bstrName );
_ASSERT( pVal );
ResetErrorCode();
WCHAR wszBuf[MAX_PROP_LEN+1];
PPropertyEntry pPropEntry = NULL;
//
// if it's the property of error status
//
if ( wcscmp( bstrName,
L"ErrorString" ) == 0 ) {
wcscpy( wszBuf, m_wszErrorString );
goto done;
}
//
// Open root key for reading
//
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key error");
wcscpy( m_wszErrorString, L"Open metabase root key error");
TraceFunctLeave();
return m_dwErrorCode;
}
//
// it's illegal to try gettign some per request properties
//
if ( wcscmp( bstrName, QUERY_STRING_NAME ) == 0 ||
wcscmp( bstrName, EMAIL_ADDRESS_NAME ) == 0 ||
wcscmp( bstrName, QUERY_ID_NAME ) == 0 ) {
ErrorTrace(0, "Try setting per request properties");
wcscpy( m_wszErrorString, L"Property doesn't exist");
m_dwErrorCode = DB_ERROR;
TraceFunctLeave();
return m_dwErrorCode;
}
//
// make sure the name passed in is valid
//
pPropEntry = m_ptblTable[ bstrName ];
if ( !pPropEntry ) {
ErrorTrace(0, "Invalid property name");
wcscpy( m_wszErrorString, L"Property doesn't exist");
m_dwErrorCode = DB_ERROR;
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
//
// get property
//
if ( !GetProperty( bstrName, wszBuf) ) {
ErrorTrace(0, "Get property fail");
wcscpy( m_wszErrorString, L"Get property fail");
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
CloseKey();
done:
//
// prepare return string
//
if ( m_bstrProperty )
SysFreeString( m_bstrProperty );
m_bstrProperty = SysAllocString( wszBuf );
if ( !m_bstrProperty ) {
ErrorTrace(0, "Sys Alloc String fail");
wcscpy( m_wszErrorString, L"Out of memory");
m_dwErrorCode = DB_ERROR;
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
//
// assign it
//
*pVal = m_bstrProperty;
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::put_property( BSTR bstrName,
BSTR newVal)
/*++
Routine Description:
Property interface, setting one property
Arguments:
IN BSTR bstrName - name of the property
IN BSTR newVal - value to set
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::put_property");
_ASSERT( bstrName );
_ASSERT( newVal );
ResetErrorCode();
HRESULT hr;
hr = VerifyProperty( bstrName,
newVal );
if ( FAILED( hr ) ) {
ErrorTrace(0, "Verify property fail");
swprintf( m_wszErrorString,
L"Property %s invalid",
bstrName );
TraceFunctLeave();
return hr;
}
//
// string length validation
//
if ( lstrlenW( newVal ) >= MAX_PROP_LEN ) {
TraceFunctLeave();
wcscpy( m_wszErrorString, L"Input too long" );
return TYPE_E_BUFFERTOOSMALL;
}
//
// Open root key for writing
//
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key error");
wcscpy( m_wszErrorString, L"Open root key error");
TraceFunctLeave();
return m_dwErrorCode;
}
//
// it's illegal to try setting some per request properties
//
if ( wcscmp( bstrName, QUERY_STRING_NAME ) == 0 ||
wcscmp( bstrName, EMAIL_ADDRESS_NAME ) == 0 ||
wcscmp( bstrName, QUERY_ID_NAME ) == 0 ) {
ErrorTrace(0, "Try setting per request properties");
wcscpy( m_wszErrorString, L"Setting property not allowed");
m_dwErrorCode = DB_ERROR;
TraceFunctLeave();
return m_dwErrorCode;
}
//
// make sure the name passed in is valid
//
PPropertyEntry pPropEntry = m_ptblTable[ bstrName ];
if ( !pPropEntry ) {
ErrorTrace(0, "Invalid property name");
wcscpy( m_wszErrorString, L"Invalid property name");
m_dwErrorCode = DB_ERROR;
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
//
// put property
//
if ( !SetProperty( bstrName, newVal) ) {
ErrorTrace(0, "Get property fail");
wcscpy( m_wszErrorString, L"Set property fail");
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
CloseKey();
TraceFunctLeave();
return S_OK;
}
//$-------------------------------------------------------------------
//
// StdPropertyGetIDispatch ( by Magnus )
//
// Description:
//
// Gets a IDispatch pointer for the given cLSID
//
// Parameters:
//
// clsid - OLE CLSID of the object
// ppIDipsatch - the IDispatch pointer to that object.
//
// Returns:
//
// E_POINTER - invalid argument
// NOERROR - Success
// Others - defined by CoCreateInstance.
//
//--------------------------------------------------------------------
HRESULT
Creq::StdPropertyGetIDispatch (
REFCLSID clsid,
IDispatch ** ppIDispatch
)
{
TraceFunctEnter ( "StdPropertyGetIDispatch" );
CComPtr<IDispatch> pNewIDispatch;
HRESULT hr = NOERROR;
_ASSERT ( ppIDispatch );
if ( ppIDispatch == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
TraceFunctLeave ();
return E_POINTER;
}
*ppIDispatch = NULL;
hr = ::CoCreateInstance (
clsid,
NULL,
CLSCTX_ALL,
IID_IDispatch,
(void **) &pNewIDispatch
);
if ( FAILED (hr) ) {
DebugTraceX ( 0, "CoCreate(IDispatch) failed %x", hr );
FatalTrace ( 0, "Failed to create IDispatch" );
goto Exit;
}
*ppIDispatch = pNewIDispatch;
pNewIDispatch->AddRef ();
Exit:
TraceFunctLeave ();
return hr;
// Destructor releases pNewIDispatch
}
STDMETHODIMP Creq::New(IDispatch **ppdispQry)
/*++
Routine Description:
Create a new query object.
Arguments:
OUT IDispatch ** pIDisp - The pointer to the dispatch interface.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::New");
ResetErrorCode();
HRESULT hr;
CLSID clsid;
WCHAR wszGuid[_MAX_PATH];
Iqry *piQry;
//
// convert the progid to clsid
//
hr = CLSIDFromProgID( QUERY_OBJ_ID,
&clsid );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Component class doesn't exist");
wcscpy( m_wszErrorString, L"Component class doesn't exist");
TraceFunctLeave();
return hr;
}
//
// create object and get idispatch
//
hr = Creq::StdPropertyGetIDispatch ( clsid,
ppdispQry);
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Get idispatch fail");
wcscpy( m_wszErrorString, L"Get IDispatch fail");
TraceFunctLeave();
return hr;
}
//
// load the object, note that at this moment, the key for
// the query object will only be created temporarily. It
// will be created permanently when saved back
//
// create key for the object
if ( !CreateKey( wszGuid ) ) {
ErrorTrace(0, "Create key fail");
wcscpy( m_wszErrorString, L"Create key fail");
TraceFunctLeave();
return m_dwErrorCode;
}
// load
piQry = (Iqry *)(*ppdispQry);
hr = piQry->Load( wszGuid,
(IDispatch *)this,
TRUE );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Load fail: %x", hr);
wcscpy( m_wszErrorString, L"Load property fail");
CloseKey();
TraceFunctLeave();
return hr;
}
CloseKey();
// now delete this key, because it has incomplete information
// now, if the object is not saved back, it shouldn't exist
if ( !DeleteKey( wszGuid ) ) {
ErrorTrace(0, "Delete key fail");
wcscpy( m_wszErrorString, L"Delete key fail");
TraceFunctLeave();
return m_dwErrorCode;
}
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::Read( BSTR wszPropName,
BSTR * pbstrVal,
BSTR wszGuid )
/*++
Routine Description:
Read a property from querybase object
Arguments:
IN BSTR wszPropName - Name of the property
OUT BSTR * pbstrVal - Will contain the value to be passed out
IN BSTR wszGuid - The object's ID
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Read");
_ASSERT( wszPropName );
_ASSERT( pbstrVal );
_ASSERT( wszGuid );
ResetErrorCode();
WCHAR wszBuf[MAX_PROP_LEN+1];
//
// if trying to read the guid itself, return it right away
//
if ( wcscmp( wszPropName, QUERY_ID_NAME ) == 0 ) {
wcscpy( wszBuf, wszGuid );
goto done;
}
//
// Otherwise get it from the metabase
//
if ( !OpenKey( wszGuid ) ) {
ErrorTrace(0, "Can't open key");
wcscpy( m_wszErrorString, L"Can't open key");
goto fail;
}
if ( !GetProperty( wszPropName,
wszBuf ) ) {
ErrorTrace(0, "Get property fail");
wcscpy( m_wszErrorString, L"Get property fail");
CloseKey();
goto fail;
}
//
// if the property is empty, I will get it from
// root key again
//
if ( wcscmp( wszBuf,
L"" ) == 0 ) {
CloseKey();
if ( !OpenRootKey() ) {
ErrorTrace(0, "Open root key fail");
wcscpy( m_wszErrorString, L"Open root key fail");
goto fail;
}
if ( !GetProperty( wszPropName,
wszBuf ) ) {
ErrorTrace(0, "Get property fail");
wcscpy( m_wszErrorString, L"Get property fail");
CloseKey();
goto fail;
}
}
done:
if ( m_bstrProperty )
SysFreeString( m_bstrProperty );
m_bstrProperty = SysAllocString( wszBuf );
if ( !m_bstrProperty ) {
ErrorTrace(0, "Sys alloc string fail");
wcscpy( m_wszErrorString, L"Out of memory");
m_dwErrorCode = DB_ERROR;
CloseKey();
goto fail;
}
*pbstrVal = m_bstrProperty;
CloseKey(); //extra close doesn't harm
TraceFunctLeave();
return S_OK;
fail:
TraceFunctLeave();
return m_dwErrorCode;
}
STDMETHODIMP Creq::Write( BSTR wszPropName,
BSTR bstrVal,
BSTR wszGuid)
/*++
Routine Description:
Write a property from querybase object
Arguments:
IN BSTR wszPropName - Name of the property
IN BSTR bstrVal - the property value to write
IN BSTR wszGuid - The object's ID
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Write");
_ASSERT( wszGuid );
_ASSERT( wszPropName );
_ASSERT( bstrVal );
ResetErrorCode();
//
// only everal properties can be written by query object
//
if ( wcscmp( wszPropName, QUERY_STRING_NAME ) == 0 ||
wcscmp( wszPropName, EMAIL_ADDRESS_NAME ) == 0 ||
wcscmp( wszPropName, NEWS_GROUP_NAME ) == 0 ||
wcscmp( wszPropName, REPLY_MODE_NAME ) == 0 ||
wcscmp( wszPropName, LAST_SEARCH_DATE_NAME ) == 0 ||
wcscmp( wszPropName, MESSAGE_TEMPLATE_TEXT_NAME) == 0 ||
wcscmp( wszPropName, URL_TEMPLATE_TEXT_NAME) == 0 ||
wcscmp( wszPropName, MESSAGE_TEMPLATE_FILE_NAME) == 0 ||
wcscmp( wszPropName, URL_TEMPLATE_FILE_NAME ) == 0 ||
wcscmp( wszPropName, SEARCH_FREQUENCY_NAME) == 0 ||
wcscmp( wszPropName, IS_BAD_QUERY_NAME) == 0 ) {
// open key
if ( !OpenKey( wszGuid, FALSE ) ) // try create it
if ( !CreateKey( wszGuid, TRUE ) ) {
ErrorTrace(0, "Unable to open or create key");
wcscpy( m_wszErrorString, L"Open key error");
goto fail;
}
// set it
if ( !SetProperty( wszPropName,
bstrVal ) ) {
ErrorTrace(0, "Set property error");
wcscpy( m_wszErrorString, L"Set property fail");
CloseKey();
goto fail;
}
CloseKey();
} //otherwise ignore it
TraceFunctLeave();
return S_OK;
fail:
TraceFunctLeave();
return m_dwErrorCode;
}
STDMETHODIMP Creq::Save(IDispatch * pdispQry)
/*++
Routine Description:
Ask the querybase object to save the query object
Arguments:
IN IDispatch *pdispQry - Interface pointer the the query object
Return Value:
HRESULT error code
--*/
{
TraceFunctEnter("Creq::Save");
_ASSERT( pdispQry );
ResetErrorCode();
HRESULT hr;
Iqry *piQry;
piQry = (Iqry *)pdispQry;
hr = piQry->Save( (IDispatch *)this,
TRUE,
FALSE );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Save query object fail: %x", hr);
wcscpy( m_wszErrorString, L"Save query object fail");
TraceFunctLeave();
return hr;
}
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::Item( BSTR wszGuid,
IDispatch * * ppdispQry)
/*++
Routine Description:
Reference a query object by guid
Arguments:
IN BSTR wszGuid - The query ID
OUT IDispatch ** ppdispQry - The pointer to the dispatch interface.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Item");
_ASSERT( wszGuid );
_ASSERT( ppdispQry );
ResetErrorCode();
HRESULT hr;
CLSID clsid;
Iqry *piQry;
//
// convert the progid to clsid
//
hr = CLSIDFromProgID( QUERY_OBJ_ID,
&clsid );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Component class doesn't exist");
wcscpy( m_wszErrorString, L"Component class doesn't exist");
TraceFunctLeave();
return hr;
}
//
// create object and get idispatch
//
hr = Creq::StdPropertyGetIDispatch ( clsid,
ppdispQry);
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Get idispatch fail");
wcscpy( m_wszErrorString, L"Get IDispatch fail");
TraceFunctLeave();
return hr;
}
//
// load the object,
//
// open key for the object
if ( !OpenKey( wszGuid ) ) {
ErrorTrace(0, "Open key fail");
wcscpy( m_wszErrorString, L"Open key fail");
TraceFunctLeave();
return m_dwErrorCode;
}
// load
piQry = (Iqry *)(*ppdispQry);
hr = piQry->Load( wszGuid,
(IDispatch *)this,
FALSE );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Load fail: %x", hr);
wcscpy( m_wszErrorString, L"Load property fail");
CloseKey();
TraceFunctLeave();
return hr;
}
CloseKey();
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::ItemInit()
/*++
Routine Description:
Initialization of enumeration.
Arguments:
None.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::ItemInit");
ResetErrorCode();
if ( EnumKeyInit() ) {
m_fEnumInit = TRUE;
m_fEnumSuccess = FALSE;
TraceFunctLeave();
return S_OK;
} else {
TraceFunctLeave();
wcscpy( m_wszErrorString, L"Item initialization fail");
return m_dwErrorCode;
}
}
STDMETHODIMP Creq::ItemNext( IDispatch * * ppdispQry,
BOOL *fSuccess)
/*++
Routine Description:
Reference next query object during an enumeration
Arguments:
OUT IDispatch ** ppdispQry - The pointer to the dispatch interface.
OUT BOOL *fSuccess - If this enumeration is successful, it should
be judged by the returned handle value.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Item");
_ASSERT( ppdispQry );
ResetErrorCode();
HRESULT hr;
CLSID clsid;
Iqry *piQry;
WCHAR wszGuid[_MAX_PATH+1];
if ( !m_fEnumInit ) {
ErrorTrace(0, "Enum not inited");
wcscpy( m_wszErrorString, L"Enumeration not inited");
m_dwErrorCode = DB_ERROR;
TraceFunctLeave();
return m_dwErrorCode;
}
//
// convert the progid to clsid
//
hr = CLSIDFromProgID( QUERY_OBJ_ID,
&clsid );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Component class doesn't exist");
wcscpy( m_wszErrorString, L"Component class doesn't exist");
TraceFunctLeave();
return hr;
}
//
// create object and get idispatch
//
hr = Creq::StdPropertyGetIDispatch ( clsid,
ppdispQry);
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Get idispatch fail");
wcscpy( m_wszErrorString, L"Get IDispatch fail");
TraceFunctLeave();
return hr;
}
//
// load the object,
//
// open key for the object
if ( !OpenNextKey( wszGuid ) ) {
ErrorTrace(0, "Open key fail");
*fSuccess = FALSE;
(*ppdispQry)->Release();
TraceFunctLeave();
return S_OK; // return a error code might cause asp crash,
// which is not what the asp programmers expect,
// so should only use fSuccess to test if an
// enumeration succeeds.
}
// load
piQry = (Iqry *)(*ppdispQry);
hr = piQry->Load( wszGuid,
(IDispatch *)this,
FALSE );
if ( FAILED( hr ) ) {
m_dwErrorCode = hr;
ErrorTrace(0, "Load fail: %x", hr);
wcscpy( m_wszErrorString, L"Load object fail");
CloseKey();
TraceFunctLeave();
return hr;
}
CloseKey();
*fSuccess = TRUE;
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::ItemClose()
/*++
Routine Description:
Close an enumeration
Arguments:
None.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::ItemClose");
ResetErrorCode();
CloseKey(); // extra close key doesn't harm
m_fEnumInit = FALSE;
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::Delete(BSTR wszGuid)
/*++
Routine Description:
Delete a query object permanently.
Arguments:
IN BSTR wszGuid - The query object's ID
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Delete");
_ASSERT( wszGuid );
ResetErrorCode();
if ( !DeleteKey( wszGuid ) ) {
ErrorTrace(0, "Delete key fail");
wcscpy( m_wszErrorString, L"Delete key fail");
TraceFunctLeave();
return m_dwErrorCode;
}
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::get_ItemX( BSTR wszGuid,
LPDISPATCH * pVal)
/*++
Routine Description:
Reference a query object, used by VB script as property.
Arguments:
IN BSTR wszGuid - The query object's ID
OUT LPDISPATCH pVal - the property value to be returned.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::get_ItemX");
HRESULT hr;
hr = Item( wszGuid,
pVal );
TraceFunctLeave();
return hr;
}
STDMETHODIMP Creq::get_NewX(LPDISPATCH * pVal)
/*++
Routine Description:
Create a new query object and return it. Used by
VBscript as a property.
Arguments:
OUT LPDISPATCH pVal - the property value to be returned.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::get_NewX");
HRESULT hr;
hr = New( pVal );
TraceFunctLeave();
return hr;
}
STDMETHODIMP Creq::get_ItemNextX(LPDISPATCH * pVal)
/*++
Routine Description:
Enumerate the next query object. Used by VBscript as
a property.
Arguments:
OUT LPDISPATCH pVal - the property value to be returned.
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::get_ItemNextX");
HRESULT hr;
hr = ItemNext( pVal, &m_fEnumSuccess);
TraceFunctLeave();
return hr;
}
STDMETHODIMP Creq::get_EnumSucceeded(BOOL * pVal)
/*++
Routine Description:
Property to show if the last enumeration succeeded.
Arguments:
OUT BOOL *pVal - Address to put the boolean value
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::get_EnumSucceeded");
*pVal = m_fEnumSuccess;
TraceFunctLeave();
return S_OK;
}
STDMETHODIMP Creq::Clean()
/*++
Routine Description:
To clean all the bad queries
Arguments:
None
Return Value:
HRESULT code.
--*/
{
TraceFunctEnter("Creq::Clean");
BOOL fMore = TRUE;
HRESULT hr;
WCHAR wszGuid[_MAX_PATH+1];
WCHAR wszProp[MAX_PROP_LEN];
ResetErrorCode();
//
// The outer loop is because the defect of metakey
// enumeration: if one key is deleted, its next key
// might not be enumerated. So if one bad query is
// cleaned, if its next key is bad, it won't be cleaned
// and we should go over again, until no bad query exists
//
while ( fMore ) {
fMore = FALSE;
hr = ItemInit();
if ( FAILED( hr ) ) {
ErrorTrace(0, "Item Init fail: %x", hr);
wcscpy( m_wszErrorString, L"Item init fail");
TraceFunctLeave();
return hr;
}
while ( OpenNextKey( wszGuid ) ) {
if ( !GetProperty( IS_BAD_QUERY_NAME,
wszProp ) ) {
ErrorTrace(0, "Get property fail: %x", m_dwErrorCode);
wcscpy( m_wszErrorString, L"Get property fail");
CloseKey();
TraceFunctLeave();
return m_dwErrorCode;
}
CloseKey();
if ( wcscmp( wszProp, L"1" ) == 0 ) {
fMore = TRUE;
DeleteKey( wszGuid );
}
}
hr = ItemClose();
if ( FAILED( hr ) ) {
ErrorTrace(0, "Item Close fail: %x", hr );
wcscpy( m_wszErrorString, L"Item close fail");
TraceFunctLeave();
return hr;
}
}
TraceFunctLeave();
return S_OK;
}
BOOL
Creq::ReadMetaValue( LPWSTR wszKey,
DWORD dwValID,
LPWSTR wszOut )
/*++
Routine Description:
Read a value from a specified metabase key. Since all other
metabase operations are query databaes oriented, this function
is written to handle other metabase key read. Note that since
it's using the same metabase object as the query database, this
method can't be called when a database key is opened already.
Or the caller should properly handle this.
Other than this, this method should have no negative effect on
the query database operation.
This method is used to read string type value only.
Arguments:
IN LPWSTR wszKey - Key to open
IN DWORD dwValID - ID of value to read
OUT LPWSTR wszOut- Address to put the metabase value
Returned Value:
TRUE if successful, FALSE otherwise
--*/
{
TraceFunctEnter("Creq::ReadMetaValue");
_ASSERT( wszKey );
_ASSERT( dwValID >= 0 );
_ASSERT( wszOut );
_ASSERT( m_pMK );
HRESULT hr;
ResetErrorCode();
//
// Close Key first
//
CloseKey(); //extra close key doesn't harm
//
// Open key
//
hr = m_pMK->Open( wszKey );
if ( FAILED( hr ) ) {
ErrorTrace(0, "Open key fail: %x", hr);
m_dwErrorCode = hr;
TraceFunctLeave();
return FALSE;
}
//
// Read the value
//
hr = m_pMK->GetString( dwValID,
wszOut,
_MAX_PATH*sizeof( WCHAR ) );
if ( FAILED( hr ) ) {
ErrorTrace(0, "Read metabase value fail: %x", hr);
m_dwErrorCode = hr;
m_pMK->Close();
TraceFunctLeave();
return FALSE;
}
//
// close key
//
m_pMK->Close();
TraceFunctLeave();
return TRUE;
}
/*
STDMETHODIMP Creq::get_ErrorString(BSTR * pVal)*/
/*++
Routine Description:
Enumerate the next query object. Used by VBscript as
a property.
Arguments:
OUT LPDISPATCH pVal - the property value to be returned.
Return Value:
HRESULT code.
--*//*
{
TraceFunctEnter("Creq::get_ErrorString");
FILE *fp = fopen("c:\\try\\bad.log", "w");
fclose(fp);
*pVal = SysAllocString( m_wszErrorString );
DebugTraceX(0, "Error string is: %ws", m_wszErrorString);
if ( ! *pVal ) {
ErrorTrace(0, "SysAllocString error");
TraceFunctLeave();
return E_OUTOFMEMORY;
}
TraceFunctLeave();
return S_OK;
}*/