724 lines
19 KiB
C
724 lines
19 KiB
C
/*****************************************************************************
|
|
*
|
|
* fnd.h - Main private header file
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Coding conventions:
|
|
*
|
|
* + Follow standard shell coding conventions.
|
|
*
|
|
* + Standard K&R brace placement and indentation style.
|
|
*
|
|
* + Indent by 4 spaces.
|
|
*
|
|
* + Fully-brace all dependent clauses. Never write "if (c) foo();"
|
|
*
|
|
* + Do not return in the middle of a function. If forced,
|
|
* use a "goto exit". This way, you can stick entry/exit stuff
|
|
* later without getting caught out. (I learned this rule the
|
|
* hard way.)
|
|
*
|
|
* + Declare variables with narrowest possible scope.
|
|
*
|
|
* + Always test for success, not failure! The compiler will
|
|
* thank you.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* NOTE! This code was written for readability, not efficiency.
|
|
*
|
|
* I'm trusting the compiler to do optimizations like these:
|
|
*
|
|
* "Parameter alias":
|
|
*
|
|
* Function(LPFOO pfoo)
|
|
* {
|
|
* LPBAR pbar = (LPBAR)pfoo;
|
|
* ... use pbar and never mention pfoo again ...
|
|
* }
|
|
*
|
|
* --> becomes
|
|
*
|
|
* Function(LPFOO pfoo)
|
|
* {
|
|
* #define pbar ((LPBAR)pfoo)
|
|
* ... use pbar and never mention pfoo again ...
|
|
* #undef pbar
|
|
* }
|
|
*
|
|
* "Speculative Execution":
|
|
*
|
|
* Function(PFOO pfoo)
|
|
* {
|
|
* BOOL fRc;
|
|
* if (... condition 1 ...) {
|
|
* ... complicated stuff ...
|
|
* *pfoo = result;
|
|
* fRc = 1;
|
|
* } else { // condition 1 failed
|
|
* *pfoo = 0;
|
|
* fRc = 0;
|
|
* }
|
|
* return fRc;
|
|
* }
|
|
*
|
|
* --> becomes
|
|
*
|
|
* Function(PFOO pfoo)
|
|
* {
|
|
* BOOL fRc = 0;
|
|
* *pfoo = 0;
|
|
* if (... condition 1 ...) {
|
|
* ... complicated stuff ...
|
|
* *pfoo = result;
|
|
* fRc = 1;
|
|
* }
|
|
* return fRc;
|
|
* }
|
|
*
|
|
* "Single Exit":
|
|
*
|
|
* Function(...)
|
|
* {
|
|
* BOOL fRc;
|
|
* if (... condition 1 ...) {
|
|
* ...
|
|
* if (... condition 2 ...) {
|
|
* ...
|
|
* fRc = 1;
|
|
* } else { // condition 2 failed
|
|
* ... clean up ...
|
|
* fRc = 0;
|
|
* }
|
|
* } else { // condition 1 failed
|
|
* ... clean up ...
|
|
* fRc = 0;
|
|
* }
|
|
* return fRc;
|
|
* }
|
|
*
|
|
* --> becomes
|
|
*
|
|
* Function(...)
|
|
* {
|
|
* if (... condition 1 ...) {
|
|
* ...
|
|
* if (... condition 2 ...) {
|
|
* ...
|
|
* return 1;
|
|
* } else { // condition 2 failed
|
|
* ... clean up ...
|
|
* return 0;
|
|
* }
|
|
* } else { // condition 1 failed
|
|
* ... clean up ...
|
|
* return 0;
|
|
* }
|
|
* NOTREACHED;
|
|
* }
|
|
*
|
|
*
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define STRICT
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#define NOIME
|
|
#define NOSERVICE
|
|
#define WINVER 0x0400
|
|
#define _WIN32_WINDOWS 0x0400
|
|
#include <windows.h>
|
|
|
|
#ifdef RC_INVOKED /* Define some tags to speed up rc.exe */
|
|
#define __RPCNDR_H__ /* Don't need RPC network data representation */
|
|
#define __RPC_H__ /* Don't need RPC */
|
|
#include <oleidl.h> /* Get the DROPEFFECT stuff */
|
|
#define _OLE2_H_ /* But none of the rest */
|
|
#define _WINDEF_
|
|
#define _WINBASE_
|
|
#define _WINGDI_
|
|
#define NONLS
|
|
#define _WINCON_
|
|
#define _WINREG_
|
|
#define _WINNETWK_
|
|
#define _INC_COMMCTRL
|
|
#define _INC_SHELLAPI
|
|
#else
|
|
#include <windowsx.h>
|
|
#endif
|
|
|
|
#include <shlobj.h>
|
|
#include <shellapi.h>
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Resource identifiers
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Icons
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define IDI_INETFIND 1 /* My main icon */
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Menus
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define IDM_ONTHEINTERNET 1 /* Our sole menu item */
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Strings
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define IDS_ONTHEINTERNET 1
|
|
#define IDS_FINDHELP 2
|
|
|
|
#ifndef RC_INVOKED
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Stuff I'm tired of typing over and over.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
typedef LPITEMIDLIST PIDL, *PPIDL;
|
|
typedef LPCITEMIDLIST PCIDL;
|
|
typedef LPSHELLFOLDER PSF;
|
|
typedef LPVOID PV;
|
|
typedef LPVOID *PPV;
|
|
typedef LPCVOID PCV;
|
|
typedef REFIID RIID;
|
|
typedef LPUNKNOWN PUNK;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Baggage - Stuff I carry everywhere
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define INTERNAL NTAPI /* Called only within a translation unit */
|
|
#define EXTERNAL NTAPI /* Called from other translation units */
|
|
#define INLINE static __inline
|
|
|
|
#define BEGIN_CONST_DATA data_seg(".text", "CODE")
|
|
#define END_CONST_DATA data_seg(".data", "DATA")
|
|
|
|
#define OBJAT(T, v) (*(T *)(v)) /* Pointer punning */
|
|
#define PUN(T, v) OBJAT(T, &(v)) /* General-purpose type-punning */
|
|
|
|
/*
|
|
* Convert a count of TCHAR's to a count of bytes.
|
|
*/
|
|
#define cbCtch(ctch) ((ctch) * sizeof(TCHAR))
|
|
|
|
/*
|
|
* Convert an object (X) to a count of bytes (cb).
|
|
*/
|
|
#define cbX(X) sizeof(X)
|
|
|
|
/*
|
|
* Convert an array name (A) to a generic count (c).
|
|
*/
|
|
#define cA(a) (cbX(a)/cbX(a[0]))
|
|
|
|
/*
|
|
* Convert an array name (A) to a pointer to its Max.
|
|
* (I.e., one past the last element.)
|
|
*/
|
|
#define pvMaxA(a) (&a[cA(a)])
|
|
|
|
#define pvSubPvCb(pv, cb) ((PV)((PBYTE)pv - (cb)))
|
|
#define pvAddPvCb(pv, cb) ((PV)((PBYTE)pv + (cb)))
|
|
#define cbSubPvPv(p1, p2) ((PBYTE)(p1) - (PBYTE)(p2))
|
|
|
|
/*
|
|
* Round cb up to the nearest multiple of cbAlign. cbAlign must be
|
|
* a power of 2 whose evaluation entails no side-effects.
|
|
*/
|
|
#define ROUNDUP(cb, cbAlign) ((((cb) + (cbAlign) - 1) / (cbAlign)) * (cbAlign))
|
|
|
|
/*
|
|
* lfNeVV
|
|
*
|
|
* Given two values, return zero if they are equal and nonzero if they
|
|
* are different. This is the same as (v1) != (v2), except that the
|
|
* return value on unequal is a random nonzero value instead of 1.
|
|
* (lf = logical flag)
|
|
*
|
|
* lfNePvPv
|
|
*
|
|
* The same as lfNeVV, but for pointers.
|
|
*
|
|
* lfPv
|
|
*
|
|
* Nonzero if pv is not null.
|
|
*
|
|
*/
|
|
#define lfNeVV(v1, v2) ((v1) - (v2))
|
|
#define lfNePvPv(v1, v2) lfNeVV((DWORD)(PV)(v1), (DWORD)(PV)(v2))
|
|
#define lfPv(pv) ((BOOL)(PV)(pv))
|
|
|
|
/*
|
|
* land -- Logical and. Evaluate the first. If the first is zero,
|
|
* then return zero. Otherwise, return the second.
|
|
*/
|
|
|
|
#define fLandFF(f1, f2) ((f1) ? (f2) : 0)
|
|
|
|
/*
|
|
* lor -- Logical or. Evaluate the first. If the first is nonzero,
|
|
* return it. Otherwise, return the second.
|
|
*
|
|
* Unfortunately, due to the limitations of the C language, this can't
|
|
* be implemented, so we just return 1 if the first is nonzero.
|
|
* GNU has an extension that supports this, which we use. //;Internal
|
|
*/
|
|
|
|
#if defined(__GNUC__) //;Internal
|
|
#define fLorFF(f1, f2) ((f1) ?: (f2)) //;Internal
|
|
#else //;Internal
|
|
#define fLorFF(f1, f2) ((f1) ? 1 : (f2))
|
|
#endif //;Internal
|
|
|
|
/*
|
|
* limp - logical implication. True unless the first is nonzero and
|
|
* the second is zero.
|
|
*/
|
|
#define fLimpFF(f1, f2) (!(f1) || (f2))
|
|
|
|
/*
|
|
* leqv - logical equivalence. True if both are zero or both are nonzero.
|
|
*/
|
|
#define fLeqvFF(f1, f2) (!(f1) == !(f2))
|
|
|
|
/*
|
|
* InOrder - checks that i1 <= i2 < i3.
|
|
*/
|
|
#define fInOrder(i1, i2, i3) ((unsigned)((i2)-(i1)) < (unsigned)((i3)-(i1)))
|
|
|
|
/*
|
|
* CopyPvPvCb - Copy some memory around
|
|
* MovePvPvCb - Move some memory around
|
|
*/
|
|
#define CopyPvPvCb RtlCopyMemory
|
|
#define MovePvPvCb RtlMoveMemory
|
|
|
|
/*
|
|
* memeq - Reverse of memcmp
|
|
*/
|
|
#define memeq !memcmp
|
|
|
|
/*
|
|
* fPvPfnCmpPv - Compare two objects for equality using the comparison
|
|
* function and the desired outcome. E.g.,
|
|
*
|
|
* fPvPfnCmpPv(psz1, lstrcmpi, >, psz2)
|
|
*
|
|
* returns nonzero if psz1 is greater than psz2 according
|
|
* to lstrcmpi.
|
|
*/
|
|
|
|
#define fPvPfnCmpPv(p1, pfn, cmp, p2) (pfn(p1, p2) cmp 0)
|
|
|
|
/*
|
|
* lstreq - nonzero if two strings (according to lstrcmp) are equal
|
|
* lstrne - nonzero if two strings (according to lstrcmp) are different
|
|
*
|
|
* lstrieq - nonzero if two strings (according to lstrcmpi) are equal
|
|
* lstrine - nonzero if two strings (according to lstrcmpi) are different
|
|
*
|
|
* lstrieqA - nonzero if two strings (according to lstrcmpiA) are equal
|
|
* lstrineA - nonzero if two strings (according to lstrcmpiA) are different
|
|
*/
|
|
|
|
#define lstreq !lstrcmp
|
|
#define lstrne lstrcmp
|
|
|
|
#define lstrieq !lstrcmpi
|
|
#define lstrine lstrcmpi
|
|
|
|
#define lstrieqA !lstrcmpiA
|
|
#define lstrineA lstrcmpiA
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Wrappers and other quickies
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define pvExchangePpvPv(ppv, pv) \
|
|
(PV)InterlockedExchangePointer((ppv), (pv))
|
|
|
|
#define hresUs(us) MAKE_HRESULT(SEVERITY_SUCCESS, 0, (USHORT)(us))
|
|
#define hresLe(le) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, (USHORT)(le))
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Static globals: Initialized at PROCESS_ATTACH and never modified.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
HINSTANCE g_hinst; /* My instance handle */
|
|
DEFINE_GUID(CLSID_Fnd, 0x37865980, 0x75d1, 0x11cf,
|
|
0xbf,0xc7,0x44,0x45,0x53,0x54,0,0);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Dynamic Globals. There should be as few of these as possible.
|
|
*
|
|
* All access to dynamic globals must be thread-safe.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
ULONG g_cRef; /* Global reference count */
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* fndcf.c - Class Factory
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDMETHODIMP CFndFactory_New(RIID riid, PPV ppvObj);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* fndcm.c - IContextMenu, IShellExtInit
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDMETHODIMP CFndCm_New(RIID riid, PPV ppvObj);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Common object managers.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
typedef struct PREVTBL0 { /* Simple (non-OLE) object */
|
|
void (NTAPI *FinalizeProc)(PV pv); /* Finalization procedure */
|
|
} PREVTBL0, *PPREVTBL0;
|
|
|
|
typedef struct PREVTBL { /* Primary interface */
|
|
REFIID riid; /* Type of this object */
|
|
void (NTAPI *FinalizeProc)(PV pv); /* Finalization procedure */
|
|
} PREVTBL, *PPREVTBL;
|
|
|
|
typedef struct PREVTBL2 { /* Secondary interface */
|
|
ULONG lib; /* offset from start of object */
|
|
} PREVTBL2, *PPREVTBL2;
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define Simple_Interface(C) Primary_Interface(C, IUnknown); \
|
|
Default_QueryInterface(C) \
|
|
Default_AddRef(C) \
|
|
Default_Release(C)
|
|
#define Simple_Vtbl(C) Primary_Vtbl(C)
|
|
#define Simple_Interface_Begin(C) Primary_Interface_Begin(C, IUnknown)
|
|
#define Simple_Interface_End(C) Primary_Interface_End(C, IUnknown)
|
|
|
|
#else
|
|
|
|
#define Simple_Interface(C) Primary_Interface(C, IUnknown)
|
|
#define Simple_Vtbl(C) Primary_Vtbl(C)
|
|
#define Simple_Interface_Begin(C) \
|
|
struct S_##C##Vtbl c_####C##VI = { { \
|
|
&IID_##IUnknown, \
|
|
C##_Finalize, \
|
|
}, { \
|
|
Common##_QueryInterface, \
|
|
Common##_AddRef, \
|
|
Common##_Release, \
|
|
|
|
#define Simple_Interface_End(C) Primary_Interface_End(C, IUnknown)
|
|
|
|
#endif
|
|
|
|
#define Primary_Interface(C, I) \
|
|
extern struct S_##C##Vtbl { \
|
|
PREVTBL prevtbl; \
|
|
I##Vtbl vtbl; \
|
|
} c_##C##VI \
|
|
|
|
#define Primary_Vtbl(C) &c_##C##VI.vtbl
|
|
|
|
#define Primary_Interface_Begin(C, I) \
|
|
struct S_##C##Vtbl c_####C##VI = { { \
|
|
&IID_##I, \
|
|
C##_Finalize, \
|
|
}, { \
|
|
C##_QueryInterface, \
|
|
C##_AddRef, \
|
|
C##_Release, \
|
|
|
|
#define Primary_Interface_End(C, I) \
|
|
} }; \
|
|
|
|
#define Secondary_Interface(C, I) \
|
|
extern struct S_##I##_##C##Vtbl { \
|
|
PREVTBL2 prevtbl; \
|
|
I##Vtbl vtbl; \
|
|
} c_##I##_##C##VI \
|
|
|
|
#define Secondary_Vtbl(C, I) &c_##I##_##C##VI.vtbl
|
|
|
|
#define Secondary_Interface_Begin(C, I, nm) \
|
|
struct S_##I##_##C##Vtbl c_##I##_##C##VI = { { \
|
|
_IOffset(C, nm), \
|
|
}, { \
|
|
Forward_QueryInterface, \
|
|
Forward_AddRef, \
|
|
Forward_Release, \
|
|
|
|
#define Secondary_Interface_End(C, I, nm) \
|
|
} }; \
|
|
|
|
STDMETHODIMP Common_QueryInterface(PV, REFIID, PPV);
|
|
STDMETHODIMP_(ULONG) _Common_AddRef(PV pv);
|
|
STDMETHODIMP_(ULONG) _Common_Release(PV pv);
|
|
|
|
/*
|
|
* In DEBUG, go through the vtbl for additional squirties.
|
|
*/
|
|
#ifdef DEBUG
|
|
#define Common_AddRef(punk) \
|
|
((IUnknown *)(punk))->lpVtbl->AddRef((IUnknown *)(punk))
|
|
#define Common_Release(punk) \
|
|
((IUnknown *)(punk))->lpVtbl->Release((IUnknown *)(punk))
|
|
#else
|
|
#define Common_AddRef _Common_AddRef
|
|
#define Common_Release _Common_Release
|
|
#endif
|
|
|
|
void EXTERNAL Common_Finalize(PV);
|
|
|
|
STDMETHODIMP _Common_New(ULONG cb, PV vtbl, PPV ppvObj);
|
|
#define Common_NewCb(cb, C, ppvObj) _Common_New(cb, Primary_Vtbl(C), ppvObj)
|
|
#define Common_New(C, ppvObj) Common_NewCb(cbX(C), C, ppvObj)
|
|
|
|
STDMETHODIMP Forward_QueryInterface(PV pv, REFIID riid, PPV ppvObj);
|
|
STDMETHODIMP_(ULONG) Forward_AddRef(PV pv);
|
|
STDMETHODIMP_(ULONG) Forward_Release(PV pv);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Common_CopyAddRef
|
|
*
|
|
* Copy a pointer and increment its reference count.
|
|
*
|
|
* Cannot be a macro because Common_AddRef evaluates its argument
|
|
* twice.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
INLINE void Common_CopyAddRef(PV pvDst, PV pvSrc)
|
|
{
|
|
PPV ppvDst = pvDst;
|
|
*ppvDst = pvSrc;
|
|
Common_AddRef(pvSrc);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Invoking OLE methods.
|
|
*
|
|
* Invoke_Release is called with a pointer to the object, not with
|
|
* the object itself. It zeros out the variable on the release.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
void EXTERNAL Invoke_AddRef(PV pv);
|
|
void EXTERNAL Invoke_Release(PV pv);
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* assert.c - Assertion stuff
|
|
*
|
|
*****************************************************************************/
|
|
|
|
typedef enum {
|
|
sqflAlways = 0x00000000, /* Unconditional */
|
|
sqflDll = 0x00000001, /* Dll bookkeeping */
|
|
sqflFactory = 0x00000002, /* IClassFactory */
|
|
sqflCm = 0x00000004, /* IContextMenu */
|
|
sqflCommon = 0x00000000, /* common.c */
|
|
sqflError = 0x80000000, /* Errors */
|
|
} SQFL; /* squiffle */
|
|
|
|
void EXTERNAL SquirtSqflPtszV(SQFL sqfl, LPCTSTR ptsz, ...);
|
|
int EXTERNAL AssertPtszPtszLn(LPCTSTR ptszExpr, LPCTSTR ptszFile, int iLine);
|
|
|
|
#ifndef DEBUG
|
|
#define SquirtSqflPtszV sizeof
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Procedure enter/exit tracking.
|
|
*
|
|
* Start a procedure with
|
|
*
|
|
* EnterProc(ProcedureName, (_ "format", arg, arg, arg, ...));
|
|
*
|
|
* The format string is documented in EmitPal.
|
|
*
|
|
* End a procedure with one of the following:
|
|
*
|
|
* ExitProc();
|
|
*
|
|
* Procedure returns no value.
|
|
*
|
|
* ExitProcX();
|
|
*
|
|
* Procedure returns an arbitrary DWORD.
|
|
*
|
|
* ExitOleProc();
|
|
*
|
|
* Procedure returns an HRESULT (named "hres").
|
|
*
|
|
* ExitOleProcPpv(ppvOut);
|
|
*
|
|
* Procedure returns an HRESULT (named "hres") and, on success,
|
|
* puts a new object in ppvOut.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#define cpvArgMax 10 /* Max of 10 args per procedure */
|
|
|
|
typedef struct ARGLIST {
|
|
LPCSTR pszProc;
|
|
LPCSTR pszFormat;
|
|
PV rgpv[cpvArgMax];
|
|
} ARGLIST, *PARGLIST;
|
|
|
|
void EXTERNAL ArgsPalPszV(PARGLIST pal, LPCSTR psz, ...);
|
|
void EXTERNAL EnterSqflPszPal(SQFL sqfl, LPCTSTR psz, PARGLIST pal);
|
|
void EXTERNAL ExitSqflPalHresPpv(SQFL, PARGLIST, HRESULT, PPV);
|
|
|
|
#ifdef DEBUG
|
|
|
|
SQFL sqflCur;
|
|
|
|
#define AssertFPtsz(c, ptsz) \
|
|
((c) ? 0 : AssertPtszPtszLn(ptsz, TEXT(__FILE__), __LINE__))
|
|
#define ValidateF(c) \
|
|
((c) ? 0 : AssertPtszPtszLn(TEXT(#c), TEXT(__FILE__), __LINE__))
|
|
#define D(x) x
|
|
|
|
#define SetupEnterProc(nm) \
|
|
static CHAR s_szProc[] = #nm; \
|
|
ARGLIST _al[1] \
|
|
|
|
#define _ _al,
|
|
|
|
#define ppvBool ((PPV)1)
|
|
#define ppvVoid ((PPV)2)
|
|
|
|
#define DoEnterProc(v) \
|
|
ArgsPalPszV v; \
|
|
EnterSqflPszPal(sqfl, s_szProc, _al) \
|
|
|
|
#define EnterProc(nm, v) \
|
|
SetupEnterProc(nm); \
|
|
DoEnterProc(v) \
|
|
|
|
#define ExitOleProcPpv(ppv) \
|
|
ExitSqflPalHresPpv(sqfl, _al, hres, (PPV)(ppv)) \
|
|
|
|
#define ExitOleProc() \
|
|
ExitOleProcPpv(0) \
|
|
|
|
#define ExitProc() \
|
|
ExitSqflPalHresPpv(sqfl, _al, 0, ppvVoid) \
|
|
|
|
#define ExitProcX(x) \
|
|
ExitSqflPalHresPpv(sqfl, _al, (HRESULT)(x), ppvBool) \
|
|
|
|
#else
|
|
|
|
#define AssertFPtsz(c, ptsz)
|
|
#define ValidateF(c) (c)
|
|
#define D(x)
|
|
|
|
#define SetupEnterProc(nm)
|
|
#define DoEnterProc(v)
|
|
#define EnterProc(nm, v)
|
|
#define ExitOleProcPpv(ppv)
|
|
#define ExitOleProc()
|
|
#define ExitProc()
|
|
|
|
#endif
|
|
|
|
#define AssertF(c) AssertFPtsz(c, TEXT(#c))
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Macros that forward to the common handlers after squirting.
|
|
* Use these only in DEBUG.
|
|
*
|
|
* It is assumed that sqfl has been #define'd to the appropriate sqfl.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define Default_QueryInterface(Class) \
|
|
STDMETHODIMP \
|
|
Class##_QueryInterface(PV pv, RIID riid, PPV ppvObj) \
|
|
{ \
|
|
SquirtSqflPtszV(sqfl, TEXT(#Class) TEXT("_QueryInterface()")); \
|
|
return Common_QueryInterface(pv, riid, ppvObj); \
|
|
} \
|
|
|
|
#define Default_AddRef(Class) \
|
|
STDMETHODIMP_(ULONG) \
|
|
Class##_AddRef(PV pv) \
|
|
{ \
|
|
ULONG ulRc = _Common_AddRef(pv); \
|
|
SquirtSqflPtszV(sqfl, TEXT(#Class) \
|
|
TEXT("_AddRef(%08x) -> %d"), pv, ulRc); \
|
|
return ulRc; \
|
|
} \
|
|
|
|
#define Default_Release(Class) \
|
|
STDMETHODIMP_(ULONG) \
|
|
Class##_Release(PV pv) \
|
|
{ \
|
|
ULONG ulRc = _Common_Release(pv); \
|
|
SquirtSqflPtszV(sqfl, TEXT(#Class) \
|
|
TEXT("_Release(%08x) -> %d"), pv, ulRc); \
|
|
return ulRc; \
|
|
} \
|
|
|
|
#endif
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* mem.c
|
|
*
|
|
* Be extremely careful with FreePv, because it doesn't work if
|
|
* the pointer is null.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
STDMETHODIMP EXTERNAL ReallocCbPpv(UINT cb, PV ppvObj);
|
|
STDMETHODIMP EXTERNAL AllocCbPpv(UINT cb, PV ppvObj);
|
|
|
|
#define FreePpv(ppv) ReallocCbPpv(0, ppv)
|
|
#define FreePv(pv) LocalFree((HLOCAL)(pv))
|
|
|
|
#endif /* !RC_INVOKED */
|