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

  1. #include "diskcopy.h"
  2. #include <shlwapip.h>
  3. #include "ids.h"
  4. #include <strsafe.h>
  5. #define INITGUID
  6. #include <initguid.h>
  7. // {59099400-57FF-11CE-BD94-0020AF85B590}
  8. DEFINE_GUID(CLSID_DriveMenuExt, 0x59099400L, 0x57FF, 0x11CE, 0xBD, 0x94, 0x00, 0x20, 0xAF, 0x85, 0xB5, 0x90);
  9. void DoRunDllThing(int _iDrive);
  10. BOOL DriveIdIsFloppy(int _iDrive);
  11. HINSTANCE g_hinst = NULL;
  12. LONG g_cRefThisDll = 0; // Reference count of this DLL.
  13. //----------------------------------------------------------------------------
  14. class CDriveMenuExt : public IContextMenu, IShellExtInit
  15. {
  16. public:
  17. CDriveMenuExt();
  18. // IUnknown
  19. STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
  20. ULONG STDMETHODCALLTYPE AddRef();
  21. ULONG STDMETHODCALLTYPE Release();
  22. // IContextMenu
  23. STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags);
  24. STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici);
  25. STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pwReserved, LPSTR pszName, UINT cchMax);
  26. // IShellExtInit
  27. STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID);
  28. private:
  29. ~CDriveMenuExt();
  30. INT _DriveFromDataObject(IDataObject *pdtobj);
  31. LONG _cRef;
  32. INT _iDrive;
  33. };
  34. CDriveMenuExt::CDriveMenuExt(): _cRef(1)
  35. {
  36. }
  37. CDriveMenuExt::~CDriveMenuExt()
  38. {
  39. }
  40. STDMETHODIMP_(ULONG) CDriveMenuExt::AddRef()
  41. {
  42. return InterlockedIncrement(&_cRef);
  43. }
  44. STDMETHODIMP_(ULONG) CDriveMenuExt::Release()
  45. {
  46. Assert( 0 != _cRef );
  47. ULONG cRef = InterlockedDecrement(&_cRef);
  48. if ( 0 == cRef )
  49. {
  50. delete this;
  51. }
  52. return cRef;
  53. }
  54. STDMETHODIMP CDriveMenuExt::QueryInterface(REFIID riid, void **ppv)
  55. {
  56. static const QITAB qit[] = {
  57. QITABENT(CDriveMenuExt, IContextMenu),
  58. QITABENT(CDriveMenuExt, IShellExtInit),
  59. { 0 },
  60. };
  61. return QISearch(this, qit, riid, ppv);
  62. }
  63. INT CDriveMenuExt::_DriveFromDataObject(IDataObject *pdtobj)
  64. {
  65. INT _iDrive = -1;
  66. STGMEDIUM medium;
  67. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  68. if (pdtobj && SUCCEEDED(pdtobj->GetData(&fmte, &medium)))
  69. {
  70. if (DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0) == 1)
  71. {
  72. TCHAR szFile[MAX_PATH];
  73. DragQueryFile((HDROP)medium.hGlobal, 0, szFile, ARRAYSIZE(szFile));
  74. Assert(lstrlen(szFile) == 3); // we are on the "Drives" class
  75. _iDrive = DRIVEID(szFile);
  76. }
  77. ReleaseStgMedium(&medium);
  78. }
  79. return _iDrive;
  80. }
  81. STDMETHODIMP CDriveMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
  82. {
  83. _iDrive = _DriveFromDataObject(pdtobj);
  84. if ((_iDrive >= 0) &&
  85. (_iDrive < 26) &&
  86. !DriveIdIsFloppy(_iDrive))
  87. {
  88. _iDrive = -1; // Copy Disk only works on floppies
  89. }
  90. return S_OK;
  91. }
  92. STDMETHODIMP CDriveMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
  93. {
  94. int cEntries = 0;
  95. if (_iDrive >= 0 &&
  96. _iDrive < 26)
  97. {
  98. TCHAR szMenu[64];
  99. LoadString(g_hinst, IDS_DISKCOPYMENU, szMenu, ARRAYSIZE(szMenu));
  100. // this will end up right above "Format Disk..."
  101. InsertMenu(hmenu, indexMenu++, MF_SEPARATOR | MF_BYPOSITION, idCmdFirst, szMenu);
  102. InsertMenu(hmenu, indexMenu++, MF_STRING | MF_BYPOSITION, idCmdFirst + 1, szMenu);
  103. cEntries = 2;
  104. }
  105. return ResultFromShort(cEntries);
  106. }
  107. STDMETHODIMP CDriveMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
  108. {
  109. HRESULT hr;
  110. if (HIWORD(pici->lpVerb) == 0)
  111. {
  112. DoRunDllThing(_iDrive);
  113. hr = S_OK;
  114. }
  115. else
  116. {
  117. hr = E_INVALIDARG;
  118. }
  119. return hr;
  120. }
  121. STDMETHODIMP CDriveMenuExt::GetCommandString(UINT_PTR idCmd, UINT uType,
  122. UINT *pwReserved, LPSTR pszName, UINT cchMax)
  123. {
  124. switch(uType)
  125. {
  126. case GCS_HELPTEXTA:
  127. LoadStringA(g_hinst, IDS_HELPSTRING, pszName, cchMax);
  128. break;
  129. case GCS_VERBA:
  130. LoadStringA(g_hinst, IDS_VERBSTRING, pszName, cchMax);
  131. break;
  132. case GCS_HELPTEXTW:
  133. return(LoadStringW(g_hinst, IDS_HELPSTRING, (LPWSTR)pszName, cchMax));
  134. break;
  135. case GCS_VERBW:
  136. LoadStringW(g_hinst, IDS_VERBSTRING, (LPWSTR)pszName, cchMax);
  137. break;
  138. case GCS_VALIDATEA:
  139. case GCS_VALIDATEW:
  140. default:
  141. break;
  142. }
  143. return S_OK;
  144. }
  145. STDAPI CDriveMenuExt_CreateInstance(IUnknown* punkOuter, REFIID riid, void **ppv)
  146. {
  147. if (punkOuter)
  148. return CLASS_E_NOAGGREGATION;
  149. CDriveMenuExt *pdme = new CDriveMenuExt;
  150. if (!pdme)
  151. return E_OUTOFMEMORY;
  152. HRESULT hr = pdme->QueryInterface(riid, ppv);
  153. pdme->Release();
  154. return hr;
  155. }
  156. // static class factory (no allocs!)
  157. class ClassFactory : public IClassFactory
  158. {
  159. public:
  160. ClassFactory() : _cRef(1) {}
  161. ~ClassFactory() {}
  162. // IUnknown
  163. STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
  164. ULONG STDMETHODCALLTYPE AddRef();
  165. ULONG STDMETHODCALLTYPE Release();
  166. // IClassFactory
  167. STDMETHODIMP CreateInstance (IUnknown *punkOuter, REFIID riid, void **ppv);
  168. STDMETHODIMP LockServer(BOOL fLock);
  169. private:
  170. LONG _cRef;
  171. };
  172. STDMETHODIMP_(ULONG) ClassFactory::AddRef()
  173. {
  174. return InterlockedIncrement(&_cRef);
  175. }
  176. STDMETHODIMP_(ULONG) ClassFactory::Release()
  177. {
  178. Assert( 0 != _cRef );
  179. ULONG cRef = InterlockedDecrement(&_cRef);
  180. if ( 0 == cRef )
  181. {
  182. delete this;
  183. }
  184. return cRef;
  185. }
  186. STDMETHODIMP ClassFactory::QueryInterface(REFIID riid, void **ppv)
  187. {
  188. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  189. {
  190. *ppv = static_cast<IClassFactory*>(this);
  191. }
  192. else
  193. {
  194. *ppv = NULL;
  195. return E_NOINTERFACE;
  196. }
  197. reinterpret_cast<IUnknown*>(*ppv)->AddRef();
  198. return S_OK;
  199. }
  200. STDMETHODIMP ClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  201. {
  202. return CDriveMenuExt_CreateInstance(punkOuter, riid, ppv);
  203. }
  204. STDMETHODIMP ClassFactory::LockServer(BOOL fLock)
  205. {
  206. if (fLock)
  207. {
  208. InterlockedIncrement(&g_cRefThisDll);
  209. }
  210. else
  211. {
  212. Assert( 0 != g_cRefThisDll );
  213. InterlockedDecrement(&g_cRefThisDll);
  214. }
  215. return S_OK;
  216. }
  217. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  218. {
  219. HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
  220. *ppv = NULL;
  221. if (IsEqualGUID(rclsid, CLSID_DriveMenuExt))
  222. {
  223. ClassFactory* ccf = new ClassFactory;
  224. if (ccf)
  225. {
  226. hr = ccf->QueryInterface(riid, ppv);
  227. ccf->Release();
  228. }
  229. }
  230. return hr;
  231. }
  232. STDAPI DllCanUnloadNow(void)
  233. {
  234. return g_cRefThisDll == 0 ? S_OK : S_FALSE;
  235. }
  236. TCHAR const c_szParamTemplate[] = TEXT("%s,DiskCopyRunDll %d");
  237. void DoRunDllThing(int _iDrive)
  238. {
  239. if (_iDrive >= 0 && _iDrive < 26)
  240. {
  241. TCHAR szModule[MAX_PATH];
  242. int cchModule = GetModuleFileName(g_hinst, szModule, ARRAYSIZE(szModule));
  243. if (cchModule > 0 &&
  244. cchModule < ARRAYSIZE(szModule))
  245. {
  246. TCHAR szParam[MAX_PATH + ARRAYSIZE(c_szParamTemplate)];
  247. if (SUCCEEDED(StringCchPrintf(szParam, ARRAYSIZE(szParam),
  248. c_szParamTemplate, szModule, _iDrive)))
  249. {
  250. SHELLEXECUTEINFO shexinfo = {0};
  251. shexinfo.cbSize = sizeof (shexinfo);
  252. shexinfo.fMask = SEE_MASK_DOENVSUBST;
  253. shexinfo.nShow = SW_SHOWNORMAL;
  254. shexinfo.lpFile = L"%windir%\\system32\\rundll32.exe";
  255. shexinfo.lpParameters = szParam;
  256. ShellExecuteEx(&shexinfo);
  257. }
  258. }
  259. }
  260. }
  261. // allow command lines to do diskcopy, use the syntax:
  262. // rundll32.dll diskcopy.dll,DiskCopyRunDll
  263. void WINAPI DiskCopyRunDll(HWND hwndStub, HINSTANCE hAppInstance, LPSTR pszCmdLine, int nCmdShow)
  264. {
  265. int iDrive;
  266. if (StrToIntExA(pszCmdLine, STIF_DEFAULT, &iDrive) &&
  267. iDrive >= 0 &&
  268. iDrive < 26)
  269. {
  270. SHCopyDisk(NULL, iDrive, iDrive, 0);
  271. }
  272. }
  273. void WINAPI DiskCopyRunDllW(HWND hwndStub, HINSTANCE hAppInstance, LPWSTR pwszCmdLine, int nCmdShow)
  274. {
  275. int iDrive;
  276. if (StrToIntExW(pwszCmdLine, STIF_DEFAULT, &iDrive) &&
  277. iDrive >= 0 &&
  278. iDrive < 26)
  279. {
  280. SHCopyDisk(NULL, iDrive, iDrive, 0);
  281. }
  282. }