Source code of Windows XP (NT5)
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.

441 lines
14 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: extinit.cpp
  3. Description: Implements IShellExtInit for disk quota shell extensions.
  4. Revision History:
  5. Date Description Programmer
  6. -------- --------------------------------------------------- ----------
  7. 08/15/96 Initial creation. BrianAu
  8. */
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "pch.h" // PCH
  11. #pragma hdrstop
  12. #include "extinit.h"
  13. #include "prshtext.h"
  14. #include "volprop.h"
  15. #include "guidsp.h"
  16. ///////////////////////////////////////////////////////////////////////////////
  17. /* Function: ShellExtInit::QueryInterface
  18. Description: Returns an interface pointer to the object's IUnknown or
  19. IShellExtInit interface. Only IID_IUnknown and
  20. IID_IShellExtInit are recognized.
  21. Arguments:
  22. riid - Reference to requested interface ID.
  23. ppvOut - Address of interface pointer variable to accept interface ptr.
  24. Returns:
  25. NO_ERROR - Success.
  26. E_NOINTERFACE - Requested interface not supported.
  27. E_INVALIDARG - ppvOut argument was NULL.
  28. Revision History:
  29. Date Description Programmer
  30. -------- --------------------------------------------------- ----------
  31. 08/15/96 Initial creation. BrianAu
  32. 06/25/98 Disabled MMC snapin code. BrianAu
  33. */
  34. ///////////////////////////////////////////////////////////////////////////////
  35. STDMETHODIMP
  36. ShellExtInit::QueryInterface(
  37. REFIID riid,
  38. LPVOID *ppvOut
  39. )
  40. {
  41. HRESULT hResult = E_NOINTERFACE;
  42. if (NULL == ppvOut)
  43. return E_INVALIDARG;
  44. *ppvOut = NULL;
  45. try
  46. {
  47. if (IID_IUnknown == riid ||
  48. IID_IShellExtInit == riid)
  49. {
  50. *ppvOut = this;
  51. ((LPUNKNOWN)*ppvOut)->AddRef();
  52. hResult = NOERROR;
  53. }
  54. else if (IID_IShellPropSheetExt == riid)
  55. {
  56. //
  57. // This can throw OutOfMemory.
  58. //
  59. hResult = Create_IShellPropSheetExt(riid, ppvOut);
  60. }
  61. #ifdef POLICY_MMC_SNAPIN
  62. else if (IID_ISnapInPropSheetExt == riid)
  63. {
  64. hResult = Create_ISnapInPropSheetExt(riid, ppvOut);
  65. }
  66. #endif // POLICY_MMC_SNAPIN
  67. }
  68. catch(CAllocException& e)
  69. {
  70. hResult = E_OUTOFMEMORY;
  71. }
  72. return hResult;
  73. }
  74. ///////////////////////////////////////////////////////////////////////////////
  75. /* Function: ShellExtInit::AddRef
  76. Description: Increments object reference count.
  77. Arguments: None.
  78. Returns: New reference count value.
  79. Revision History:
  80. Date Description Programmer
  81. -------- --------------------------------------------------- ----------
  82. 08/15/96 Initial creation. BrianAu
  83. */
  84. ///////////////////////////////////////////////////////////////////////////////
  85. STDMETHODIMP_(ULONG)
  86. ShellExtInit::AddRef(
  87. VOID
  88. )
  89. {
  90. ULONG ulReturn = m_cRef + 1;
  91. DBGPRINT((DM_COM, DL_HIGH, TEXT("ShellExtInit::AddRef, 0x%08X %d -> %d\n"),
  92. this, ulReturn - 1, ulReturn));
  93. InterlockedIncrement(&m_cRef);
  94. return ulReturn;
  95. }
  96. ///////////////////////////////////////////////////////////////////////////////
  97. /* Function: ShellExtInit::Release
  98. Description: Decrements object reference count. If count drops to 0,
  99. object is deleted.
  100. Arguments: None.
  101. Returns: New reference count value.
  102. Revision History:
  103. Date Description Programmer
  104. -------- --------------------------------------------------- ----------
  105. 08/15/96 Initial creation. BrianAu
  106. */
  107. ///////////////////////////////////////////////////////////////////////////////
  108. STDMETHODIMP_(ULONG)
  109. ShellExtInit::Release(
  110. VOID
  111. )
  112. {
  113. ULONG ulReturn = m_cRef - 1;
  114. DBGPRINT((DM_COM, DL_HIGH, TEXT("ShellExtInit::Release, 0x%08X %d -> %d\n"),
  115. this, ulReturn + 1, ulReturn));
  116. if (InterlockedDecrement(&m_cRef) == 0)
  117. {
  118. delete this;
  119. ulReturn = 0;
  120. }
  121. return ulReturn;
  122. }
  123. ///////////////////////////////////////////////////////////////////////////////
  124. /* Function: ShellExtInit::Initialize
  125. Description: Called by the shell to initialize the shell extension.
  126. Arguments:
  127. pidlFolder - Pointer to IDL of selected folder. This NULL for
  128. property sheet and context menu extensions.
  129. lpDataObj - Pointer to data object containing list of selected objects.
  130. hkeyProgID - Registry key for the file object or folder type.
  131. Returns:
  132. S_OK - Success.
  133. E_FAIL - Can't initialize extension.
  134. Revision History:
  135. Date Description Programmer
  136. -------- --------------------------------------------------- ----------
  137. 08/15/96 Initial creation. BrianAu
  138. 06/28/98 Added mounted-volume support. BrianAu
  139. Includes introduction of CVolumeID object.
  140. */
  141. ///////////////////////////////////////////////////////////////////////////////
  142. STDMETHODIMP
  143. ShellExtInit::Initialize(
  144. LPCITEMIDLIST pidlFolder,
  145. LPDATAOBJECT lpDataObj,
  146. HKEY hkeyProgID)
  147. {
  148. HRESULT hResult = E_FAIL;
  149. if (NULL != lpDataObj)
  150. {
  151. //
  152. // First assume it's a normal volume ID (i.e. "C:\").
  153. // The DataObject will provide CF_HDROP if it is.
  154. //
  155. FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
  156. STGMEDIUM medium;
  157. bool bMountedVol = false;
  158. hResult = lpDataObj->GetData(&fe, &medium);
  159. if (FAILED(hResult))
  160. {
  161. //
  162. // Isn't a normal volume name. Maybe it's a mounted volume.
  163. // Mounted volume names come in on a different clipboard format
  164. // so we can treat them differently from normal volume
  165. // names like "C:\". A mounted volume name will be the path
  166. // to the folder hosting the mounted volume.
  167. // For mounted volumes, the DataObject provides CF "MountedVolume".
  168. //
  169. fe.cfFormat = (CLIPFORMAT)RegisterClipboardFormat(CFSTR_MOUNTEDVOLUME);
  170. hResult = lpDataObj->GetData(&fe, &medium);
  171. bMountedVol = SUCCEEDED(hResult);
  172. }
  173. if (SUCCEEDED(hResult))
  174. {
  175. if (1 == DragQueryFile((HDROP)medium.hGlobal, (DWORD)-1, NULL, 0))
  176. {
  177. //
  178. // Retrieve volume ID string passed in from the shell.
  179. //
  180. CString strForParsing; // Used for calling Win32 functions.
  181. CString strForDisplay; // Used for UI display.
  182. CString strFSPath; // Used when an FS path is required.
  183. DragQueryFile((HDROP)medium.hGlobal,
  184. 0,
  185. strForParsing.GetBuffer(MAX_PATH),
  186. MAX_PATH);
  187. strForParsing.ReleaseBuffer();
  188. if (!bMountedVol)
  189. {
  190. //
  191. // If it's a normal volume name like "C:\", just
  192. // use that as the display name and FS Path also.
  193. //
  194. strFSPath = strForDisplay = strForParsing;
  195. }
  196. else
  197. {
  198. //
  199. // It's a mounted volume so we need to come up with something
  200. // better than "\\?\Volume{ <guid> }\" to display.
  201. //
  202. // The UI spec says the name shall be like this:
  203. //
  204. // <label> (<mounted path>)
  205. //
  206. TCHAR szMountPtGUID[MAX_PATH] = { TEXT('\0') };
  207. GetVolumeNameForVolumeMountPoint(strForParsing,
  208. szMountPtGUID,
  209. ARRAYSIZE(szMountPtGUID));
  210. TCHAR szLabel[MAX_VOL_LABEL] = { TEXT('\0') };
  211. GetVolumeInformation(szMountPtGUID,
  212. szLabel,
  213. ARRAYSIZE(szLabel),
  214. NULL,
  215. NULL,
  216. NULL,
  217. NULL,
  218. 0);
  219. //
  220. // Format display name as:
  221. //
  222. // "VOL_LABEL (C:\MountDir)" or
  223. // "(C:\MountDir)" if no volume label is available.
  224. //
  225. // First remove any trailing backslash from the original parsing
  226. // string. It was needed for the call to get the volume mount
  227. // point but we don't want to display it in the UI.
  228. //
  229. if (!strForParsing.IsEmpty())
  230. {
  231. int iLastBS = strForParsing.Last(TEXT('\\'));
  232. if (iLastBS == strForParsing.Length() - 1)
  233. strForParsing = strForParsing.SubString(0, iLastBS);
  234. }
  235. strForDisplay.Format(g_hInstDll,
  236. IDS_FMT_MOUNTEDVOL_DISPLAYNAME,
  237. szLabel,
  238. strForParsing.Cstr());
  239. //
  240. // Remember the "C:\MountDir" form as the "FSPath".
  241. //
  242. strFSPath = strForParsing;
  243. //
  244. // From here on out, the mounted volume GUID string
  245. // is used for parsing.
  246. //
  247. strForParsing = szMountPtGUID;
  248. }
  249. //
  250. // Store the parsing and display name strings in our CVolumeID
  251. // object for convenient packaging. This way we can pass around
  252. // one object and the various parts of the UI can use either the
  253. // parsable or displayable name as they see fit. Since the
  254. // CString objects are reference-counted, all the copying doesn't
  255. // result in duplication of the actual string contents.
  256. //
  257. m_idVolume.SetNames(strForParsing, strForDisplay, strFSPath);
  258. hResult = S_OK;
  259. }
  260. ReleaseStgMedium(&medium);
  261. }
  262. }
  263. return hResult;
  264. }
  265. ///////////////////////////////////////////////////////////////////////////////
  266. /* Function: ShellExtInit::Create_IShellPropSheetExt
  267. Description: Creates a shell property sheet extension object and returns
  268. a pointer to it's IShellPropSheetExt interface.
  269. Arguments:
  270. riid - Reference to interface IID.
  271. ppvOut - Address of interface pointer variable to receive interface
  272. pointer.
  273. Returns:
  274. NO_ERROR - Success.
  275. E_FAIL - Extension initialized with something other
  276. than the name of a volume or directory.
  277. - OR -
  278. The volume or directory doesn't support quotas.
  279. Exceptions: OutOfMemory.
  280. Revision History:
  281. Date Description Programmer
  282. -------- --------------------------------------------------- ----------
  283. 08/16/96 Initial creation. BrianAu
  284. 10/07/97 Removed "access denied" and "invalid FS Ver" msgs BrianAu
  285. from prop sheet page. Only display page if
  286. volume supports quotas and quota control object
  287. can be initialized.
  288. */
  289. ///////////////////////////////////////////////////////////////////////////////
  290. HRESULT
  291. ShellExtInit::Create_IShellPropSheetExt(
  292. REFIID riid,
  293. LPVOID *ppvOut
  294. )
  295. {
  296. HRESULT hResult = E_FAIL;
  297. DWORD dwFileSysFlags = 0;
  298. TCHAR szFileSysName[MAX_PATH];
  299. if (GetVolumeInformation(m_idVolume.ForParsing(), // Volume id str [in]
  300. NULL, 0, // Don't want volume name
  301. NULL, // Don't want serial no.
  302. NULL, // Don't want max comp length.
  303. &dwFileSysFlags, // File system flags.
  304. szFileSysName,
  305. ARRAYSIZE(szFileSysName)))
  306. {
  307. //
  308. // Only continue if the volume supports quotas.
  309. //
  310. if (0 != (dwFileSysFlags & FILE_VOLUME_QUOTAS))
  311. {
  312. DiskQuotaPropSheetExt *pSheetExt = NULL;
  313. try
  314. {
  315. pSheetExt = new VolumePropPage;
  316. //
  317. // This can throw OutOfMemory.
  318. //
  319. hResult = pSheetExt->Initialize(m_idVolume,
  320. IDD_PROPPAGE_VOLQUOTA,
  321. VolumePropPage::DlgProc);
  322. if (SUCCEEDED(hResult))
  323. {
  324. hResult = pSheetExt->QueryInterface(riid, ppvOut);
  325. }
  326. }
  327. catch(CAllocException& e)
  328. {
  329. hResult = E_OUTOFMEMORY;
  330. }
  331. if (FAILED(hResult))
  332. {
  333. delete pSheetExt;
  334. *ppvOut = NULL;
  335. }
  336. }
  337. }
  338. return hResult;
  339. }
  340. #ifdef POLICY_MMC_SNAPIN
  341. HRESULT
  342. ShellExtInit::Create_ISnapInPropSheetExt(
  343. REFIID riid,
  344. LPVOID *ppvOut
  345. )
  346. {
  347. HRESULT hResult = E_FAIL;
  348. DiskQuotaPropSheetExt *pSheetExt = NULL;
  349. try
  350. {
  351. pSheetExt = new SnapInVolPropPage;
  352. hResult = pSheetExt->Initialize(NULL,
  353. IDD_PROPPAGE_POLICY,
  354. VolumePropPage::DlgProc);
  355. if (SUCCEEDED(hResult))
  356. {
  357. hResult = pSheetExt->QueryInterface(riid, ppvOut);
  358. }
  359. }
  360. catch(CAllocException& e)
  361. {
  362. hResult = E_OUTOFMEMORY;
  363. }
  364. if (FAILED(hResult))
  365. {
  366. delete pSheetExt;
  367. *ppvOut = NULL;
  368. }
  369. return hResult;
  370. }
  371. #endif // POLICY_MMC_SNAPIN