home *** CD-ROM | disk | FTP | other *** search
-
- /******************************************************************************\
- * This is a part of the Microsoft Source Code Samples.
- * Copyright (C) 1994-1995 Microsoft Corporation.
- * All rights reserved.
- * This source code is only intended as a supplement to
- * Microsoft Development Tools and/or WinHelp documentation.
- * See these sources for detailed information regarding the
- * Microsoft samples programs.
- \******************************************************************************/
-
- //---------------------------------------------------------------------------
- //
- // File: dropext.c
- //
- // This file contains a sample source code of context menu extension handler.
- //
- //---------------------------------------------------------------------------
-
- #include "priv.h"
-
- //
- // Initialize GUIDs (should be done only and at-least once per DLL/EXE)
- //
- #pragma data_seg(".text")
- #define INITGUID
- #include <initguid.h>
- #include "dropext.h"
- #pragma data_seg()
-
- //
- // Function prototypes
- //
- HRESULT CALLBACK DropExt_CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
-
- //
- // Global variables
- //
- UINT g_cRefThisDll = 0; // Reference count of this DLL.
- UINT g_cfNetResource = 0; // Clipboard format
-
- //---------------------------------------------------------------------------
- // LibMain
- //---------------------------------------------------------------------------
- #pragma argsused
- BOOL APIENTRY LibMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
- {
- switch(dwReason)
- {
- case DLL_PROCESS_ATTACH:
- break;
- case DLL_PROCESS_DETACH:
- break;
-
- case DLL_THREAD_DETACH:
- break;
-
- case DLL_THREAD_ATTACH:
- default:
- break;
- } // end switch()
-
- return TRUE;
- }
-
- //---------------------------------------------------------------------------
- // DllCanUnloadNow
- //---------------------------------------------------------------------------
-
- STDAPI DllCanUnloadNow(void)
- {
- return ResultFromScode((g_cRefThisDll==0) ? S_OK : S_FALSE);
- }
-
- //---------------------------------------------------------------------------
- //
- // DllGetClassObject
- //
- // This is the entry of this DLL, which all the In-Proc server DLLs should
- // export. See the description of "DllGetClassObject" of OLE 2.0 reference
- // manual for detail.
- //
- //---------------------------------------------------------------------------
-
- STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID FAR* ppvOut)
- {
- //
- // This DLL has only one class (CLSID_SampleDropExt). If a DLL supports
- // multiple classes, it should have either multiple if-statements or
- // efficient table lookup code.
- //
- if (IsEqualIID(rclsid, &CLSID_SampleDropExt))
- {
- //
- // We are supposed return the class object for this class. Instead
- // of fully implementing it in this DLL, we just call a helper
- // function in the shell DLL which creates a default class factory
- // object for us. When its CreateInstance member is called, it
- // will call back our create instance function (DropExt_CreateInstance).
- //
- return SHCreateDefClassObject(
- riid, //
- ppvOut, //
- DropExt_CreateInstance, // callback function
- &g_cRefThisDll, // reference count of this DLL
- &IID_IShellExtInit // init interface
- );
- }
-
- return ResultFromScode(E_FAIL);
- }
-
-
- //---------------------------------------------------------------------------
- //
- // CSampleDropExt class
- //
- // In C++:
- // class CSampleDropExt : protected IContextMenu, protected IShellExtInit
- // {
- // protected:
- // UINT _cRef;
- // LPDATAOBJECT _pdtobj;
- // HKEY _hkeyProgID;
- // public:
- // CSampleDropExt() _cRef(1), _pdtobj(NULL), _hkeyProgID(NULL) {};
- // ...
- // };
- //
- //---------------------------------------------------------------------------
- typedef struct _CSampleDropExt // smx
- {
- IContextMenu _ctm; // 1st base class
- IShellExtInit _sxi; // 2nd base class
- UINT _cRef; // reference count
- LPDATAOBJECT _pdtobj; // data object
- HKEY _hkeyProgID; // reg. database key to ProgID
- char _szTargetFolder[MAX_PATH];
- } CSampleDropExt, * PSAMPLEDROPEXT;
-
- #define SMX_OFFSETOF(x) ((UINT)(&((PSAMPLEDROPEXT)0)->x))
- #define PVOID2PSMX(pv,offset) ((PSAMPLEDROPEXT)(((LPBYTE)pv)-offset))
- #define PCTM2PSMX(pctm) PVOID2PSMX(pctm, SMX_OFFSETOF(_ctm))
- #define PSXI2PSMX(psxi) PVOID2PSMX(psxi, SMX_OFFSETOF(_sxi))
-
- //
- // Vtable prototype
- //
- extern IContextMenuVtbl c_SampleDropExt_CTMVtbl;
- extern IShellExtInitVtbl c_SampleDropExt_SXIVtbl;
-
- //---------------------------------------------------------------------------
- //
- // DropExt_CreateInstance
- //
- // This function is called back from within IClassFactory::CreateInstance()
- // of the default class factory object, which is created by SHCreateClassObject.
- //
- //---------------------------------------------------------------------------
-
- HRESULT CALLBACK DropExt_CreateInstance(LPUNKNOWN punkOuter,
- REFIID riid, LPVOID FAR* ppvOut)
- {
- HRESULT hres;
- PSAMPLEDROPEXT psmx;
-
- //
- // Shell extentions typically does not support aggregation.
- //
- if (punkOuter) {
- return ResultFromScode(CLASS_E_NOAGGREGATION);
- }
-
- //
- // in C++:
- // psmx = new CSampleDropExt();
- //
- psmx = LocalAlloc(LPTR, sizeof(CSampleDropExt));
- if (!psmx) {
- return ResultFromScode(E_OUTOFMEMORY);
- }
- psmx->_ctm.lpVtbl = &c_SampleDropExt_CTMVtbl;
- psmx->_sxi.lpVtbl = &c_SampleDropExt_SXIVtbl;
- psmx->_cRef = 1;
- psmx->_pdtobj = NULL;
- psmx->_hkeyProgID = NULL;
- g_cRefThisDll++;
-
- //
- // in C++:
- // hres = psmx->QueryInterface(riid, ppvOut);
- // psmx->Release();
- //
- // Note that the Release member will free the object, if QueryInterface
- // failed.
- //
- hres = c_SampleDropExt_CTMVtbl.QueryInterface(&psmx->_ctm, riid, ppvOut);
- c_SampleDropExt_CTMVtbl.Release(&psmx->_ctm);
-
- return hres; // S_OK or E_NOINTERFACE
- }
-
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::Initialize (IShellExtInit override)
- //---------------------------------------------------------------------------
- STDMETHODIMP DropExt_Initialize(LPSHELLEXTINIT psxi,
- LPCITEMIDLIST pidlFolder,
- LPDATAOBJECT pdtobj,
- HKEY hkeyProgID)
- {
- PSAMPLEDROPEXT this = PSXI2PSMX(psxi);
-
- // Initialize can be called more than once.
- if (this->_pdtobj) {
- this->_pdtobj->lpVtbl->Release(this->_pdtobj);
- }
-
- if (this->_hkeyProgID) {
- RegCloseKey(this->_hkeyProgID);
- }
-
- // Duplicate the pdtobj pointer
- if (pdtobj) {
- this->_pdtobj = pdtobj;
- pdtobj->lpVtbl->AddRef(pdtobj);
- }
-
- // Duplicate the handle
- if (hkeyProgID) {
- RegOpenKeyEx(hkeyProgID, NULL, 0L, MAXIMUM_ALLOWED, &this->_hkeyProgID);
- }
-
- // Get the path to the drop target folder
- if (pidlFolder) {
- SHGetPathFromIDList(pidlFolder, this->_szTargetFolder);
- }
-
- return NOERROR;
- }
-
- #pragma argsused
- STDMETHODIMP DropExt_QueryContextMenu(LPCONTEXTMENU pctm,
- HMENU hmenu,
- UINT indexMenu,
- UINT idCmdFirst,
- UINT idCmdLast,
- UINT uFlags)
- {
- UINT idCmd = idCmdFirst;
- InsertMenu(hmenu, indexMenu++, MF_STRING|MF_BYPOSITION, idCmd++, "Check H&DROP (dropext)");
- InsertMenu(hmenu, indexMenu++, MF_STRING|MF_BYPOSITION, idCmd++, "Check H&NRES (dropext)");
- return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_NULL, (USHORT)2));
- }
-
- //
- // Converts an offset to a string to a string pointer.
- //
- LPCSTR _Offset2Ptr(LPSTR pszBase, UINT offset, UINT * pcb)
- {
- LPSTR pszRet;
- if (offset==0) {
- pszRet = NULL;
- *pcb = 0;
- } else {
- pszRet = pszBase + offset;
- *pcb = lstrlen(pszRet) + 1;
- }
- return pszRet;
- }
-
- //
- // This is a helper routine which extracts a specified NETRESOURCE from hnres.
- //
- UINT DropExt_GetNetResource(HGLOBAL hnres, UINT iItem, LPNETRESOURCE pnresOut, UINT cbMax)
- {
- LPNRESARRAY panr = GlobalLock(hnres);
- UINT iRet = 0; // assume error
- if (hnres)
- {
- if (iItem==(UINT)-1)
- {
- iRet = panr->cItems;
- }
- else if (iItem < panr->cItems)
- {
- UINT cbProvider, cbRemoteName;
- LPCSTR pszProvider = _Offset2Ptr((LPSTR)panr, (UINT)panr->nr[iItem].lpProvider, &cbProvider);
- LPCSTR pszRemoteName = _Offset2Ptr((LPSTR)panr, (UINT)panr->nr[iItem].lpRemoteName, &cbRemoteName);
- iRet = sizeof(NETRESOURCE) + cbProvider + cbRemoteName;
- if (iRet <= cbMax)
- {
- LPSTR psz = (LPSTR)(pnresOut+1);
- *pnresOut = panr->nr[iItem];
- if (pnresOut->lpProvider) {
- pnresOut->lpProvider = psz;
- lstrcpy(psz, pszProvider);
- psz += cbProvider;
- }
- if (pnresOut->lpRemoteName) {
- pnresOut->lpRemoteName = psz;
- lstrcpy(psz, pszRemoteName);
- }
- }
- }
- GlobalUnlock(hnres);
- }
- return iRet;
- }
-
- HRESULT DropExt_CheckForHDROP(PSAMPLEDROPEXT this, HWND hwnd)
- {
- FORMATETC fmte = {
- CF_HDROP,
- (DVTARGETDEVICE FAR *)NULL,
- DVASPECT_CONTENT,
- -1,
- TYMED_HGLOBAL };
- STGMEDIUM medium;
- HRESULT hres = this->_pdtobj->lpVtbl->GetData(this->_pdtobj, &fmte, &medium);
-
- if (SUCCEEDED(hres))
- {
-
- // STGMEDIUM uses anonymous unions, which are not supported in C.
- // The code below is conditionalized to show you how the usage differs
- // between C and C++.
- #if defined (__cplusplus)
- HDROP hdrop = medium.hGlobal;
- #else
- HDROP hdrop = medium.u.hGlobal;
- #endif
-
- UINT cFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
- char szFile[MAX_PATH];
- char szBuf[MAX_PATH*2+64];
-
- DragQueryFile(hdrop, 0, szFile, sizeof(szFile));
- wsprintf(szBuf,
- "The drop target is %s.\n"
- "%d files/directories in HDROP\n"
- "The path to the first object is\n"
- "\t%s.",
- this->_szTargetFolder,
- cFiles,
- szFile);
-
- MessageBox(hwnd, szBuf, "DropExt", MB_OK);
-
- //
- // HACK: We are supposed to call ReleaseStgMedium. This is a temporary
- // hack until OLE 2.01 for Windows 95 is released.
- //
- if (medium.pUnkForRelease)
- {
- medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
- }
- else
- {
-
- // STGMEDIUM uses anonymous unions, which are not supported in C.
- // The code below is conditionalized to show you how the usage differs
- // between C and C++.
- #if defined (__cplusplus)
- GlobalFree(medium.hGlobal);
- #else
- GlobalFree(medium.u.hGlobal);
- #endif
- }
- }
- else
- {
- MessageBox(hwnd, "No file system object in the selection", "DropExt", MB_OK);
- }
-
- return hres;
- }
-
- HRESULT DropExt_CheckForHNRES(PSAMPLEDROPEXT this, HWND hwnd)
- {
- FORMATETC fmte;
- STGMEDIUM medium;
- HRESULT hres;
-
- fmte.cfFormat = (CLIPFORMAT) (g_cfNetResource ? g_cfNetResource
- : (g_cfNetResource = RegisterClipboardFormat("Net Resource")));
- fmte.ptd = (DVTARGETDEVICE FAR *)NULL;
- fmte.dwAspect = DVASPECT_CONTENT;
- fmte.lindex = -1;
- fmte.tymed = TYMED_HGLOBAL;
-
- hres = this->_pdtobj->lpVtbl->GetData(this->_pdtobj, &fmte, &medium);
-
- if (SUCCEEDED(hres))
- {
-
- // STGMEDIUM uses anonymous unions, which are not supported in C.
- // The code below is conditionalized to show you how the usage differs
- // between C and C++.
- #if defined (__cplusplus)
- HDROP hnres = medium.hGlobal;
- #else
- HDROP hnres = medium.u.hGlobal;
- #endif
-
- LPNETRESOURCE pnr = (LPNETRESOURCE)LocalAlloc(LPTR, 1024);
-
- if (pnr)
- {
- char szBuf[512];
- UINT cItems = DropExt_GetNetResource(hnres, (UINT)-1, NULL, 0);
-
- // Get the NETRESOURCE of the first item
- DropExt_GetNetResource(hnres, 0, pnr, 1024);
-
- wsprintf(szBuf,
- "%d network resource objects in HNRES\n"
- "The attributes of the first object are\n"
- "\tProvider = %s\n"
- "\tRemoteName = %s\n"
- "\tdwDisplayType = %x\n"
- "\tdwType = %x\n"
- "\tdwUsage = %x\n",
- cItems,
- pnr->lpProvider,
- pnr->lpRemoteName ? pnr->lpRemoteName : "N/A",
- pnr->dwDisplayType,
- pnr->dwType,
- pnr->dwUsage);
-
- MessageBox(hwnd, szBuf, "DropExt", MB_OK);
-
- LocalFree(pnr);
- }
- else
- {
- hres = ResultFromScode(E_OUTOFMEMORY);
- }
-
- //
- // HACK: We are supposed to call ReleaseStgMedium. This is a temporary
- // hack until OLE 2.01 for Windows 95 is released.
- //
- if (medium.pUnkForRelease)
- {
- medium.pUnkForRelease->lpVtbl->Release(medium.pUnkForRelease);
- }
- else
- {
- // STGMEDIUM uses anonymous unions, which are not supported in C.
- // The code below is conditionalized to show you how the usage differs
- // between C and C++.
- #if defined (__cplusplus)
- GlobalFree(medium.hGlobal);
- #else
- GlobalFree(medium.u.hGlobal);
- #endif
- }
- }
- else
- {
- MessageBox(hwnd, "No network objects in the selection", "DropExt", MB_OK);
- }
- return hres;
- }
-
- STDMETHODIMP DropExt_InvokeCommand(LPCONTEXTMENU pctm,
- LPCMINVOKECOMMANDINFO lpici)
- {
- PSAMPLEDROPEXT this = PCTM2PSMX(pctm);
- HRESULT hres = ResultFromScode(E_INVALIDARG); // assume error
- //
- // No need to support string based command.
- //
- if (!HIWORD(lpici->lpVerb))
- {
- UINT idCmd = LOWORD(lpici->lpVerb);
-
- switch(idCmd)
- {
- case 0:
- hres = DropExt_CheckForHDROP(this, lpici->hwnd);
- break;
-
- case 1:
- hres = DropExt_CheckForHNRES(this, lpici->hwnd);
- break;
- }
- }
- return hres;
- }
-
- #pragma argsused
- STDMETHODIMP DropExt_GetCommandString(
- LPCONTEXTMENU pctm,
- UINT idCmd,
- UINT wReserved,
- UINT FAR * pwReserved,
- LPSTR pszName,
- UINT cchMax)
- {
- return NOERROR;
- }
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::AddRef (IContextMenu override)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP_(UINT) DropExt_CTM_AddRef(LPCONTEXTMENU pctm)
- {
- PSAMPLEDROPEXT this = PCTM2PSMX(pctm);
- return ++this->_cRef;
- }
-
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::AddRef (IShellExtInit override)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP_(UINT) DropExt_SXI_AddRef(LPSHELLEXTINIT psxi)
- {
- PSAMPLEDROPEXT this = PSXI2PSMX(psxi);
- return ++this->_cRef;
- }
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::Release (IContextMenu override)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP_(UINT) DropExt_CTM_Release(LPCONTEXTMENU pctm)
- {
- PSAMPLEDROPEXT this = PCTM2PSMX(pctm);
- if (--this->_cRef) {
- return this->_cRef;
- }
-
- if (this->_pdtobj) {
- this->_pdtobj->lpVtbl->Release(this->_pdtobj);
- }
-
- if (this->_hkeyProgID) {
- RegCloseKey(this->_hkeyProgID);
- }
-
- LocalFree((HLOCAL)this);
- g_cRefThisDll--;
-
- return 0;
- }
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::Release (IShellExtInit thunk)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP_(UINT) DropExt_SXI_Release(LPSHELLEXTINIT psxi)
- {
- PSAMPLEDROPEXT this = PSXI2PSMX(psxi);
- return DropExt_CTM_Release(&this->_ctm);
- }
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::QueryInterface (IContextMenu override)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP DropExt_CTM_QueryInterface(LPCONTEXTMENU pctm, REFIID riid, LPVOID FAR* ppvOut)
- {
- PSAMPLEDROPEXT this = PCTM2PSMX(pctm);
- if (IsEqualIID(riid, &IID_IContextMenu) || IsEqualIID(riid, &IID_IUnknown))
- {
- (LPCONTEXTMENU)*ppvOut=pctm;
- this->_cRef++;
- return NOERROR;
- }
- if (IsEqualIID(riid, &IID_IShellExtInit))
- {
- (LPSHELLEXTINIT)*ppvOut=&this->_sxi;
- this->_cRef++;
- return NOERROR;
- }
- return ResultFromScode(E_NOINTERFACE);
- }
-
- //---------------------------------------------------------------------------
- // CSampleDropExt::QueryInterface (IShellExtInit thunk)
- //---------------------------------------------------------------------------
-
- STDMETHODIMP DropExt_SXI_QueryInterface(LPSHELLEXTINIT psxi, REFIID riid, LPVOID FAR* ppv)
- {
- PSAMPLEDROPEXT this = PSXI2PSMX(psxi);
- return DropExt_CTM_QueryInterface(&this->_ctm, riid, ppv);
- }
-
-
- //---------------------------------------------------------------------------
- // CSampleDropExt class : Vtables
- //---------------------------------------------------------------------------
-
- #pragma data_seg(".text")
- #pragma warn -sus
- IContextMenuVtbl c_SampleDropExt_CTMVtbl = {
- DropExt_CTM_QueryInterface,
- DropExt_CTM_AddRef,
- DropExt_CTM_Release,
- DropExt_QueryContextMenu,
- DropExt_InvokeCommand,
- DropExt_GetCommandString,
- };
-
- IShellExtInitVtbl c_SampleDropExt_SXIVtbl = {
- DropExt_SXI_QueryInterface,
- DropExt_SXI_AddRef,
- DropExt_SXI_Release,
- DropExt_Initialize
- };
- #pragma warn .sus
- #pragma data_seg()
-