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.

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