Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

336 lines
8.7 KiB

#include "diskcopy.h"
#include <shlwapip.h>
#include "ids.h"
#include <strsafe.h>
#define INITGUID
#include <initguid.h>
// {59099400-57FF-11CE-BD94-0020AF85B590}
DEFINE_GUID(CLSID_DriveMenuExt, 0x59099400L, 0x57FF, 0x11CE, 0xBD, 0x94, 0x00, 0x20, 0xAF, 0x85, 0xB5, 0x90);
void DoRunDllThing(int _iDrive);
BOOL DriveIdIsFloppy(int _iDrive);
HINSTANCE g_hinst = NULL;
LONG g_cRefThisDll = 0; // Reference count of this DLL.
//----------------------------------------------------------------------------
class CDriveMenuExt : public IContextMenu, IShellExtInit
{
public:
CDriveMenuExt();
// IUnknown
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IContextMenu
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
// IShellExtInit
STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID);
private:
~CDriveMenuExt();
INT _DriveFromDataObject(IDataObject *pdtobj);
LONG _cRef;
INT _iDrive;
};
CDriveMenuExt::CDriveMenuExt(): _cRef(1)
{
}
CDriveMenuExt::~CDriveMenuExt()
{
}
STDMETHODIMP_(ULONG) CDriveMenuExt::AddRef()
{
return InterlockedIncrement(&_cRef);
}
STDMETHODIMP_(ULONG) CDriveMenuExt::Release()
{
Assert( 0 != _cRef );
ULONG cRef = InterlockedDecrement(&_cRef);
if ( 0 == cRef )
{
delete this;
}
return cRef;
}
STDMETHODIMP CDriveMenuExt::QueryInterface(REFIID riid, void **ppv)
{
static const QITAB qit[] = {
QITABENT(CDriveMenuExt, IContextMenu),
QITABENT(CDriveMenuExt, IShellExtInit),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}
INT CDriveMenuExt::_DriveFromDataObject(IDataObject *pdtobj)
{
INT _iDrive = -1;
STGMEDIUM medium;
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
if (pdtobj && SUCCEEDED(pdtobj->GetData(&fmte, &medium)))
{
if (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0) == 1)
{
TCHAR szFile[MAX_PATH];
DragQueryFile((HDROP)medium.hGlobal, 0, szFile, ARRAYSIZE(szFile));
Assert(lstrlen(szFile) == 3); // we are on the "Drives" class
_iDrive = DRIVEID(szFile);
}
ReleaseStgMedium(&medium);
}
return _iDrive;
}
STDMETHODIMP CDriveMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
{
_iDrive = _DriveFromDataObject(pdtobj);
if ((_iDrive >= 0) &&
(_iDrive < 26) &&
!DriveIdIsFloppy(_iDrive))
{
_iDrive = -1; // Copy Disk only works on floppies
}
return S_OK;
}
STDMETHODIMP CDriveMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
{
int cEntries = 0;
if (_iDrive >= 0 &&
_iDrive < 26)
{
TCHAR szMenu[64];
LoadString(g_hinst, IDS_DISKCOPYMENU, szMenu, ARRAYSIZE(szMenu));
// this will end up right above "Format Disk..."
InsertMenu(hmenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, idCmdFirst, szMenu);
InsertMenu(hmenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + 1, szMenu);
cEntries = 2;
}
return ResultFromShort(cEntries);
}
STDMETHODIMP CDriveMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
HRESULT hr;
if (HIWORD(pici->lpVerb) == 0)
{
DoRunDllThing(_iDrive);
hr = S_OK;
}
else
{
hr = E_INVALIDARG;
}
return hr;
}
STDMETHODIMP CDriveMenuExt::GetCommandString(UINT_PTR idCmd, UINT uType,
UINT *pwReserved, LPSTR pszName, UINT cchMax)
{
switch(uType)
{
case GCS_HELPTEXTA:
LoadStringA(g_hinst, IDS_HELPSTRING, pszName, cchMax);
break;
case GCS_VERBA:
LoadStringA(g_hinst, IDS_VERBSTRING, pszName, cchMax);
break;
case GCS_HELPTEXTW:
return(LoadStringW(g_hinst, IDS_HELPSTRING, (LPWSTR)pszName, cchMax));
break;
case GCS_VERBW:
LoadStringW(g_hinst, IDS_VERBSTRING, (LPWSTR)pszName, cchMax);
break;
case GCS_VALIDATEA:
case GCS_VALIDATEW:
default:
break;
}
return S_OK;
}
STDAPI CDriveMenuExt_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppv)
{
if (punkOuter)
return CLASS_E_NOAGGREGATION;
CDriveMenuExt *pdme = new CDriveMenuExt;
if (!pdme)
return E_OUTOFMEMORY;
HRESULT hr = pdme->QueryInterface(riid, ppv);
pdme->Release();
return hr;
}
// static class factory (no allocs!)
class ClassFactory : public IClassFactory
{
public:
ClassFactory() : _cRef(1) {}
~ClassFactory() {}
// IUnknown
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
ULONG STDMETHODCALLTYPE AddRef();
ULONG STDMETHODCALLTYPE Release();
// IClassFactory
STDMETHODIMP CreateInstance (IUnknown *punkOuter, REFIID riid, void **ppv);
STDMETHODIMP LockServer(BOOL fLock);
private:
LONG _cRef;
};
STDMETHODIMP_(ULONG) ClassFactory::AddRef()
{
return InterlockedIncrement(&_cRef);
}
STDMETHODIMP_(ULONG) ClassFactory::Release()
{
Assert( 0 != _cRef );
ULONG cRef = InterlockedDecrement(&_cRef);
if ( 0 == cRef )
{
delete this;
}
return cRef;
}
STDMETHODIMP ClassFactory::QueryInterface(REFIID riid, void **ppv)
{
if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
{
*ppv = static_cast<IClassFactory*>(this);
}
else
{
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
STDMETHODIMP ClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
{
return CDriveMenuExt_CreateInstance(punkOuter, riid, ppv);
}
STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
{
if (fLock)
{
InterlockedIncrement(&g_cRefThisDll);
}
else
{
Assert( 0 != g_cRefThisDll );
InterlockedDecrement(&g_cRefThisDll);
}
return S_OK;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
{
HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
*ppv = NULL;
if (IsEqualGUID(rclsid, CLSID_DriveMenuExt))
{
ClassFactory* ccf = new ClassFactory;
if (ccf)
{
hr = ccf->QueryInterface(riid, ppv);
ccf->Release();
}
}
return hr;
}
STDAPI DllCanUnloadNow(void)
{
return g_cRefThisDll == 0 ? S_OK : S_FALSE;
}
TCHAR const c_szParamTemplate[] = TEXT("%s,DiskCopyRunDll %d");
void DoRunDllThing(int _iDrive)
{
if (_iDrive >= 0 && _iDrive < 26)
{
TCHAR szModule[MAX_PATH];
int cchModule = GetModuleFileName(g_hinst, szModule, ARRAYSIZE(szModule));
if (cchModule > 0 &&
cchModule < ARRAYSIZE(szModule))
{
TCHAR szParam[MAX_PATH + ARRAYSIZE(c_szParamTemplate)];
if (SUCCEEDED(StringCchPrintf(szParam, ARRAYSIZE(szParam),
c_szParamTemplate, szModule, _iDrive)))
{
SHELLEXECUTEINFO shexinfo = {0};
shexinfo.cbSize = sizeof (shexinfo);
shexinfo.fMask = SEE_MASK_DOENVSUBST;
shexinfo.nShow = SW_SHOWNORMAL;
shexinfo.lpFile = L"%windir%\\system32\\rundll32.exe";
shexinfo.lpParameters = szParam;
ShellExecuteEx(&shexinfo);
}
}
}
}
// allow command lines to do diskcopy, use the syntax:
// rundll32.dll diskcopy.dll,DiskCopyRunDll
void WINAPI DiskCopyRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
{
int iDrive;
if (StrToIntExA(pszCmdLine, STIF_DEFAULT, &iDrive) &&
iDrive >= 0 &&
iDrive < 26)
{
SHCopyDisk(NULL, iDrive, iDrive, 0);
}
}
void WINAPI DiskCopyRunDllW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR pwszCmdLine, int nCmdShow)
{
int iDrive;
if (StrToIntExW(pwszCmdLine, STIF_DEFAULT, &iDrive) &&
iDrive >= 0 &&
iDrive < 26)
{
SHCopyDisk(NULL, iDrive, iDrive, 0);
}
}