Windows2003-3790/windows/appcompat/shims/specific/wordperfect9_2.cpp
2020-09-30 16:53:55 +02:00

162 lines
3.9 KiB
C++

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
WordPerfect9_2.cpp
Abstract:
WORDPERFECT 9 - GRAMMAR CHECK BUG:
Shim prevents an internal reference count used by the Grammar Checker
from becoming negative by not allowing Add/Release to be called more than
once for the life of the interface.
This COM Interface allocates some internal memory in DllGetClassObject()
and frees the memory in the Release().
Under WIN98 and NT4 this works because DllGetClassObject() is called at
the beginning of Grammar Checking and Release() is called after completion.
In Whistler OLE makes two pairs of extra calls (AddRef => Release &
QueryInterface => Release) causing Release() to free the internal
memory before the object is truly deleted. The code also set the internal
reference count to -2. On the next initiation of the grammar checker the
internal REF count NZ (-2) and DllGetClassObject() does not allocate the
needed memory and then access violates.
Notes:
This is an application specific shim.
History:
12/01/2000 a-larrsh Created
--*/
#include "precomp.h"
#include <initguid.h>
IMPLEMENT_SHIM_BEGIN(WordPerfect9_2)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(DllGetClassObject)
APIHOOK_ENUM_ENTRY_COMSERVER(wt9li)
APIHOOK_ENUM_END
IMPLEMENT_COMSERVER_HOOK(wt9li)
/* ++
COM definitions for object we are hooking
--*/
class __declspec(uuid("C0E10005-0500-0900-C0E1-C0E1C0E1C0E1")) WP9;
struct __declspec(uuid("C0E10005-0100-0900-C0E1-C0E1C0E1C0E1")) IWP9;
DEFINE_GUID(CLSID_WP9, 0xC0E10005, 0x0500, 0x0900, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1);
DEFINE_GUID(IID_IWP9, 0xC0E10005, 0x0100, 0x0900, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1, 0xC0, 0xE1);
typedef HRESULT (*_pfn_IWP9_QueryInterface)( PVOID pThis, REFIID iid, PVOID* ppvObject );
typedef ULONG (*_pfn_IWP9_AddRef)( PVOID pThis );
typedef ULONG (*_pfn_IWP9_Release)( PVOID pThis );
/*++
Manage OLE Object Ref count for QueryInterface, AddRef and Release
--*/
static int g_nInternalRefCount = 0;
HRESULT
APIHOOK(DllGetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID * ppv)
{
HRESULT hrResult;
hrResult = ORIGINAL_API(DllGetClassObject)(rclsid, riid, ppv);
if ( IsEqualGUID(rclsid, CLSID_WP9) &&
IsEqualGUID(riid, IID_IWP9) &&
hrResult == S_OK)
{
if (g_nInternalRefCount == 0)
{
g_nInternalRefCount++;
}
DPFN( eDbgLevelInfo, "DllGetClassObject");
}
return hrResult;
}
ULONG
COMHOOK(IWP9, AddRef)(PVOID pThis)
{
if (g_nInternalRefCount == 0)
{
_pfn_IWP9_AddRef pfnAddRef = (_pfn_IWP9_AddRef) ORIGINAL_COM(IWP9, AddRef, pThis);
(*pfnAddRef)(pThis);
}
g_nInternalRefCount++;
DPFN( eDbgLevelInfo, "AddRef");
return g_nInternalRefCount;
}
ULONG
COMHOOK(IWP9, Release)(PVOID pThis)
{
g_nInternalRefCount--;
if (g_nInternalRefCount == 0)
{
_pfn_IWP9_Release pfnRelease = (_pfn_IWP9_Release) ORIGINAL_COM(IWP9, Release, pThis);
(*pfnRelease)(pThis);
}
DPFN( eDbgLevelInfo, "Release");
return g_nInternalRefCount;
}
HRESULT
COMHOOK(IWP9, QueryInterface)( PVOID pThis, REFIID iid, PVOID* ppvObject )
{
HRESULT hrResult;
_pfn_IWP9_QueryInterface pfnQueryInterface = (_pfn_IWP9_QueryInterface) ORIGINAL_COM(IWP9, QueryInterface, pThis);
hrResult = (*pfnQueryInterface)(pThis, iid, ppvObject);
DPFN( eDbgLevelInfo, "QueryInterface");
return hrResult;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY_COMSERVER(wt9li)
APIHOOK_ENTRY(wt9li.dll, DllGetClassObject)
COMHOOK_ENTRY(WP9, IWP9, QueryInterface, 0)
COMHOOK_ENTRY(WP9, IWP9, AddRef, 1)
COMHOOK_ENTRY(WP9, IWP9, Release, 2)
HOOK_END
IMPLEMENT_SHIM_END