/*----------------------------------------------------------------------
John Robbins
Microsoft Systems Journal, December 1997 - BugSlayer Column!
----------------------------------------------------------------------*/
import "oaidl.idl" ;
import "ocidl.idl" ;
// Forward declarations.
interface ITrace ;
dispinterface _TraceEvent ;
[
uuid ( 76AA99F4-0228-11D1-B293-00AA004206E4 ) ,
helpstring ( "ITrace Interface" ) ,
// Mark this as a dual interface.
dual ,
// Mark this interface as compatible with OLE automation.
oleautomation
]
interface ITrace : IDispatch
{
[
id ( 0x00000001 ) ,
helpstring ( "Tracing output method" )
]
// The simple method that everyone will call.
HRESULT Trace ( [in] BSTR bstrText ) ;
// For advanced users, or cool wrappers.
HRESULT FullTrace ( [in] BSTR bstrText ,
[in] long dwPID ) ;
////////////////////////////////////////////////////////////////////
// ShowTimeStamps property.
////////////////////////////////////////////////////////////////////
[
propget ,
id ( 2 ) ,
helpstring("If set, puts the time the trace message was
received by the server on the front of the message.")
]
HRESULT ShowTimeStamps ( [out , retval ] VARIANT_BOOL *pVal ) ;
[
propput ,
id ( 2 ) ,
helpstring("If set, puts the time the trace message was
received by the server on the front of the message.")
]
HRESULT ShowTimeStamps ( [in] VARIANT_BOOL newVal ) ;
////////////////////////////////////////////////////////////////////
// ShowTraceAsODS property
////////////////////////////////////////////////////////////////////
[
propget ,
id ( 3 ) ,
helpstring("Sends the Trace string to kernel debuggers on
the server system.")
]
HRESULT ShowTraceAsODS ( [out , retval ] VARIANT_BOOL *pVal ) ;
[
propput ,
id ( 3 ) ,
helpstring("Sends the Trace string to kernel debuggers on
the server system.")
]
HRESULT ShowTraceAsODS ( [in] VARIANT_BOOL newVal ) ;
////////////////////////////////////////////////////////////////////
// ShowItemNumber property
////////////////////////////////////////////////////////////////////
[
propget ,
id ( 4 ) ,
helpstring("If set, puts the trace message count on the
front of the message.")
]
HRESULT ShowItemNumber ( [out , retval ] VARIANT_BOOL *pVal ) ;
[
propput ,
id ( 4 ) ,
helpstring("If set, puts the trace message count on the
front of the message.")
]
HRESULT ShowItemNumber ( [in] VARIANT_BOOL newVal ) ;
////////////////////////////////////////////////////////////////////
// ShowPID property
////////////////////////////////////////////////////////////////////
[
propget ,
id ( 5 ) ,
helpstring("If set, and the PID is passed in, will show
the PID in the message.")
]
HRESULT ShowPID ( [out , retval ] VARIANT_BOOL *pVal ) ;
[
propput ,
id ( 5 ) ,
helpstring("If set, and the PID is passed in, will show
the PID in the message.")
]
HRESULT ShowPID ( [in] VARIANT_BOOL newVal ) ;
////////////////////////////////////////////////////////////////////
// AddCRLF property
////////////////////////////////////////////////////////////////////
[
propget ,
id ( 6 ) ,
helpstring("If set, adds a CR/LF to the message if needed.")
]
HRESULT AddCRLF ( [out , retval ] VARIANT_BOOL *pVal ) ;
[
propput ,
id ( 6 ) ,
helpstring("If set, adds a CR/LF to the message if needed.")
]
HRESULT AddCRLF ( [in] VARIANT_BOOL newVal ) ;
} ;
[
object ,
uuid ( D4C22CC0-0620-11D1-B29A-00aa004206e4 ) ,
helpstring ( "ITraceEvent Interface" ),
// Mark as hidden for user browsers.
//hidden
]
interface ITraceEvent : IDispatch
{
HRESULT TraceEvent ( BSTR bstrText ) ;
HRESULT ChangeShowTimeStamps ( VARIANT_BOOL bNewVal ) ;
HRESULT ChangeShowTraceAsODS ( VARIANT_BOOL bNewVal ) ;
HRESULT ChangeShowItemNumber ( VARIANT_BOOL bNewVal ) ;
HRESULT ChangeShowPID ( VARIANT_BOOL bNewVal ) ;
HRESULT ChangeAddCRLF ( VARIANT_BOOL bNewVal ) ;
} ;
[
uuid ( C1262E40-0186-11D1-B292-00AA004206E4 ) ,
version ( 1.0 ) ,
helpstring ( "TraceSrv 1.0 Type Library" )
]
library TRACESRVLib
{
// Import the specified standard libraries into this library.
importlib ( "stdole32.tlb" ) ;
importlib ( "stdole2.tlb" ) ;
[
uuid ( 480F47B3-02F0-11D1-B296-00AA004206E4 ) ,
helpstring ( "TraceSrv notification events for trace viewers" ),
// Mark as hidden for user browsers.
//hidden
]
dispinterface DITraceEvent
{
properties :
methods :
[
id ( 0x00000001 ) ,
helpstring ( "Tells the viewer that an ODS string is here" ),
]
void TraceEvent ( [in] BSTR bstrText ) ;
[
id ( 0x00000002 ) ,
helpstring ( "Tells the viewer the state of the ShowTimeStamps
property" ),
]
void ChangeShowTimeStamps ( [in] VARIANT_BOOL bNewVal ) ;
[
id ( 0x00000003 ) ,
helpstring ( "Tells the viewer the state of the ShowTraceAsODS
property" ),
]
void ChangeShowTraceAsODS ( [in] VARIANT_BOOL bNewVal ) ;
[
id ( 0x00000004 ) ,
helpstring ( "Tells the viewer the state of the ShowItemNumber
property" ),
]
void ChangeShowItemNumber ( [in] VARIANT_BOOL bNewVal ) ;
[
id ( 0x00000005 ) ,
helpstring ( "Tells the viewer the state of the ShowPID
property" ),
]
void ChangeShowPID ( [in] VARIANT_BOOL bNewVal ) ;
[
id ( 0x00000006 ) ,
helpstring ( "Tells the viewer the state of the AddCRLF
property" ),
]
void ChangeAddCRLF ( [in] VARIANT_BOOL bNewVal ) ;
} ;
////////////////////////////////////////////////////////////////////
// Trace coclass supported interface attributes.
////////////////////////////////////////////////////////////////////
[
uuid ( 76AA99F5-0228-11D1-B293-00AA004206E4 ) ,
helpstring ( "Trace Class" )
]
coclass Trace
{
// The default input interface.
[default] interface ITrace ;
// The event interface.
interface ITraceEvent ;
// The dispinterface needed to trigger events in VB.
[default , source] dispinterface DITraceEvent ;
} ;
} ;
Figure 2 TraceSrv Interface and Handlers
Trace.h
/*----------------------------------------------------------------------
John Robbins Microsoft Systems Journal, December 1997 - Bugslayer Column!
----------------------------------------------------------------------*/
#ifndef __TRACE_H_
#define __TRACE_H_
#include "resource.h"
// The IDispatch proxy classes for the events.
#include "CorrectProxyTraceSrv.h"
// The fast BSTR class.
#include "FastBSTR.h"
// The following are the formatting sizes. Since I arbitrarily chose to
// wrap the item numbers at 100,000, so the number format was known in
// advance, you can change those constants if you would like. You will
// need to change the handling code in TraceFull as well.
// Item Number - 6 (5 numbers + 1 space).
const int k_SIZE_ITEMNUMBER = 6 ;
// Time - 9 (hh:mm:ss + 1 space)
// BUG BUG
// Double check that Chinese and Thai formats are really this size!
// I think they might have characters on the front of the time but,
// I'm not sure if the TIME_NOTIMEMARKER shuts them off.
const int k_SIZE_TIME = 9 ;
// PID - 7 ([XXXX] + 1 space)
const int k_SIZE_PID = 7 ;
// CR/LF - 2
const int k_SIZE_CRLF = 2 ;
// TOTAL...
const int k_SIZE_FULLFORMAT = k_SIZE_ITEMNUMBER + k_SIZE_TIME +
k_SIZE_PID + k_SIZE_CRLF ;
// The byte count is expressed in Unicode characters since everything
// sent to this class is in wide characters.
const int k_SIZE_FULLFORMATBYTES = k_SIZE_FULLFORMAT * sizeof ( wchar_t ) ;
// The minimum trace buffer size.
const int k_MIN_TRACE_BUFF_SIZE = 2048 ;
// The default values for the trace settings. These are used in both
// the constructor and in the INI reading code. Note that -1 is TRUE
// for VARIANT_BOOLS!
const int k_DEFVAL_SHOWTIMESTAMPS = 0 ;
const int k_DEFVAL_SHOWTRACEASODS = -1 ;
const int k_DEFVAL_SHOWITEMNUMBER = 0 ;
const int k_DEFVAL_SHOWPID = 0 ;
const int k_DEFVAL_ADDCRLF = 0 ;
// The constant values for the INI where settings are stored. These
// do not need to be internationalized.
const LPCTSTR k_STR_INIFILE = _T ( "TraceSrv.ini" ) ;
const LPCTSTR k_STR_SECTION = _T ( "Settings" ) ;
const LPCTSTR k_STR_SHOWTIMESTAMPS = _T ( "ShowTimeStamps" ) ;
const LPCTSTR k_STR_SHOWTRACEASODS = _T ( "ShowTraceAsODS" ) ;
const LPCTSTR k_STR_SHOWITEMNUMBER = _T ( "ShowItemNumber" ) ;
const LPCTSTR k_STR_SHOWPID = _T ( "ShowPID" ) ;
const LPCTSTR k_STR_ADDCRLF = _T ( "AddCRLF" ) ;
// Since there is no WritePrivateProfileInt, these are the strings that
// represent the integer values for all the settings.
const LPCTSTR k_STR_VBTRUE = _T ( "-1" ) ;
const LPCTSTR k_STR_VBFALSE = _T ( "0" ) ;
class ATL_NO_VTABLE CTrace :
// The standard COM classes.
public CComObjectRootEx<CComMultiThreadModel> ,
public CComCoClass<CTrace , &CLSID_Trace> ,
public ISupportErrorInfo ,
public IDispatchImpl<ITrace , &IID_ITrace , &LIBID_TRACESRVLib> ,
// This class holds ITraceEvent connection points.
public IConnectionPointContainerImpl<CTrace> ,
// The actual event classes.
public CProxyDITraceEvent<CTrace> ,
// Allows TraceSrv to be scriptable.
public IObjectSafetyImpl<CTrace>
{
public :
CTrace( )
{
m_pUnkMarshaler = NULL ;
m_vbShowTimeStamps = k_DEFVAL_SHOWTIMESTAMPS ;
m_vbShowTraceAsODS = k_DEFVAL_SHOWTRACEASODS ;
m_vbShowItemNumber = k_DEFVAL_SHOWITEMNUMBER ;
m_vbShowPID = k_DEFVAL_SHOWPID ;
m_vbAddCRLF = k_DEFVAL_ADDCRLF ;
m_dwCurrCount = 0 ;
LoadSettings ( ) ;
}
~CTrace ( void )
{
SaveSettings ( ) ;
}
DECLARE_REGISTRY_RESOURCEID(IDR_TRACE)
DECLARE_GET_CONTROLLING_UNKNOWN()
// Wow, it only took me an entire day to figure out that this was the
// magic macro that forced a single instance!
DECLARE_CLASSFACTORY_SINGLETON(CTrace)
BEGIN_COM_MAP(CTrace)
COM_INTERFACE_ENTRY(ITrace)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal, m_pUnkMarshaler.p)
COM_INTERFACE_ENTRY_IMPL(IObjectSafety)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CTrace)
CONNECTION_POINT_ENTRY(DIID_DITraceEvent)
END_CONNECTION_POINT_MAP()
// The memory debugging code. See the Oct installment of Bugslayer!
DECLARE_MEMDEBUG ( CTrace ) ;
HRESULT FinalConstruct ( )
{
return ( CoCreateFreeThreadedMarshaler( GetControllingUnknown(),
&m_pUnkMarshaler.p ));
}
void FinalRelease ( )
{
m_pUnkMarshaler.Release ( ) ;
}
CComPtr<IUnknown> m_pUnkMarshaler;
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// ITrace
public :
STDMETHOD(Trace) ( BSTR bstrText ) ;
STDMETHOD(FullTrace) ( BSTR bstrText , long dwPID ) ;
STDMETHOD(get_ShowTimeStamps) ( VARIANT_BOOL * pVal ) ;
STDMETHOD(put_ShowTimeStamps) ( VARIANT_BOOL newVal ) ;
STDMETHOD(get_ShowTraceAsODS) ( VARIANT_BOOL * pVal ) ;
STDMETHOD(put_ShowTraceAsODS) ( VARIANT_BOOL newVal ) ;
STDMETHOD(get_ShowItemNumber) ( VARIANT_BOOL * pVal ) ;
STDMETHOD(put_ShowItemNumber) ( VARIANT_BOOL newVal ) ;
STDMETHOD(get_ShowPID) ( VARIANT_BOOL * pVal ) ;
STDMETHOD(put_ShowPID) ( VARIANT_BOOL newVal ) ;
STDMETHOD(get_AddCRLF) ( VARIANT_BOOL * pVal ) ;
STDMETHOD(put_AddCRLF) ( VARIANT_BOOL newVal ) ;
private :
void LoadSettings ( void ) ;
void SaveSettings ( void ) ;
// The real property values.
VARIANT_BOOL m_vbShowTimeStamps ;
VARIANT_BOOL m_vbShowTraceAsODS ;
VARIANT_BOOL m_vbShowItemNumber ;
VARIANT_BOOL m_vbShowPID ;
VARIANT_BOOL m_vbAddCRLF ;
// The running trace count.
DWORD m_dwCurrCount ;
// The fast BSTR class that holds the string buffer built up.
CFastBSTR m_cOutput ;
// The function that does all the actual work! If this function
// returns S_OK, then the m_cOutput variable has the string to
// use as the parameter to Fire_TraceEvent.
HRESULT ProcessTrace ( BSTR bstrText , long dwPID ) ;
} ;
#endif //__TRACE_H_
Trace.cpp
/*----------------------------------------------------------------------
John Robbins Microsoft Systems Journal, December 1997 - Bugslayer Column!
----------------------------------------------------------------------*/
#include "stdafx.h"
#include "TraceSrv.h"
#include "Trace.h"
IMPLEMENT_MEMDEBUG ( CTrace ) ;
// The memory dumping and validating code for this class.
#ifdef _DEBUG
void CTrace :: ClassDumper ( const void * pData )
{
CTrace * pClass = (CTrace*)pData ;
_RPT1 ( _CRT_WARN, " CTrace instance : 0x%08X\n" , pClass ) ;
}
void CTrace :: ClassValidator ( const void * , const void * )
{
// The validator is not needed for this class.
}
#endif
STDMETHODIMP CTrace :: InterfaceSupportsErrorInfo ( REFIID riid )
{
ASSERT ( this ) ;
static const IID* arr[] =
{
&IID_ITrace,
} ;
for ( int i = 0 ; i < (sizeof(arr)/sizeof(arr[0])) ; i++ )
{
if ( InlineIsEqualGUID ( *arr[ i ] , riid ) )
{
return ( S_OK ) ;
}
}
return ( S_FALSE ) ;
}
STDMETHODIMP CTrace :: Trace ( BSTR bstrText )
{
ASSERT ( this ) ;
return ( FullTrace ( bstrText , 0 ) ) ;
}
STDMETHODIMP CTrace :: FullTrace ( BSTR bstrText, long dwPID )
{
ASSERT ( this ) ;
return ( ProcessTrace ( bstrText , dwPID ) ) ;
}
STDMETHODIMP CTrace :: get_ShowTimeStamps ( VARIANT_BOOL * pVal )
{
ASSERT ( this ) ;
*pVal = m_vbShowTimeStamps ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: put_ShowTimeStamps ( VARIANT_BOOL newVal )
{
ASSERT ( this ) ;
m_vbShowTimeStamps = newVal ;
Fire_ChangeShowTimeStamps ( newVal ) ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: get_ShowTraceAsODS ( VARIANT_BOOL * pVal )
{
ASSERT ( this ) ;
*pVal = (VARIANT_BOOL)m_vbShowTraceAsODS ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: put_ShowTraceAsODS ( VARIANT_BOOL newVal )
{
ASSERT ( this ) ;
m_vbShowTraceAsODS = newVal ;
Fire_ChangeShowTraceAsODS ( newVal ) ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: get_ShowItemNumber ( VARIANT_BOOL * pVal )
{
ASSERT ( this ) ;
*pVal = (VARIANT_BOOL)m_vbShowItemNumber ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: put_ShowItemNumber ( VARIANT_BOOL newVal )
{
ASSERT ( this ) ;
m_vbShowItemNumber = newVal ;
Fire_ChangeShowItemNumber ( newVal ) ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: get_ShowPID ( VARIANT_BOOL * pVal )
{
ASSERT ( this ) ;
*pVal = (VARIANT_BOOL)m_vbShowPID ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: put_ShowPID ( VARIANT_BOOL newVal )
{
ASSERT ( this ) ;
m_vbShowPID = newVal ;
Fire_ChangeShowPID ( newVal ) ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: get_AddCRLF ( VARIANT_BOOL * pVal )
{
ASSERT ( this ) ;
*pVal = (VARIANT_BOOL)m_vbAddCRLF ;
return ( S_OK ) ;
}
STDMETHODIMP CTrace :: put_AddCRLF ( VARIANT_BOOL newVal )
{
ASSERT ( this ) ;
m_vbAddCRLF = newVal ;
Fire_ChangeAddCRLF ( newVal ) ;
return ( S_OK ) ;
}
HRESULT CTrace :: ProcessTrace ( BSTR bstrText , long dwPID )
{
// Always double check everything. Trust nothing.
ASSERT ( this ) ;
ASSERT ( NULL != bstrText ) ;
// The length of the input string. This is read after the pointer
// is validated and for everyone else to use.
int iInputLen = 0 ;
if ( NULL == bstrText )
{
return ( Error ( IDS_NULLSTRINGPASSED, GUID_NULL, E_INVALIDARG ) ) ;
}
// We have some form of pointer in bstrText. Make sure what it holds
// is valid.
ASSERT ( FALSE == IsBadReadPtr ( bstrText , sizeof ( BSTR ) ) ) ;
ASSERT ( L'\0' != *bstrText ) ;
if ( ( TRUE == IsBadReadPtr ( bstrText , sizeof ( BSTR ) ) ) ||
( L'\0' == *bstrText ) )
{
return ( Error ( IDS_INVALIDSTRING, GUID_NULL, E_INVALIDARG ) ) ;
}
// Get the input length now that the pointer is validated.
iInputLen = lstrlenW ( bstrText ) ;
// Could this string blow the buffer?
UINT uiSize = ( iInputLen * sizeof ( OLECHAR) ) + k_SIZE_FULLFORMATBYTES ;
// If this is the first time through, then m_lBuffSize is zero so
// this serves as the initial allocation point.
if ( uiSize >= m_cOutput.BufferSize ( ) )
{
// Delete the existing buffer and allocate a bigger one.
m_cOutput.Free ( ) ;
UINT uiAllocSize = uiSize * 2 ;
// Make sure we get a minimum buffer size.
if ( k_MIN_TRACE_BUFF_SIZE > uiAllocSize )
{
uiAllocSize = k_MIN_TRACE_BUFF_SIZE ;
}
OLECHAR * pTemp = m_cOutput.Allocate ( uiAllocSize ) ;
ASSERT ( NULL != pTemp ) ;
if ( NULL == pTemp )
{
return ( Error ( IDS_OUTOFMEMORY, GUID_NULL, E_OUTOFMEMORY ) ) ;
}
}
// Now start the real work, everything checked out.
// Increment the total.
m_dwCurrCount++ ;
// Is it time to wrap?
if ( 100000 == m_dwCurrCount )
{
m_dwCurrCount = 0 ;
}
// Have the marker pointer start at the beginning of the output buffer.
OLECHAR * pCurr = m_cOutput.GetDataBuffer ( ) ;
if ( -1 == m_vbShowItemNumber )
{
pCurr += wsprintfW ( pCurr , L"%05d " , m_dwCurrCount ) ;
}
if ( -1 == m_vbShowTimeStamps )
{
// Show the timestamp based on the user's local (here at the
// server, not at the client!). It is forced to just be the
// 24 hour military time.
int iLen = GetTimeFormatW ( LOCALE_USER_DEFAULT,
LOCALE_NOUSEROVERRIDE | TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
NULL, NULL, pCurr,
m_cOutput.BufferSize ( ) - k_SIZE_FULLFORMATBYTES ) ;
// BUG BUG. I need more error checking here.
ASSERT ( 0 != iLen ) ;
// Move the pointer along but remember to account for the
// null character counted item.
pCurr += ( iLen - 1 ) ;
// GetTimeFormat does not stick in the extra space on the end
// so do it now.
*pCurr = L' ' ;
pCurr++ ;
}
if ( -1 == m_vbShowPID )
{
pCurr += wsprintfW ( pCurr , L"[%04X] " , dwPID ) ;
}
// Now put the actual message in and copy the NULL terminator as well.
lstrcpynW ( pCurr , bstrText , iInputLen + 1 ) ;
// Move pCurr to point at the NULL terminator.
pCurr += iInputLen ;
// Finally check if the string needs CRLFs.
if ( -1 == m_vbAddCRLF )
{
if ( ( L'\x0D' != *(pCurr - 2) ) ||
( L'\x0A' != *(pCurr - 1) ) )
{
*(pCurr) = L'\x0D' ;
*(pCurr + 1) = L'\x0A' ;
pCurr += 2 ;
*pCurr = L'\0' ;
}
}
// Is it supposed to get shot to a kernel debugger?
if ( -1 == m_vbShowTraceAsODS )
{
OutputDebugStringW ( (BSTR)m_cOutput ) ;
}
// Calculate the actual string length for the string.
m_cOutput.GetStringByteLength ( ) ;
// Finally, let any viewers know.
Fire_TraceEvent ( m_cOutput ) ;
return ( S_OK ) ;
}
void CTrace :: LoadSettings ( void )
{
ASSERT ( this ) ;
m_vbShowTimeStamps =
(VARIANT_BOOL)GetPrivateProfileInt ( k_STR_SECTION, k_STR_SHOWTIMESTAMPS,
k_DEFVAL_SHOWTIMESTAMPS,
k_STR_INIFILE);
m_vbShowTraceAsODS =
(VARIANT_BOOL)GetPrivateProfileInt ( k_STR_SECTION, k_STR_SHOWTRACEASODS,
k_DEFVAL_SHOWTRACEASODS,
k_STR_INIFILE);
m_vbShowItemNumber =
(VARIANT_BOOL)GetPrivateProfileInt ( k_STR_SECTION, k_STR_SHOWITEMNUMBER,
k_DEFVAL_SHOWITEMNUMBER,
k_STR_INIFILE);
m_vbShowPID =
(VARIANT_BOOL)GetPrivateProfileInt ( k_STR_SECTION, k_STR_SHOWPID,
k_DEFVAL_SHOWPID, k_STR_INIFILE);
m_vbAddCRLF =
(VARIANT_BOOL)GetPrivateProfileInt ( k_STR_SECTION, k_STR_ADDCRLF,
k_DEFVAL_ADDCRLF, k_STR_INIFILE);
}
void CTrace :: SaveSettings ( void )
{
ASSERT ( this ) ;
WritePrivateProfileString ( k_STR_SECTION, k_STR_SHOWTIMESTAMPS,
( m_vbShowTimeStamps == -1 ) ? k_STR_VBTRUE : k_STR_VBFALSE,
k_STR_INIFILE);
WritePrivateProfileString ( k_STR_SECTION, k_STR_SHOWTRACEASODS,
( m_vbShowTraceAsODS == -1 ) ? k_STR_VBTRUE : k_STR_VBFALSE,
k_STR_INIFILE);
WritePrivateProfileString ( k_STR_SECTION, k_STR_SHOWITEMNUMBER,
( m_vbShowItemNumber == -1 ) ? k_STR_VBTRUE : k_STR_VBFALSE,
k_STR_INIFILE);
WritePrivateProfileString ( k_STR_SECTION, k_STR_SHOWPID,
( m_vbShowPID == -1 ) ? k_STR_VBTRUE : k_STR_VBFALSE,
k_STR_INIFILE);
WritePrivateProfileString ( k_STR_SECTION, k_STR_ADDCRLF,
( m_vbAddCRLF == -1 ) ? k_STR_VBTRUE : k_STR_VBFALSE,
k_STR_INIFILE);
}
Figure 3 FastBSTR.h
/*----------------------------------------------------------------------
John Robbins
Microsoft Systems Journal, December 1997 - Bugslayer Column!
----------------------------------------------------------------------*/
#ifndef _FASTBSTR_
#define _FASTBSTR_
class CFastBSTR
{
////////////////////////////////////////////////////////////////////////
// Public construction and destruction.
////////////////////////////////////////////////////////////////////////
public :
// The memory debugging code. See the Oct installment of
// Bugslayer!
DECLARE_MEMDEBUG ( CFastBSTR ) ;
CFastBSTR ( void )
{
m_szData = NULL ;
m_szWholeBuff = NULL ;
m_pdwStringSize = NULL ;
m_uiBuffSize = 0 ;
}
~CFastBSTR ( void )
{
Free ( ) ;
}
////////////////////////////////////////////////////////////////////////
// Public allocation and deallocation functions.
////////////////////////////////////////////////////////////////////////
public :
OLECHAR * Allocate ( UINT uiSize )
{
ASSERT ( 0 != uiSize ) ;
if ( 0 == uiSize )
{
return ( NULL ) ;
}
// Free up any existing.
if ( NULL != m_szWholeBuff )
{
delete [] m_szWholeBuff ;
}
m_szWholeBuff = new DWORD[ uiSize ] ;
memset ( m_szWholeBuff , NULL , uiSize ) ;
m_pdwStringSize = (LPDWORD)m_szWholeBuff ;
*m_pdwStringSize = 0 ;
m_szData = (OLECHAR*)(m_pdwStringSize + 1) ;
m_uiBuffSize = uiSize ;
return ( m_szData ) ;
}
void Free ( )
{
if ( NULL == m_szWholeBuff )
{
return ;
}
delete [] m_szWholeBuff ;
m_szData = NULL ;
m_szWholeBuff = NULL ;
m_pdwStringSize = NULL ;
m_uiBuffSize = 0 ;
}
////////////////////////////////////////////////////////////////////////
// Public length functions.
////////////////////////////////////////////////////////////////////////
public :
// Returns the length of the whole data buffer currently allocated.
UINT BufferSize ( void ) const
{
return ( m_uiBuffSize ) ;
}
// Returns the byte length of the current string. Call this before
// passing the data for this string to a function that needs a
// BSTR. If the parameter is not zero, then that value will be
// used for the string size. If this parameter is zero, then
// this returns the length of the string data. (This means that
// the length will be up to the first NULL character.)
UINT GetStringByteLength ( UINT uiLen = 0 )
{
ASSERT ( m_pdwStringSize != NULL ) ;
if ( NULL == m_pdwStringSize )
{
return ( 0 ) ;
}
if ( 0 == uiLen )
{
uiLen = lstrlenW ( m_szData ) * sizeof ( OLECHAR ) ;
}
*m_pdwStringSize = uiLen ;
return ( uiLen ) ;
}
////////////////////////////////////////////////////////////////////////
// Public data access members and operators.
////////////////////////////////////////////////////////////////////////
public :
OLECHAR * GetDataBuffer ( ) const
{
return ( m_szData ) ;
}
operator BSTR ( ) const
{
return ( m_szData ) ;
}
////////////////////////////////////////////////////////////////////////
// Private data members.
////////////////////////////////////////////////////////////////////////
private :
// The whole actual buffer.
LPDWORD m_szWholeBuff ;
// The string size portion of the buffer.
LPDWORD m_pdwStringSize ;
// The data portion of the buffer.
OLECHAR * m_szData ;
// The buffer size.
DWORD m_uiBuffSize ;
} ;
#endif // _FASTBSTR_
Figure 4 DCOM Properties Settings
|
In the Default Properties Page in DCOMCNFG |
||
|
Enable Distributed COM on this Computer |
Checked |
|
|
Default Authentication Level |
Connect |
|
|
Default Impersonation Level |
Identify |
|
|
In the Default Security Page in DCOMCNFG |
||
|
Default Access Permissions |
Everyone |
Allow Access |
|
INTERACTIVE |
Allow Access |
|
|
NETWORK |
Allow Access |
|
|
SYSTEM |
Allow Access |
|
|
Default Launch Permissions |
Administrators |
Allow Launch |
|
Everyone |
Allow Launch |
|
|
INTERACTIVE |
Allow Launch |
|
|
NETWORK |
Allow Launch |
|
|
SYSTEM |
Allow Launch |
|
|
Default Configuration Permissions |
Administrators |
Full Control |
|
CREATOR OWNER |
Full Control |
|
|
Everyone |
Read |
|
|
INTERACTIVE |
Special Access |
|
|
SYSTEM |
Full Control |
|