summaryrefslogtreecommitdiffstats
path: root/private/nw/svcdlls/nwwks/client/nwshext.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'private/nw/svcdlls/nwwks/client/nwshext.cxx')
-rw-r--r--private/nw/svcdlls/nwwks/client/nwshext.cxx854
1 files changed, 854 insertions, 0 deletions
diff --git a/private/nw/svcdlls/nwwks/client/nwshext.cxx b/private/nw/svcdlls/nwwks/client/nwshext.cxx
new file mode 100644
index 000000000..4818a3823
--- /dev/null
+++ b/private/nw/svcdlls/nwwks/client/nwshext.cxx
@@ -0,0 +1,854 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ nwshext.cxx
+
+Abstract:
+
+ This module implements the basics of shell extension classes.
+ It includes AddRef(), Release(), QueryInterface() of the
+ following classes.
+ CNWObjContextMenuClassFactory, CNWObjContextMenu
+ CNWFldContextMenuClassFactory, CNWFldContextMenu
+ CNWHoodContextMenuClassFactory, CNWHoodContextMenu
+
+
+Author:
+
+ Yi-Hsin Sung (yihsins) 25-Oct-1995
+
+--*/
+
+extern "C"
+{
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+#include <shellapi.h>
+#include <shlobj.h>
+#include <stdio.h>
+#define DONT_WANT_SHELLDEBUG
+#include <shsemip.h>
+
+#include <nwreg.h>
+}
+
+#include "nwshcmn.h"
+#include "nwshext.h"
+
+//
+// Initialize GUIDs (should be done only and at-least once per DLL/EXE)
+//
+
+#pragma data_seg(".text")
+#define INITGUID
+#include <initguid.h>
+#include <shlguid.h>
+#include "nwclsid.h"
+#pragma data_seg()
+
+//
+// Global variables
+//
+LONG g_cRefThisDll = 0; // Reference count of this DLL.
+WCHAR g_szProviderName[256]; // Store the provider name
+
+HINSTANCE g_hShellLibrary = NULL;
+SHELLGETNETRESOURCE g_pFuncSHGetNetResource = NULL;
+SHELLDRAGQUERYFILE g_pFuncSHDragQueryFile = NULL;
+SHELLCHANGENOTIFY g_pFuncSHChangeNotify = NULL;
+SHELLEXECUTEEX g_pFuncSHExecuteEx = NULL;
+
+
+#if DBG
+WCHAR szDebugStr[256]; // For Debug Output
+#endif
+
+BOOL LoadShellDllEntries( VOID );
+
+extern "C"
+{
+//---------------------------------------------------------------------------
+// NwCleanupShellExtension
+//---------------------------------------------------------------------------
+
+VOID NwCleanupShellExtensions( VOID )
+{
+ if ( g_hShellLibrary )
+ {
+ FreeLibrary( g_hShellLibrary );
+ g_hShellLibrary = NULL;
+ }
+}
+}
+
+//---------------------------------------------------------------------------
+// DllCanUnloadNow
+//---------------------------------------------------------------------------
+
+STDAPI DllCanUnloadNow(void)
+{
+#if DBG
+ wsprintf( szDebugStr,L"In DLLCanUnloadNow: g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+
+ return ResultFromScode((g_cRefThisDll == 0) ? S_OK : S_FALSE);
+}
+
+//---------------------------------------------------------------------------
+// DllGetClassObject
+//---------------------------------------------------------------------------
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut)
+{
+ *ppvOut = NULL;
+
+ if ( !LoadShellDllEntries() )
+ return ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
+
+ if (IsEqualIID(rclsid, CLSID_NetWareObjectExt))
+ {
+ CNWObjContextMenuClassFactory *pcf = new CNWObjContextMenuClassFactory;
+
+ if ( pcf == NULL )
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ HRESULT hr = pcf->QueryInterface(riid, ppvOut);
+
+ if ( FAILED(hr) )
+ delete pcf;
+
+ return hr;
+ }
+ else if (IsEqualIID(rclsid, CLSID_NetWareFolderMenuExt))
+ {
+ CNWFldContextMenuClassFactory *pcf = new CNWFldContextMenuClassFactory;
+
+ if ( pcf == NULL )
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ HRESULT hr = pcf->QueryInterface(riid, ppvOut);
+
+ if ( FAILED(hr) )
+ delete pcf;
+
+ return hr;
+ }
+ else if (IsEqualIID(rclsid, CLSID_NetworkNeighborhoodMenuExt))
+ {
+ CNWHoodContextMenuClassFactory *pcf= new CNWHoodContextMenuClassFactory;
+
+ if ( pcf == NULL )
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ HRESULT hr = pcf->QueryInterface(riid, ppvOut);
+
+ if ( FAILED(hr) )
+ delete pcf;
+
+ return hr;
+ }
+
+
+ return ResultFromScode(CLASS_E_CLASSNOTAVAILABLE);
+}
+
+BOOL LoadShellDllEntries( VOID )
+{
+ static BOOL s_fLoaded = FALSE;
+
+ if ( !s_fLoaded )
+ {
+ DWORD err;
+ HKEY hkey;
+
+ g_hShellLibrary = LoadLibrary( L"shell32.dll");
+ if ( g_hShellLibrary != NULL )
+ {
+ s_fLoaded = TRUE;
+
+ g_pFuncSHGetNetResource =
+ (SHELLGETNETRESOURCE) GetProcAddress( g_hShellLibrary,
+ (LPCSTR)(MAKELONG(SHGetNetResourceORD, 0)) );
+
+ g_pFuncSHDragQueryFile =
+ (SHELLDRAGQUERYFILE) GetProcAddress( g_hShellLibrary,
+ (LPCSTR) "DragQueryFileW");
+ g_pFuncSHChangeNotify =
+ (SHELLCHANGENOTIFY) GetProcAddress( g_hShellLibrary,
+ (LPCSTR) "SHChangeNotify");
+ g_pFuncSHExecuteEx =
+ (SHELLEXECUTEEX) GetProcAddress( g_hShellLibrary,
+ (LPCSTR) "ShellExecuteExW");
+ }
+
+ // Set the default provider name in case we fail to read
+ // it from the registry.
+ wcscpy( g_szProviderName, L"NetWare or Compatible Network");
+
+ //
+ // Read the Network Provider Name.
+ //
+ // Open HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services
+ // \NWCWorkstation\networkprovider
+ //
+ err = RegOpenKeyExW(
+ HKEY_LOCAL_MACHINE,
+ NW_WORKSTATION_PROVIDER_PATH,
+ REG_OPTION_NON_VOLATILE, // options
+ KEY_READ, // desired access
+ &hkey
+ );
+
+ if ( err == NO_ERROR )
+ {
+ LPWSTR pszProviderName = NULL;
+
+ //
+ // ignore the return code. if fail, pszProviderName is NULL
+ //
+ err = NwReadRegValue(
+ hkey,
+ NW_PROVIDER_VALUENAME,
+ &pszProviderName // free with LocalFree
+ );
+
+ if ( err == NO_ERROR && pszProviderName != NULL )
+ {
+ wcscpy( g_szProviderName, pszProviderName );
+ LocalFree( pszProviderName );
+ }
+
+ RegCloseKey( hkey );
+ }
+ }
+
+ return s_fLoaded;
+}
+
+//---------------------------------------------------------------------------
+// CNWObjContextMenuClassFactory
+//---------------------------------------------------------------------------
+
+CNWObjContextMenuClassFactory::CNWObjContextMenuClassFactory()
+{
+ _cRef = 0L;
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWObjContextMenuClassFactory::CNWObjContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWObjContextMenuClassFactory::~CNWObjContextMenuClassFactory()
+{
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWObjContextMenuClassFactory::~CNWObjContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWObjContextMenuClassFactory::QueryInterface(REFIID riid,
+ LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ // Any interface on this object is the object pointer
+
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppv = (LPCLASSFACTORY)this;
+ AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWObjContextMenuClassFactory::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWObjContextMenuClassFactory::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+STDMETHODIMP CNWObjContextMenuClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ *ppvObj = NULL;
+
+ // Shell extensions typically don't support aggregation (inheritance)
+
+ if (pUnkOuter)
+ return ResultFromScode(CLASS_E_NOAGGREGATION);
+
+ // Create the main shell extension object. The shell will then call
+ // QueryInterface with IID_IShellExtInit--this is how shell extensions are
+ // initialized.
+
+ LPCNWOBJCONTEXTMENU pShellExt = new CNWObjContextMenu(); // Create the CNWObjContextMenu object
+
+ if (NULL == pShellExt)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ //
+ // We set the reference count of CNWObjContextMenu to one at initialization.
+ // Hence, we can call Release() after QueryInterface.
+ // So, if QueryInterface failed, Release will free the object.
+ //
+
+ HRESULT hr = pShellExt->QueryInterface(riid, ppvObj);
+ pShellExt->Release();
+
+ return hr;
+}
+
+STDMETHODIMP CNWObjContextMenuClassFactory::LockServer(BOOL fLock)
+{
+ return NOERROR;
+}
+
+//---------------------------------------------------------------------------
+// CNWObjContextMenu
+//---------------------------------------------------------------------------
+
+CNWObjContextMenu::CNWObjContextMenu()
+{
+ _cRef = 1L;
+ _pDataObj = NULL;
+
+ _fGotClusterInfo = FALSE;
+ _dwTotal = 0;
+ _dwFree = 0;
+
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWObjContextMenu::CNWObjContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWObjContextMenu::~CNWObjContextMenu()
+{
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWObjContextMenu::~CNWObjContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWObjContextMenu::QueryInterface(REFIID riid, LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (LPSHELLEXTINIT)this;
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu))
+ {
+ *ppv = (LPCONTEXTMENU)this;
+ }
+ else if (IsEqualIID(riid, IID_IShellPropSheetExt))
+ {
+ *ppv = (LPSHELLPROPSHEETEXT)this;
+ }
+
+ if (*ppv)
+ {
+ AddRef();
+
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWObjContextMenu::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWObjContextMenu::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+//
+// FUNCTION: CNWObjContextMenu::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY)
+//
+// PURPOSE: Called by the shell when initializing a context menu or property
+// sheet extension.
+//
+// PARAMETERS:
+// pIDFolder - Specifies the parent folder
+// pDataObj - Spefifies the set of items selected in that folder.
+// hRegKey - Specifies the type of the focused item in the selection.
+//
+// RETURN VALUE:
+//
+// NOERROR in all cases.
+//
+// COMMENTS: Note that at the time this function is called, we don't know
+// (or care) what type of shell extension is being initialized.
+// It could be a context menu or a property sheet.
+//
+
+STDMETHODIMP CNWObjContextMenu::Initialize( LPCITEMIDLIST pIDFolder,
+ LPDATAOBJECT pDataObj,
+ HKEY hRegKey)
+{
+ // We do not need the registry handle so ignore it.
+
+ // Initialize can be called more than once
+
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ // Duplicate the object pointer
+
+ if (pDataObj)
+ {
+ _pDataObj = pDataObj;
+ pDataObj->AddRef();
+ }
+
+ return NOERROR;
+}
+
+//---------------------------------------------------------------------------
+// CNWFldContextMenuClassFactory
+//---------------------------------------------------------------------------
+
+CNWFldContextMenuClassFactory::CNWFldContextMenuClassFactory()
+{
+ _cRef = 0L;
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWFldContextMenuClassFactory::CNWFldContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWFldContextMenuClassFactory::~CNWFldContextMenuClassFactory()
+{
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWFldContextMenuClassFactory::~CNWFldContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWFldContextMenuClassFactory::QueryInterface(REFIID riid,
+ LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ // Any interface on this object is the object pointer
+
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppv = (LPCLASSFACTORY)this;
+ AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWFldContextMenuClassFactory::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWFldContextMenuClassFactory::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+STDMETHODIMP CNWFldContextMenuClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ *ppvObj = NULL;
+
+ // Shell extensions typically don't support aggregation (inheritance)
+
+ if (pUnkOuter)
+ return ResultFromScode(CLASS_E_NOAGGREGATION);
+
+ // Create the main shell extension object. The shell will then call
+ // QueryInterface with IID_IShellExtInit--this is how shell extensions are
+ // initialized.
+
+ LPCNWFLDCONTEXTMENU pShellExt = new CNWFldContextMenu(); // Create the CNWFldContextMenu object
+
+ if (NULL == pShellExt)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ //
+ // We set the reference count of CNWFldContextMenu to one at initialization.
+ // Hence, we can call Release() after QueryInterface.
+ // So, if QueryInterface failed, Release will free the object.
+ //
+
+ HRESULT hr = pShellExt->QueryInterface(riid, ppvObj);
+ pShellExt->Release();
+
+ return hr;
+}
+
+STDMETHODIMP CNWFldContextMenuClassFactory::LockServer(BOOL fLock)
+{
+ return NOERROR;
+}
+
+//---------------------------------------------------------------------------
+// CNWFldContextMenu
+//---------------------------------------------------------------------------
+
+CNWFldContextMenu::CNWFldContextMenu()
+{
+ _cRef = 1L;
+ _pDataObj = NULL;
+
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWFldContextMenu::CNWFldContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWFldContextMenu::~CNWFldContextMenu()
+{
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWFldContextMenu::~CNWFldContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWFldContextMenu::QueryInterface(REFIID riid, LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (LPSHELLEXTINIT)this;
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu))
+ {
+ *ppv = (LPCONTEXTMENU)this;
+ }
+
+ if (*ppv)
+ {
+ AddRef();
+
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWFldContextMenu::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWFldContextMenu::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+//
+// FUNCTION: CNWFldContextMenu::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY)
+//
+// PURPOSE: Called by the shell when initializing a context menu or property
+// sheet extension.
+//
+// PARAMETERS:
+// pIDFolder - Specifies the parent folder
+// pDataObj - Spefifies the set of items selected in that folder.
+// hRegKey - Specifies the type of the focused item in the selection.
+//
+// RETURN VALUE:
+//
+// NOERROR in all cases.
+//
+// COMMENTS: Note that at the time this function is called, we don't know
+// (or care) what type of shell extension is being initialized.
+// It could be a context menu or a property sheet.
+//
+
+STDMETHODIMP CNWFldContextMenu::Initialize( LPCITEMIDLIST pIDFolder,
+ LPDATAOBJECT pDataObj,
+ HKEY hRegKey)
+{
+ // We do not need the registry handle so ignore it.
+
+ // Initialize can be called more than once
+
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ // Duplicate the object pointer
+
+ if (pDataObj)
+ {
+ _pDataObj = pDataObj;
+ pDataObj->AddRef();
+ }
+
+ return NOERROR;
+}
+
+//---------------------------------------------------------------------------
+// CNWHoodContextMenuClassFactory
+//---------------------------------------------------------------------------
+
+CNWHoodContextMenuClassFactory::CNWHoodContextMenuClassFactory()
+{
+ _cRef = 0L;
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWHoodContextMenuClassFactory::CNWHoodContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWHoodContextMenuClassFactory::~CNWHoodContextMenuClassFactory()
+{
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWHoodContextMenuClassFactory::~CNWHoodContextMenuClassFactory(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWHoodContextMenuClassFactory::QueryInterface(REFIID riid,
+ LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ // Any interface on this object is the object pointer
+
+ if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
+ {
+ *ppv = (LPCLASSFACTORY)this;
+ AddRef();
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWHoodContextMenuClassFactory::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWHoodContextMenuClassFactory::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+STDMETHODIMP CNWHoodContextMenuClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
+ REFIID riid,
+ LPVOID *ppvObj)
+{
+ *ppvObj = NULL;
+
+ // Shell extensions typically don't support aggregation (inheritance)
+
+ if (pUnkOuter)
+ return ResultFromScode(CLASS_E_NOAGGREGATION);
+
+ // Create the main shell extension object. The shell will then call
+ // QueryInterface with IID_IShellExtInit--this is how shell extensions are
+ // initialized.
+
+ LPCNWHOODCONTEXTMENU pShellExt = new CNWHoodContextMenu(); // Create the CNWHoodContextMenu object
+
+ if (NULL == pShellExt)
+ return ResultFromScode(E_OUTOFMEMORY);
+
+ //
+ // We set the reference count of CNWHoodContextMenu to one at initialization.
+ // Hence, we can call Release() after QueryInterface.
+ // So, if QueryInterface failed, Release will free the object.
+ //
+
+ HRESULT hr = pShellExt->QueryInterface(riid, ppvObj);
+ pShellExt->Release();
+
+ return hr;
+}
+
+STDMETHODIMP CNWHoodContextMenuClassFactory::LockServer(BOOL fLock)
+{
+ return NOERROR;
+}
+
+//---------------------------------------------------------------------------
+// CNWHoodContextMenu
+//---------------------------------------------------------------------------
+
+CNWHoodContextMenu::CNWHoodContextMenu()
+{
+ _cRef = 1L;
+ _pDataObj = NULL;
+
+ InterlockedIncrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWHoodContextMenu::CNWHoodContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+CNWHoodContextMenu::~CNWHoodContextMenu()
+{
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ InterlockedDecrement( &g_cRefThisDll );
+
+#if DBG
+ wsprintf( szDebugStr,L"CNWHoodContextMenu::~CNWHoodContextMenu(), g_cRefThisDll = %d\r\n", g_cRefThisDll);
+ ODS( szDebugStr );
+#endif
+}
+
+STDMETHODIMP CNWHoodContextMenu::QueryInterface(REFIID riid, LPVOID FAR *ppv)
+{
+ *ppv = NULL;
+
+ if (IsEqualIID(riid, IID_IShellExtInit) || IsEqualIID(riid, IID_IUnknown))
+ {
+ *ppv = (LPSHELLEXTINIT)this;
+ }
+ else if (IsEqualIID(riid, IID_IContextMenu))
+ {
+ *ppv = (LPCONTEXTMENU)this;
+ }
+
+ if (*ppv)
+ {
+ AddRef();
+
+ return NOERROR;
+ }
+
+ return ResultFromScode(E_NOINTERFACE);
+}
+
+STDMETHODIMP_(ULONG) CNWHoodContextMenu::AddRef()
+{
+ return ++_cRef;
+}
+
+STDMETHODIMP_(ULONG) CNWHoodContextMenu::Release()
+{
+ if (--_cRef)
+ return _cRef;
+
+ delete this;
+
+ return 0L;
+}
+
+//
+// FUNCTION: CNWHoodContextMenu::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY)
+//
+// PURPOSE: Called by the shell when initializing a context menu or property
+// sheet extension.
+//
+// PARAMETERS:
+// pIDFolder - Specifies the parent folder
+// pDataObj - Spefifies the set of items selected in that folder.
+// hRegKey - Specifies the type of the focused item in the selection.
+//
+// RETURN VALUE:
+//
+// NOERROR in all cases.
+//
+// COMMENTS: Note that at the time this function is called, we don't know
+// (or care) what type of shell extension is being initialized.
+// It could be a context menu or a property sheet.
+//
+
+STDMETHODIMP CNWHoodContextMenu::Initialize( LPCITEMIDLIST pIDFolder,
+ LPDATAOBJECT pDataObj,
+ HKEY hRegKey)
+{
+ // We do not need the registry handle so ignore it.
+
+ // Initialize can be called more than once
+
+ if (_pDataObj)
+ _pDataObj->Release();
+
+ // Duplicate the object pointer
+
+ if (pDataObj)
+ {
+ _pDataObj = pDataObj;
+ pDataObj->AddRef();
+ }
+
+ return NOERROR;
+}
+