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.

503 lines
15 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: prshtext.cpp
  3. Description: DSKQUOTA property sheet extention implementation.
  4. Revision History:
  5. Date Description Programmer
  6. -------- --------------------------------------------------- ----------
  7. 08/15/96 Initial creation. BrianAu
  8. 07/03/97 Added m_hrInitialization member. BrianAu
  9. 01/23/98 Removed m_hrInitialization member. BrianAu
  10. 06/25/98 Disabled snapin code with #ifdef POLICY_MMC_SNAPIN. BrianAu
  11. Switching to ADM-file approach to entering policy
  12. data. Keeping snapin code available in case
  13. we decide to switch back at a later time.
  14. */
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #include "pch.h" // PCH
  17. #pragma hdrstop
  18. #include "dskquota.h"
  19. #include "prshtext.h"
  20. #include "guidsp.h"
  21. extern LONG g_cLockThisDll;
  22. DiskQuotaPropSheetExt::DiskQuotaPropSheetExt(
  23. VOID
  24. ) : m_cRef(0),
  25. m_dwDlgTemplateID(0),
  26. m_lpfnDlgProc(NULL),
  27. m_hPage(NULL),
  28. m_pQuotaControl(NULL),
  29. m_cOleInitialized(0)
  30. {
  31. DBGTRACE((DM_PRSHTEXT, DL_HIGH, TEXT("DiskQuotaPropSheetExt::DiskQuotaPropSheetExt")));
  32. InterlockedIncrement(&g_cRefThisDll);
  33. }
  34. ///////////////////////////////////////////////////////////////////////////////
  35. /* Function: DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt
  36. Description: Destructor for the property sheet extension class.
  37. Arguments: None.
  38. Returns: Nothing.
  39. Revision History:
  40. Date Description Programmer
  41. -------- --------------------------------------------------- ----------
  42. 08/15/96 Initial creation. BrianAu
  43. */
  44. ///////////////////////////////////////////////////////////////////////////////
  45. DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt(VOID)
  46. {
  47. DBGTRACE((DM_PRSHTEXT, DL_HIGH, TEXT("DiskQuotaPropSheetExt::~DiskQuotaPropSheetExt")));
  48. if (NULL != m_pQuotaControl)
  49. {
  50. m_pQuotaControl->Release();
  51. m_pQuotaControl = NULL;
  52. }
  53. //
  54. // Call OleUninitialize for each time OleInitialize was called in Initialize().
  55. //
  56. while(0 != m_cOleInitialized--)
  57. {
  58. DBGASSERT((0 <= m_cOleInitialized)); // Make sure we don't go negative.
  59. CoUninitialize();
  60. }
  61. InterlockedDecrement(&g_cRefThisDll);
  62. }
  63. ///////////////////////////////////////////////////////////////////////////////
  64. /* Function: DiskQuotaPropSheetExt::QueryInterface
  65. Description: Returns an interface pointer to the object's IUnknown
  66. and IShellPropSheetExt interfaces.
  67. Arguments:
  68. riid - Reference to requested interface ID.
  69. ppvOut - Address of interface pointer variable to accept interface ptr.
  70. Returns:
  71. NO_ERROR - Success.
  72. E_NOINTERFACE - Requested interface not supported.
  73. E_INVALIDARG - ppvOut argument was NULL.
  74. Revision History:
  75. Date Description Programmer
  76. -------- --------------------------------------------------- ----------
  77. 08/15/96 Initial creation. BrianAu
  78. */
  79. ///////////////////////////////////////////////////////////////////////////////
  80. STDMETHODIMP
  81. DiskQuotaPropSheetExt::QueryInterface(
  82. REFIID riid,
  83. LPVOID *ppvOut
  84. )
  85. {
  86. HRESULT hResult = E_NOINTERFACE;
  87. if (NULL == ppvOut)
  88. return E_INVALIDARG;
  89. *ppvOut = NULL;
  90. if (IID_IUnknown == riid ||
  91. IID_IShellPropSheetExt == riid
  92. #ifdef POLICY_MMC_SNAPIN
  93. || IID_ISnapInPropSheetExt == riid // This is not a "real" interface.
  94. #endif
  95. )
  96. {
  97. *ppvOut = this;
  98. }
  99. #ifdef POLICY_MMC_SNAPIN
  100. else if (IID_IDiskQuotaPolicy == riid)
  101. {
  102. hResult = CreateDiskQuotaPolicyObject(reinterpret_cast<IDiskQuotaPolicy **>(ppvOut));
  103. }
  104. #endif
  105. if (NULL != *ppvOut)
  106. {
  107. ((LPUNKNOWN)*ppvOut)->AddRef();
  108. hResult = NOERROR;
  109. }
  110. return hResult;
  111. }
  112. ///////////////////////////////////////////////////////////////////////////////
  113. /* Function: DiskQuotaPropSheetExt::AddRef
  114. Description: Increments object reference count.
  115. Arguments: None.
  116. Returns: New reference count value.
  117. Revision History:
  118. Date Description Programmer
  119. -------- --------------------------------------------------- ----------
  120. 08/15/96 Initial creation. BrianAu
  121. */
  122. ///////////////////////////////////////////////////////////////////////////////
  123. STDMETHODIMP_(ULONG)
  124. DiskQuotaPropSheetExt::AddRef(
  125. VOID
  126. )
  127. {
  128. ULONG ulReturn = m_cRef + 1;
  129. DBGPRINT((DM_COM, DL_HIGH, TEXT("DiskQuotaPropSheetExt::AddRef, 0x%08X %d -> %d\n"),
  130. this, ulReturn - 1, ulReturn));
  131. InterlockedIncrement(&m_cRef);
  132. return ulReturn;
  133. }
  134. ///////////////////////////////////////////////////////////////////////////////
  135. /* Function: DiskQuotaPropSheetExt::Release
  136. Description: Decrements object reference count. If count drops to 0,
  137. object is deleted.
  138. Arguments: None.
  139. Returns: New reference count value.
  140. Revision History:
  141. Date Description Programmer
  142. -------- --------------------------------------------------- ----------
  143. 08/15/96 Initial creation. BrianAu
  144. */
  145. ///////////////////////////////////////////////////////////////////////////////
  146. STDMETHODIMP_(ULONG)
  147. DiskQuotaPropSheetExt::Release(
  148. VOID
  149. )
  150. {
  151. ULONG ulReturn = m_cRef - 1;
  152. DBGPRINT((DM_COM, DL_HIGH, TEXT("DiskQuotaPropSheetExt::Release, 0x%08X %d -> %d\n"),
  153. this, ulReturn + 1, ulReturn));
  154. if (InterlockedDecrement(&m_cRef) == 0)
  155. {
  156. delete this;
  157. ulReturn = 0;
  158. }
  159. return ulReturn;
  160. }
  161. ///////////////////////////////////////////////////////////////////////////////
  162. /* Function: DiskQuotaPropSheetExt::Initialize
  163. Description: Initializes a new property sheet extension object.
  164. Arguments:
  165. idVolume - Reference to a CVolumeID object containing both parsable
  166. and displayable names for the volume. In the case of
  167. normal volumes, this is the same string. In the case
  168. of mounted volumes, it may not be depending on what's
  169. provided by the OS for the mounted volume. Most mounted
  170. volumes have names like "\\?\Volume{ GUID }\".
  171. dwDlgTemplateID - Resource ID for the dialog template to use for the
  172. property sheet.
  173. lpfnDlgProc - Address of dialog's window message procedure.
  174. Returns:
  175. NO_ERROR - Success.
  176. ERROR_ACCESS_DENIED (hr) - Read access denied to the device.
  177. Exceptions: OutOfMemory.
  178. Revision History:
  179. Date Description Programmer
  180. -------- --------------------------------------------------- ----------
  181. 08/15/96 Initial creation. BrianAu
  182. 06/27/98 Replaced volume name arg with CVolumeID arg to BrianAu
  183. support mounted volumes.
  184. */
  185. ///////////////////////////////////////////////////////////////////////////////
  186. HRESULT
  187. DiskQuotaPropSheetExt::Initialize(
  188. const CVolumeID& idVolume,
  189. DWORD dwDlgTemplateID,
  190. DLGPROC lpfnDlgProc
  191. )
  192. {
  193. HRESULT hResult = NO_ERROR;
  194. DBGASSERT((NULL != lpfnDlgProc));
  195. DBGASSERT((0 != dwDlgTemplateID));
  196. m_idVolume = idVolume;
  197. m_dwDlgTemplateID = dwDlgTemplateID;
  198. m_lpfnDlgProc = lpfnDlgProc;
  199. //
  200. // Volume parsing name will be blank for a snap-in prop page since
  201. // it isn't displayed on behalf of any particular volume.
  202. //
  203. if (!m_idVolume.ForParsing().IsEmpty())
  204. {
  205. hResult = CoInitialize(NULL);
  206. if (SUCCEEDED(hResult))
  207. {
  208. IDiskQuotaControl *pqc;
  209. m_cOleInitialized++; // Need to call OleUninitialize once more in dtor.
  210. //
  211. // Validate that we can use quotas by instantiating the quota control
  212. // object. If this fails the user probably doesn't have access
  213. // to manipulate quotas.
  214. //
  215. hResult = GetQuotaController(&pqc);
  216. if (SUCCEEDED(hResult))
  217. {
  218. pqc->Release();
  219. //
  220. // Also release the cached m_pQuotaControl ptr.
  221. // We don't want to hold open a handle to the volume if our
  222. // page is not active.
  223. //
  224. m_pQuotaControl->Release();
  225. m_pQuotaControl = NULL;
  226. }
  227. }
  228. }
  229. return hResult;
  230. }
  231. //
  232. // Get a pointer to the IDiskQuotaControl interface.
  233. // If the cached m_pQuotaControl ptr is non-NULL we merely AddRef this
  234. // and return it to the caller. Otherwise we CoCreate a new controller,
  235. // cache the pointer in m_pQuotaControl and return that.
  236. //
  237. // History:
  238. // Originally we opened the controller in ::Initialize() and cached
  239. // the pointer in m_pQuotaControl. The controller remained alive
  240. // until the prop SHEET was destroyed. This was holding open a handle
  241. // to the volume device which prevented the disk checking function
  242. // on the "Tools" page from accessing the volume. Therefore I
  243. // changed the code so that now we call GetQuotaController whenever
  244. // we want an IDiskQuotaControl pointer. The caller releases that
  245. // ptr when done with it. Whenever the prop page becomes inactive
  246. // we release the cached m_pQuotaControl. This ensures that the
  247. // code has the volume open only when the page is active.
  248. // [brianau - 5/21/99]
  249. //
  250. //
  251. HRESULT
  252. DiskQuotaPropSheetExt::GetQuotaController(
  253. IDiskQuotaControl **ppqc
  254. )
  255. {
  256. HRESULT hr = NOERROR;
  257. *ppqc = NULL;
  258. if (NULL == m_pQuotaControl)
  259. {
  260. //
  261. // No cached ptr. Create a new controller.
  262. //
  263. hr = CoCreateInstance(CLSID_DiskQuotaControl,
  264. NULL,
  265. CLSCTX_INPROC_SERVER,
  266. IID_IDiskQuotaControl,
  267. (LPVOID *)&m_pQuotaControl);
  268. if (SUCCEEDED(hr))
  269. {
  270. hr = m_pQuotaControl->Initialize(m_idVolume.ForParsing(), TRUE);
  271. if (FAILED(hr))
  272. {
  273. m_pQuotaControl->Release();
  274. m_pQuotaControl = NULL;
  275. }
  276. }
  277. }
  278. if (NULL != m_pQuotaControl)
  279. {
  280. //
  281. // Ptr is cached. Merely addref and return it.
  282. //
  283. *ppqc = m_pQuotaControl;
  284. static_cast<IUnknown *>(*ppqc)->AddRef();
  285. }
  286. return hr;
  287. }
  288. ///////////////////////////////////////////////////////////////////////////////
  289. /* Function: DiskQuotaPropSheetExt::AddPages
  290. Description: Called by the shell when a page is to be added to the property
  291. sheet.
  292. Arguments:
  293. lpfnAddPage - Address of a callback function provided by the shell
  294. that is to be called if the property page creation succedes.
  295. lParam - Parameter to pass to lpfnAddPage function.
  296. Returns:
  297. NO_ERROR - Success.
  298. E_FAIL - Failed to create or add page.
  299. Revision History:
  300. Date Description Programmer
  301. -------- --------------------------------------------------- ----------
  302. 08/15/96 Initial creation. BrianAu
  303. */
  304. ///////////////////////////////////////////////////////////////////////////////
  305. STDMETHODIMP
  306. DiskQuotaPropSheetExt::AddPages(
  307. LPFNADDPROPSHEETPAGE lpfnAddPage,
  308. LPARAM lParam
  309. )
  310. {
  311. HRESULT hResult = E_FAIL; // Assume failure.
  312. PROPSHEETPAGE psp;
  313. psp.dwSize = sizeof(psp);
  314. psp.dwFlags = PSP_USECALLBACK | PSP_USEREFPARENT;
  315. psp.hInstance = g_hInstDll;
  316. psp.pszTemplate = MAKEINTRESOURCE(m_dwDlgTemplateID);
  317. psp.hIcon = NULL;
  318. psp.pszTitle = NULL;
  319. psp.pfnDlgProc = m_lpfnDlgProc;
  320. psp.lParam = (LPARAM)this;
  321. psp.pcRefParent = (UINT *)& g_cRefThisDll;
  322. psp.pfnCallback = (LPFNPSPCALLBACK)PropSheetPageCallback;
  323. m_hPage = CreatePropertySheetPage(&psp);
  324. if (NULL != m_hPage)
  325. {
  326. if (!lpfnAddPage(m_hPage, lParam))
  327. {
  328. DBGERROR((TEXT("PRSHTEXT - Failed to add page.\n")));
  329. DestroyPropertySheetPage(m_hPage);
  330. m_hPage = NULL;
  331. }
  332. }
  333. else
  334. {
  335. DBGERROR((TEXT("PRSHTEXT - CreatePropertySheetPage failed.\n")));
  336. }
  337. if (NULL != m_hPage)
  338. {
  339. //
  340. // Incr ref count to keep the extension object alive.
  341. // The shell will release it as soon as the page is created.
  342. // We'll release it on PSPCB_RELEASE in PropSheetPageCallback.
  343. //
  344. AddRef();
  345. hResult = NO_ERROR;
  346. }
  347. return hResult;
  348. }
  349. ///////////////////////////////////////////////////////////////////////////////
  350. /* Function: DiskQuotaPropSheetExt::PropSheetPageCallback
  351. Description: Called by the property sheet code when the property page
  352. is being created and again when it is being destroyed. This gives the
  353. page a chance to act at these critical points. We primarily use it
  354. to call Release() on the page extension which calls the virtual
  355. destructor, ultimately destroying the VolumePropPage or FolderPropPage
  356. object.
  357. Arguments:
  358. hwnd - Always NULL (according to SDK docs).
  359. uMsg - PSPCB_CREATE = Creating page.
  360. PSPCB_RELEASE = Destroying page.
  361. ppsp - Pointer to the PROPSHEETPAGE structure for the page.
  362. Returns:
  363. Return value is ignore when uMsg is PSPCB_RELEASE.
  364. On PSPCB_CREATE, returning 0 instructs the PropertySheet to NOT
  365. display the page. 1 means OK to display page.
  366. Revision History:
  367. Date Description Programmer
  368. -------- --------------------------------------------------- ----------
  369. 09/12/96 Initial creation. BrianAu
  370. */
  371. ///////////////////////////////////////////////////////////////////////////////
  372. UINT CALLBACK
  373. DiskQuotaPropSheetExt::PropSheetPageCallback(
  374. HWND hwnd,
  375. UINT uMsg,
  376. LPPROPSHEETPAGE ppsp
  377. )
  378. {
  379. UINT uReturn = 1;
  380. DiskQuotaPropSheetExt *pThis = (DiskQuotaPropSheetExt *)ppsp->lParam;
  381. DBGASSERT((NULL != pThis));
  382. switch(uMsg)
  383. {
  384. case PSPCB_CREATE:
  385. //
  386. // uReturn == 0 means Don't create the prop page.
  387. //
  388. uReturn = pThis->OnPropSheetPageCreate(ppsp);
  389. break;
  390. case PSPCB_RELEASE:
  391. //
  392. // uReturn is ignored for this uMsg.
  393. //
  394. pThis->OnPropSheetPageRelease(ppsp);
  395. //
  396. // This will release the extension and call the virtual
  397. // destructor (which will destroy the prop page object).
  398. //
  399. pThis->Release();
  400. break;
  401. }
  402. return uReturn;
  403. }