218 lines
4.8 KiB
C++
218 lines
4.8 KiB
C++
|
//+-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1998 - 1999
|
||
|
//
|
||
|
// File: shellext.cpp
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
|
||
|
|
||
|
#include "pch.h"
|
||
|
#include "util.h"
|
||
|
#include "dsuiwiz.h"
|
||
|
#include "shellext.h"
|
||
|
#include "delegwiz.h"
|
||
|
|
||
|
|
||
|
|
||
|
//#define _MMC_HACK
|
||
|
|
||
|
#ifdef _MMC_HACK
|
||
|
|
||
|
BOOL CALLBACK EnumThreadWndProc(HWND hwnd, /* enumerated HWND */
|
||
|
LPARAM lParam /* pass a HWND* for return value*/ )
|
||
|
{
|
||
|
ASSERT(hwnd);
|
||
|
HWND hParentWnd = GetParent(hwnd);
|
||
|
// the main window of the MMC console should staitsfy this condition
|
||
|
if ( ((hParentWnd == GetDesktopWindow()) || (hParentWnd == NULL)) && IsWindowVisible(hwnd) )
|
||
|
{
|
||
|
HWND* pH = (HWND*)lParam;
|
||
|
*pH = hwnd;
|
||
|
return FALSE; // stop enumerating
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
HWND FindMMCMainWindow()
|
||
|
{
|
||
|
DWORD dwThreadID = ::GetCurrentThreadId();
|
||
|
ASSERT(dwThreadID != 0);
|
||
|
HWND hWnd = NULL;
|
||
|
BOOL bEnum = EnumThreadWindows(dwThreadID, EnumThreadWndProc,(LPARAM)&hWnd);
|
||
|
ASSERT(hWnd != NULL);
|
||
|
return hWnd;
|
||
|
}
|
||
|
|
||
|
#endif // _MMC_HACK
|
||
|
|
||
|
HWND _GetParentWindow(LPDATAOBJECT pDataObj )
|
||
|
{
|
||
|
HWND hWnd = NULL;
|
||
|
STGMEDIUM ObjMedium = {TYMED_NULL};
|
||
|
FORMATETC fmte = {(CLIPFORMAT)_Module.GetCfParentHwnd(),
|
||
|
NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
||
|
|
||
|
if (SUCCEEDED(pDataObj->GetData(&fmte, &ObjMedium)))
|
||
|
{
|
||
|
hWnd = *((HWND*)ObjMedium.hGlobal);
|
||
|
::ReleaseStgMedium(&ObjMedium);
|
||
|
}
|
||
|
#ifdef _MMC_HACK
|
||
|
if (hWnd == NULL)
|
||
|
hWnd = FindMMCMainWindow();
|
||
|
#endif
|
||
|
return hWnd;
|
||
|
}
|
||
|
|
||
|
HRESULT _GetObjectLDAPPath(IDataObject* pDataObj, CWString& szLDAPPath)
|
||
|
{
|
||
|
TRACE(L"entering _GetObjectLDAPPath()\n");
|
||
|
if (pDataObj == NULL)
|
||
|
{
|
||
|
// no data object, no name
|
||
|
szLDAPPath = L"";
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
//crack the data object and get the name
|
||
|
STGMEDIUM ObjMedium = {TYMED_NULL};
|
||
|
FORMATETC fmte = {(CLIPFORMAT)_Module.GetCfDsObjectNames(),
|
||
|
NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
|
||
|
// Get the path to the DS object from the data object.
|
||
|
HRESULT hr = pDataObj->GetData(&fmte, &ObjMedium);
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
LPDSOBJECTNAMES pDsObjectNames = (LPDSOBJECTNAMES)ObjMedium.hGlobal;
|
||
|
if (pDsObjectNames->cItems == 1)
|
||
|
{
|
||
|
LPCWSTR lpsz = (LPCWSTR)ByteOffset(pDsObjectNames,
|
||
|
pDsObjectNames->aObjects[0].offsetName);
|
||
|
if ((lpsz == NULL) || (lpsz[0] == NULL))
|
||
|
{
|
||
|
szLDAPPath = L"";
|
||
|
hr = E_INVALIDARG;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
szLDAPPath = lpsz;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
szLDAPPath = L"";
|
||
|
hr = E_INVALIDARG;
|
||
|
}
|
||
|
::ReleaseStgMedium(&ObjMedium);
|
||
|
}
|
||
|
|
||
|
TRACE(L"returning from _GetObjectLDAPPath(_, %s), hr = 0x%x\n", (LPCWSTR)szLDAPPath, hr);
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
// IShellExtInit methods
|
||
|
|
||
|
STDMETHODIMP CShellExt::Initialize(
|
||
|
LPCITEMIDLIST pidlFolder,
|
||
|
LPDATAOBJECT lpdobj,
|
||
|
HKEY hKeyProgID)
|
||
|
{
|
||
|
if (lpdobj == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
m_hParentWnd = _GetParentWindow(lpdobj);
|
||
|
|
||
|
if ((m_hParentWnd == NULL) || !::IsWindow(m_hParentWnd))
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
return _GetObjectLDAPPath(lpdobj, m_szObjectLDAPPath);
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////
|
||
|
// IContextMenu methods
|
||
|
|
||
|
STDMETHODIMP CShellExt::QueryContextMenu(
|
||
|
HMENU hMenu,
|
||
|
UINT indexMenu,
|
||
|
UINT idCmdFirst,
|
||
|
UINT idCmdLast,
|
||
|
UINT uFlags)
|
||
|
{
|
||
|
// only one menu item to insert (position zero)
|
||
|
TCHAR szContextMenu[128];
|
||
|
LoadStringHelper(IDS_DELEGWIZ_CONTEXT_MENU, szContextMenu, ARRAYSIZE(szContextMenu));
|
||
|
UINT countMenuItems = 1;
|
||
|
::InsertMenu(hMenu, indexMenu, MF_STRING | MF_BYPOSITION,
|
||
|
idCmdFirst /* + 0*/, szContextMenu);
|
||
|
|
||
|
return MAKE_SCODE(SEVERITY_SUCCESS, 0, countMenuItems);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
STDMETHODIMP CShellExt::GetCommandString(
|
||
|
UINT_PTR idCmd,
|
||
|
UINT uFlags,
|
||
|
UINT * reserved,
|
||
|
LPSTR pszName,
|
||
|
UINT cchMax)
|
||
|
{
|
||
|
if (uFlags != GCS_HELPTEXT)
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Copy the requested string to the caller's buffer.
|
||
|
//
|
||
|
if (idCmd == 0) // we inserted the zero-th element
|
||
|
{
|
||
|
// this is really WCHAR, as Jim swears, so lets trust him...
|
||
|
LPWSTR lpszHack = (LPWSTR)pszName;
|
||
|
if (::LoadStringHelper(IDS_DELEGWIZ_CONTEXT_MENU_DESCR,
|
||
|
lpszHack, cchMax))
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
return E_INVALIDARG;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
STDMETHODIMP CShellExt::InvokeCommand(
|
||
|
LPCMINVOKECOMMANDINFO lpcmi)
|
||
|
{
|
||
|
if (lpcmi == NULL)
|
||
|
return E_INVALIDARG;
|
||
|
|
||
|
|
||
|
//Check if you have read and write permission
|
||
|
if( InitCheckAccess(m_hParentWnd, m_szObjectLDAPPath) != S_OK )
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
if (!HIWORD(lpcmi->lpVerb))
|
||
|
{
|
||
|
UINT iCmd = LOWORD(lpcmi->lpVerb);
|
||
|
if (iCmd == 0)
|
||
|
{
|
||
|
ASSERT(m_hParentWnd != NULL);
|
||
|
CDelegWiz delegWiz;
|
||
|
delegWiz.InitFromLDAPPath(m_szObjectLDAPPath);
|
||
|
delegWiz.DoModal(m_hParentWnd);
|
||
|
}
|
||
|
}
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|