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.

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