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.

440 lines
12 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: dskquowd.cpp
  3. Description: Main entry point for the Windows NT Disk Quota Notification
  4. WatchDog. This DLL exports the functions ProcessGPTA and ProcessGPTW
  5. to be called periodically from WINLOGON.EXE. When invoked, the
  6. module enumerates all local and connected volumes, gathers quota
  7. statistics for each and generates email messages and/or a popup
  8. dialog as specified by system policy and the volume's quota settings.
  9. Ideally, the underlying file system could generate notifications
  10. warning users of approaching a quota limit. However, within base
  11. NT, the name used by the user for identifying a drive is unknown.
  12. Therefore, a message meaningful to the user cannot be generated
  13. by NTFS. It must be performed by the client workstation. Hence,
  14. this watchdog applet is required.
  15. Revision History:
  16. Date Description Programmer
  17. -------- --------------------------------------------------- ----------
  18. 06/22/97 Initial creation. BrianAu
  19. */
  20. ///////////////////////////////////////////////////////////////////////////////
  21. #include "precomp.hxx" // PCH
  22. #pragma hdrstop
  23. #define INITGUIDS
  24. #include "dskquota.h"
  25. #include "watchdog.h"
  26. HINSTANCE g_hInstDll; // DLL instance handle.
  27. //
  28. // Location in HKEY_CURRENT_USER for configuration and state data.
  29. // Names are #define'd in ..\common\private.h
  30. //
  31. TCHAR g_szRegSubKeyAdmin[] = G_SZ_REGSUBKEY_ADMIN;
  32. TCHAR g_szRegSubKeyUser[] = G_SZ_REGSUBKEY_USER;
  33. ///////////////////////////////////////////////////////////////////////////////
  34. /* Function: OnProcessAttach
  35. Description: Handles all tasks associated with a process attaching to
  36. the DLL.
  37. Try to keep processing time to a minimum.
  38. Arguments:
  39. hInstDll - The DLL instance handle passed to DllMain.
  40. Returns:
  41. NOERROR - Success.
  42. E_FAIL - Something failed.
  43. Revision History:
  44. Date Description Programmer
  45. -------- --------------------------------------------------- ----------
  46. 06/22/97 Initial creation. BrianAu
  47. */
  48. ///////////////////////////////////////////////////////////////////////////////
  49. HRESULT
  50. OnProcessAttach(
  51. HINSTANCE hInstDll
  52. )
  53. {
  54. HRESULT hResult = E_FAIL;
  55. //
  56. // Start IceCAP profiling.
  57. //
  58. ICAP_START_ALL;
  59. #ifdef DEBUG
  60. //
  61. // Default is DM_NONE.
  62. //
  63. SetDebugMask(DM_ASSERT | DM_ERROR);
  64. #endif
  65. g_hInstDll = hInstDll;
  66. DisableThreadLibraryCalls(hInstDll);
  67. if (FAILED(g_OleAlloc.Initialize()))
  68. {
  69. goto proc_attach_failed;
  70. }
  71. hResult = NOERROR;
  72. proc_attach_failed:
  73. NULL;
  74. return hResult;
  75. }
  76. ///////////////////////////////////////////////////////////////////////////////
  77. /* Function: OnProcessDetach
  78. Description: Handles all tasks associated with a process detaching from
  79. the DLL.
  80. Arguments: None.
  81. Returns:
  82. NOERROR - Success.
  83. E_FAIL - Something failed.
  84. Revision History:
  85. Date Description Programmer
  86. -------- --------------------------------------------------- ----------
  87. 06/22/97 Initial creation. BrianAu
  88. */
  89. ///////////////////////////////////////////////////////////////////////////////
  90. HRESULT
  91. OnProcessDetach(
  92. VOID
  93. )
  94. {
  95. HRESULT hResult = NOERROR;
  96. //
  97. // Stop IceCAP profiling.
  98. //
  99. ICAP_STOP_ALL;
  100. return hResult;
  101. }
  102. ///////////////////////////////////////////////////////////////////////////////
  103. /* Function: DllMain
  104. Description: Main entry point for OLE component server.
  105. Arguments:
  106. hInstDll - Instance handle of DLL
  107. fdwReason - Reason DllMain is being called. Can be at Process attach/
  108. detach or Thread attach/detach.
  109. lpdwReserved - Reserved.
  110. Returns:
  111. TRUE - Successful initialization.
  112. FALSE - Failed initialization.
  113. Revision History:
  114. Date Description Programmer
  115. -------- --------------------------------------------------- ----------
  116. 06/22/97 Initial creation. BrianAu
  117. */
  118. ///////////////////////////////////////////////////////////////////////////////
  119. BOOL WINAPI
  120. DllMain(
  121. HINSTANCE hInstDll,
  122. DWORD fdwReason,
  123. LPVOID lpvReserved
  124. )
  125. {
  126. BOOL bResult = FALSE;
  127. switch(fdwReason)
  128. {
  129. case DLL_PROCESS_ATTACH:
  130. DebugMsg(DM_OLE, TEXT("DSKQUOWD - DLL_PROCESS_ATTACH"));
  131. bResult = SUCCEEDED(OnProcessAttach(hInstDll));
  132. break;
  133. case DLL_THREAD_ATTACH:
  134. case DLL_THREAD_DETACH:
  135. bResult = TRUE;
  136. break;
  137. case DLL_PROCESS_DETACH:
  138. DebugMsg(DM_OLE, TEXT("DSKQUOWD - DLL_PROCESS_DETACH"));
  139. bResult = SUCCEEDED(OnProcessDetach());
  140. break;
  141. }
  142. return bResult;
  143. }
  144. BOOL
  145. ProcessGPT(
  146. HANDLE hUserToken, // User's token
  147. HKEY hKeyCurrentUser, // Registry key to the root of the user's profile
  148. LPTSTR pszGPTPath, // UNC path to the gpt
  149. BOOL bMachinePolicyOnly, // Only apply machine policy
  150. BOOL bBackgroundRefresh, // This is a background refresh - ok to do slow stuff...
  151. BOOL bDelete // Delete policy
  152. )
  153. {
  154. BOOL bResult = FALSE; // Assume failure.
  155. try
  156. {
  157. HRESULT hr;
  158. //
  159. // Create a watchdog object and tell it to run.
  160. //
  161. CWatchDog Hooch(hUserToken);
  162. hr = Hooch.Run();
  163. bResult = SUCCEEDED(hr);
  164. if (FAILED(hr))
  165. {
  166. DebugMsg(DM_ERROR,
  167. TEXT("ProcessGPT - CWatchDog::Run failed with error 0x%08X"), hr);
  168. }
  169. }
  170. catch(OutOfMemory)
  171. {
  172. //
  173. // Handle general out-of-memory exceptions.
  174. //
  175. DebugMsg(DM_ERROR, TEXT("ProcessGPT - Insufficient memory"));
  176. }
  177. catch(CString::Exception& e)
  178. {
  179. //
  180. // The CString class throws it's own exceptions.
  181. //
  182. switch(e.Reason())
  183. {
  184. case CString::Exception::Index:
  185. DebugMsg(DM_ERROR, TEXT("ProcessGPT - CString::Exception::Index"));
  186. break;
  187. case CString::Exception::Memory:
  188. DebugMsg(DM_ERROR, TEXT("ProcessGPT - CString::Exception::Memory"));
  189. break;
  190. default:
  191. DebugMsg(DM_ERROR, TEXT("ProcessGPT - CString::Exception::Unknown"));
  192. break;
  193. }
  194. }
  195. catch(...)
  196. {
  197. //
  198. // Report any general exceptions.
  199. //
  200. DebugMsg(DM_ERROR, TEXT("ProcessGPT - Unknown exception"));
  201. }
  202. return bResult;
  203. }
  204. BOOL
  205. ProcessGPTW (
  206. HANDLE hUserToken, // User's token
  207. HKEY hKeyCurrentUser, // Registry key to the root of the user's profile
  208. LPWSTR pszGPTPathW, // UNC path to the gpt
  209. BOOL bMachinePolicyOnly, // Only apply machine policy
  210. BOOL bBackgroundRefresh, // This is a background refresh - ok to do slow stuff...
  211. BOOL bDelete // Delete policy
  212. )
  213. {
  214. BOOL bResult = FALSE;
  215. LPTSTR pszGPTPath = NULL;
  216. LPSTR pszGPTPathA = NULL;
  217. try
  218. {
  219. #ifndef UNICODE
  220. //
  221. // Get the size of the buffer needed to hold pszGPTPathA as a UNICODE str.
  222. //
  223. INT cchA = WideCharToMultiByte(CP_ACP,
  224. 0,
  225. pszGPTPathW,
  226. -1,
  227. NULL,
  228. 0, NULL, NULL);
  229. //
  230. // Allocate the ANSI buffer.
  231. //
  232. LPSTR pszGPTPathA = new WCHAR[cchA];
  233. if (NULL != pszGPTPathA)
  234. {
  235. //
  236. // Now convert the UNICODE string to ANSI.
  237. //
  238. cchA = MultiByteToWideChar(CP_ACP,
  239. 0,
  240. pszGPTPathW,
  241. -1,
  242. pszGPTPathA,
  243. cchA);
  244. }
  245. pszGPTPath = pszGPTPathA;
  246. #else
  247. pszGPTPath = pszGPTPathW;
  248. #endif
  249. if (NULL != pszGPTPath && TEXT('\0') != *pszGPTPath)
  250. {
  251. //
  252. // Process the GPT using the UNICODE/Ansi-sensitive version.
  253. // ProcessGPT will trap any exceptions.
  254. //
  255. bResult = ProcessGPT(hUserToken,
  256. hKeyCurrentUser,
  257. pszGPTPath,
  258. bMachinePolicyOnly,
  259. bBackgroundRefresh,
  260. bDelete);
  261. }
  262. }
  263. catch(OutOfMemory)
  264. {
  265. //
  266. // Handle general out-of-memory exceptions.
  267. //
  268. DebugMsg(DM_ERROR, TEXT("ProcessGPTW - Insufficient memory"));
  269. }
  270. catch(...)
  271. {
  272. //
  273. // Report any general exceptions.
  274. //
  275. DebugMsg(DM_ERROR, TEXT("ProcessGPTW - Unknown exception"));
  276. }
  277. if ((LPWSTR)pszGPTPath != pszGPTPathW)
  278. {
  279. //
  280. // If pszGPTPath isn't pointing to the UNICODE version, it is either
  281. // pointing to the ANSI version or it's NULL.
  282. //
  283. Assert(NULL == pszGPTPath || pszGPTPathA == (LPSTR)pszGPTPath);
  284. delete[] pszGPTPath;
  285. }
  286. return bResult;
  287. }
  288. BOOL
  289. ProcessGPTA (
  290. HANDLE hUserToken, // User's token
  291. HKEY hKeyCurrentUser, // Registry key to the root of the user's profile
  292. LPSTR pszGPTPathA, // UNC path to the gpt
  293. BOOL bMachinePolicyOnly, // Only apply machine policy
  294. BOOL bBackgroundRefresh, // This is a background refresh - ok to do slow stuff...
  295. BOOL bDelete // Delete policy
  296. )
  297. {
  298. BOOL bResult = FALSE;
  299. LPTSTR pszGPTPath = NULL;
  300. LPWSTR pszGPTPathW = NULL;
  301. try
  302. {
  303. #ifdef UNICODE
  304. //
  305. // Get the size of the buffer needed to hold pszGPTPathA as a UNICODE str.
  306. //
  307. INT cchW = MultiByteToWideChar(CP_ACP,
  308. 0,
  309. pszGPTPathA,
  310. -1,
  311. NULL,
  312. 0);
  313. //
  314. // Allocate the UNICODE buffer.
  315. //
  316. LPWSTR pszGPTPathW = new WCHAR[cchW];
  317. if (NULL != pszGPTPathW)
  318. {
  319. //
  320. // Now convert the ANSI string to UNICODE.
  321. //
  322. cchW = MultiByteToWideChar(CP_ACP,
  323. 0,
  324. pszGPTPathA,
  325. -1,
  326. pszGPTPathW,
  327. cchW);
  328. }
  329. pszGPTPath = pszGPTPathW;
  330. #else
  331. pszGPTPath = pszGPTPathA;
  332. #endif
  333. if (NULL != pszGPTPath && TEXT('\0') != *pszGPTPath)
  334. {
  335. //
  336. // Process the GPT using the UNICODE/Ansi-sensitive version.
  337. // ProcessGPT will trap any exceptions.
  338. //
  339. bResult = ProcessGPT(hUserToken,
  340. hKeyCurrentUser,
  341. pszGPTPath,
  342. bMachinePolicyOnly,
  343. bBackgroundRefresh,
  344. bDelete);
  345. }
  346. }
  347. catch(OutOfMemory)
  348. {
  349. //
  350. // Handle general out-of-memory exceptions.
  351. //
  352. DebugMsg(DM_ERROR, TEXT("ProcessGPTA - Insufficient memory"));
  353. }
  354. catch(...)
  355. {
  356. //
  357. // Report any general exceptions.
  358. //
  359. DebugMsg(DM_ERROR, TEXT("ProcessGPTA - Unknown exception"));
  360. }
  361. if ((LPSTR)pszGPTPath != pszGPTPathA)
  362. {
  363. //
  364. // If pszGPTPath isn't pointing to the ANSI version, it is either
  365. // pointing to the UNICODE version or it's NULL.
  366. //
  367. Assert(NULL == pszGPTPath || pszGPTPathW == (LPWSTR)pszGPTPath);
  368. delete[] pszGPTPath;
  369. }
  370. return bResult;
  371. }