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.

566 lines
16 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. /* File: utils.cpp
  3. Description: Contains any general utility functions applicable to the
  4. dskquota project.
  5. Revision History:
  6. Date Description Programmer
  7. -------- --------------------------------------------------- ----------
  8. 08/06/96 Initial creation. BrianAu
  9. */
  10. ///////////////////////////////////////////////////////////////////////////////
  11. #include "pch.h" // PCH
  12. #pragma hdrstop
  13. #include "resource.h"
  14. #include "dskquota.h"
  15. #include <advpub.h> // For REGINSTALL
  16. #include <sddl.h>
  17. //
  18. // Verify that build is UNICODE.
  19. //
  20. #if !defined(UNICODE)
  21. # error This module must be compiled UNICODE.
  22. #endif
  23. ///////////////////////////////////////////////////////////////////////////////
  24. /* Function: SidToString
  25. Description: Format a SID as a character string suitable for character
  26. output. This code was taken from MSDN KB article Q131320.
  27. Arguments:
  28. pSid - Address of SID to format.
  29. pszSid - Address of output buffer for formatted SID.
  30. Returns:
  31. TRUE - Success.
  32. FALSE - Destination buffer too small, invalid SID or pSid == NULL.
  33. Revision History:
  34. Date Description Programmer
  35. -------- --------------------------------------------------- ----------
  36. 07/07/96 Initial creation. BrianAu
  37. 02/26/02 Call ConvertSidToStringSid. BrianAu
  38. */
  39. ///////////////////////////////////////////////////////////////////////////////
  40. BOOL SidToString(
  41. PSID pSid,
  42. LPTSTR pszSid,
  43. LPDWORD pcchBuffer
  44. )
  45. {
  46. LPTSTR pszSidTemp;
  47. BOOL bResult = ConvertSidToStringSid(pSid, &pszSidTemp);
  48. if (bResult)
  49. {
  50. //
  51. // check provided buffer length.
  52. // If not large enough, indicate proper size and setlasterror
  53. //
  54. const DWORD cchSid = lstrlen(pszSidTemp) + 1;
  55. if (*pcchBuffer < cchSid)
  56. {
  57. *pcchBuffer = cchSid;
  58. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  59. bResult = FALSE;
  60. }
  61. else
  62. {
  63. lstrcpyn(pszSid, pszSidTemp, *pcchBuffer);
  64. }
  65. LocalFree(pszSidTemp);
  66. }
  67. return bResult;
  68. }
  69. ///////////////////////////////////////////////////////////////////////////////
  70. /* Function: CreateSidList
  71. Description: Creates a structure required for the SID list argument to
  72. NtQueryQuotaInformationFile. The caller passes the address of an
  73. array of SID pointers. The function allocates an sufficient array
  74. and creates the following formatted structure:
  75. +--------+--------+--------+--------+--------+--------+-+
  76. | SID[0] | SID[1] | SID[2] | | |SID[n-1]|0|
  77. +--------+--------+--------+--------+--------+--------+-+
  78. | |
  79. | |
  80. / \
  81. / -------------------------------
  82. / \
  83. / \
  84. +------------+------------+-----------------------------+
  85. | Next entry | SID length | SID |
  86. | offset | (DWORD) | (variable length) |
  87. | (DWORD) | | |
  88. +------------+------------+-----------------------------+
  89. Arguments:
  90. rgpSids - Array of SID pointers.
  91. cpSids - Number of pointers in rgpSids. If 0, the array must
  92. contain a terminating NULL pointer.
  93. ppSidList - Address of a PSIDLIST pointer variable to receive
  94. the address of the final structure. The caller is reponsible
  95. for deleting the returned buffer using "delete".
  96. pcbSidList - Address of DWORD varible to receive the byte count
  97. for the returned SidList structure. If the function returns
  98. hresult ERROR_INVALID_SID, the index in the source array of the invalid
  99. SID will be returned at this location.
  100. Returns:
  101. NO_ERROR - Success.
  102. ERROR_INVALID_SID (hr) - An invalid SID was found in rgpSids. The
  103. index of the invalid SID is returned in *pcbSidList.
  104. Exceptions: OutOfMemory.
  105. Revision History:
  106. Date Description Programmer
  107. -------- --------------------------------------------------- ----------
  108. 08/13/96 Initial creation. BrianAu
  109. 09/05/96 Added exception handling. BrianAu
  110. */
  111. ///////////////////////////////////////////////////////////////////////////////
  112. HRESULT
  113. CreateSidList(
  114. PSID *rgpSids,
  115. DWORD cpSids,
  116. PSIDLIST *ppSidList,
  117. LPDWORD pcbSidList
  118. )
  119. {
  120. HRESULT hResult = NO_ERROR;
  121. DBGASSERT((NULL != rgpSids));
  122. DBGASSERT((NULL != ppSidList));
  123. DBGASSERT((NULL != pcbSidList));
  124. DWORD cbBuffer = 0;
  125. PBYTE pbBuffer = NULL;
  126. //
  127. // Initialize return values.
  128. //
  129. *ppSidList = NULL;
  130. *pcbSidList = 0;
  131. //
  132. // If caller passed 0 for cpSids, list is NULL-terminated.
  133. // Set cpSids to a large value so it is not a factor in controlling the
  134. // byte-counter loop.
  135. //
  136. if (0 == cpSids)
  137. cpSids = (DWORD)~0;
  138. //
  139. // Count how many bytes we'll need to create the SID list.
  140. // Note that a NULL SID pointer at any array location
  141. // will truncate all following SIDs from the final list. Just like strncpy
  142. // with character strings.
  143. //
  144. for (UINT i = 0; NULL != rgpSids[i] && i < cpSids; i++)
  145. {
  146. if (IsValidSid(rgpSids[i]))
  147. {
  148. cbBuffer += (sizeof(DWORD) + sizeof(DWORD) + GetLengthSid(rgpSids[i]));
  149. }
  150. else
  151. {
  152. //
  153. // Tell caller they passed a ptr to an invalid SID and also tell them
  154. // which one it was.
  155. //
  156. hResult = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
  157. *pcbSidList = i;
  158. break;
  159. }
  160. }
  161. //
  162. // Reset cpSids to the actual number of SIDs processed.
  163. //
  164. cpSids = i;
  165. if (SUCCEEDED(hResult))
  166. {
  167. //
  168. // Got a good byte count and all SIDs are valid.
  169. //
  170. DBGASSERT((0 < cpSids));
  171. pbBuffer = new BYTE [cbBuffer]; // Can throw OutOfMemory.
  172. PFILE_GET_QUOTA_INFORMATION pfgqi = NULL;
  173. DWORD cbRecord = 0;
  174. DWORD cbSid = 0;
  175. //
  176. // Return buffer address and length to caller.
  177. //
  178. *ppSidList = (PSIDLIST)pbBuffer;
  179. *pcbSidList = cbBuffer;
  180. for (UINT i = 0; i < cpSids; i++)
  181. {
  182. pfgqi = (PFILE_GET_QUOTA_INFORMATION)pbBuffer;
  183. DBGASSERT((0 == ((DWORD_PTR)pfgqi & 3))); // record is DWORD aligned?
  184. //
  185. // Calculate offsets and sizes for this entry.
  186. //
  187. cbSid = GetLengthSid(rgpSids[i]);
  188. cbRecord = sizeof(pfgqi->NextEntryOffset) +
  189. sizeof(pfgqi->SidLength) +
  190. cbSid;
  191. //
  192. // Write the entry information.
  193. // On last entry, NextEntryOffset is 0.
  194. //
  195. if (i < (cpSids - 1))
  196. pfgqi->NextEntryOffset = cbBuffer + cbRecord;
  197. else
  198. pfgqi->NextEntryOffset = 0;
  199. pfgqi->SidLength = cbSid;
  200. CopyMemory(&(pfgqi->Sid), rgpSids[i], cbSid);
  201. pbBuffer += cbRecord; // Advance write buffer pointer.
  202. }
  203. }
  204. return hResult;
  205. }
  206. ///////////////////////////////////////////////////////////////////////////////
  207. /* Function: MessageBoxNYI
  208. Description: Simple message box for unimplemented features.
  209. Arguments: None.
  210. Returns: Nothing.
  211. Revision History:
  212. Date Description Programmer
  213. -------- --------------------------------------------------- ----------
  214. 08/30/96 Initial creation. BrianAu
  215. */
  216. ///////////////////////////////////////////////////////////////////////////////
  217. VOID MessageBoxNYI(VOID)
  218. {
  219. MessageBox(NULL,
  220. TEXT("This feature has not been implemented."),
  221. TEXT("Under Construction"),
  222. MB_ICONWARNING | MB_OK);
  223. }
  224. ///////////////////////////////////////////////////////////////////////////////
  225. /* Function: DiskQuotaMsgBox
  226. Description: Several overloaded functions for displaying messages.
  227. The variations allow the caller to provide either string resource
  228. IDs or text strings as arguments.
  229. Arguments:
  230. Returns: Nothing.
  231. Revision History:
  232. Date Description Programmer
  233. -------- --------------------------------------------------- ----------
  234. 08/30/96 Initial creation. BrianAu
  235. */
  236. ///////////////////////////////////////////////////////////////////////////////
  237. INT DiskQuotaMsgBox(
  238. HWND hWndParent,
  239. UINT idMsgText,
  240. UINT idMsgTitle,
  241. UINT uType
  242. )
  243. {
  244. INT iReturn = 0;
  245. CString strTitle(g_hInstDll, idMsgTitle);
  246. CString strText(g_hInstDll, idMsgText);
  247. iReturn = MessageBox(hWndParent, strText, strTitle, MB_SETFOREGROUND | uType);
  248. return iReturn;
  249. }
  250. INT DiskQuotaMsgBox(
  251. HWND hWndParent,
  252. LPCTSTR pszText,
  253. LPCTSTR pszTitle,
  254. UINT uType
  255. )
  256. {
  257. return MessageBox(hWndParent, pszText, pszTitle, MB_SETFOREGROUND | uType);
  258. }
  259. INT DiskQuotaMsgBox(
  260. HWND hWndParent,
  261. UINT idMsgText,
  262. LPCTSTR pszTitle,
  263. UINT uType
  264. )
  265. {
  266. INT iReturn = 0;
  267. CString strText(g_hInstDll, idMsgText);
  268. iReturn = MessageBox(hWndParent, strText, pszTitle, MB_SETFOREGROUND | uType);
  269. return iReturn;
  270. }
  271. INT DiskQuotaMsgBox(
  272. HWND hWndParent,
  273. LPCTSTR pszText,
  274. UINT idMsgTitle,
  275. UINT uType
  276. )
  277. {
  278. LPTSTR pszTitle = NULL;
  279. INT iReturn = 0;
  280. CString strTitle(g_hInstDll, idMsgTitle);
  281. iReturn = MessageBox(hWndParent, pszText, strTitle, MB_SETFOREGROUND | uType);
  282. return iReturn;
  283. }
  284. //
  285. // Center a popup window in it's parent.
  286. // If hwndParent is NULL, the window's parent is used.
  287. // If hwndParent is not NULL, hwnd is centered in it.
  288. // If hwndParent is NULL and hwnd doesn't have a parent, it is centered
  289. // on the desktop.
  290. //
  291. VOID
  292. CenterPopupWindow(
  293. HWND hwnd,
  294. HWND hwndParent
  295. )
  296. {
  297. RECT rcScreen;
  298. if (NULL != hwnd)
  299. {
  300. rcScreen.left = rcScreen.top = 0;
  301. rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
  302. rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
  303. if (NULL == hwndParent)
  304. {
  305. hwndParent = GetParent(hwnd);
  306. if (NULL == hwndParent)
  307. hwndParent = GetDesktopWindow();
  308. }
  309. RECT rcWnd;
  310. RECT rcParent;
  311. GetWindowRect(hwnd, &rcWnd);
  312. GetWindowRect(hwndParent, &rcParent);
  313. INT cxWnd = rcWnd.right - rcWnd.left;
  314. INT cyWnd = rcWnd.bottom - rcWnd.top;
  315. INT cxParent = rcParent.right - rcParent.left;
  316. INT cyParent = rcParent.bottom - rcParent.top;
  317. POINT ptParentCtr;
  318. ptParentCtr.x = rcParent.left + (cxParent / 2);
  319. ptParentCtr.y = rcParent.top + (cyParent / 2);
  320. if ((ptParentCtr.x + (cxWnd / 2)) > rcScreen.right)
  321. {
  322. //
  323. // Window would run off the right edge of the screen.
  324. //
  325. rcWnd.left = rcScreen.right - cxWnd;
  326. }
  327. else if ((ptParentCtr.x - (cxWnd / 2)) < rcScreen.left)
  328. {
  329. //
  330. // Window would run off the left edge of the screen.
  331. //
  332. rcWnd.left = rcScreen.left;
  333. }
  334. else
  335. {
  336. rcWnd.left = ptParentCtr.x - (cxWnd / 2);
  337. }
  338. if ((ptParentCtr.y + (cyWnd / 2)) > rcScreen.bottom)
  339. {
  340. //
  341. // Window would run off the bottom edge of the screen.
  342. //
  343. rcWnd.top = rcScreen.bottom - cyWnd;
  344. }
  345. else if ((ptParentCtr.y - (cyWnd / 2)) < rcScreen.top)
  346. {
  347. //
  348. // Window would run off the top edge of the screen.
  349. //
  350. rcWnd.top = rcScreen.top;
  351. }
  352. else
  353. {
  354. rcWnd.top = ptParentCtr.y - (cyWnd / 2);
  355. }
  356. MoveWindow(hwnd, rcWnd.left, rcWnd.top, cxWnd, cyWnd, TRUE);
  357. }
  358. }
  359. //
  360. // Duplicate a string.
  361. //
  362. LPTSTR StringDup(
  363. LPCTSTR pszSource
  364. )
  365. {
  366. const size_t cch = lstrlen(pszSource) + 1;
  367. LPTSTR pszNew = new TCHAR[cch];
  368. lstrcpyn(pszNew, pszSource, cch);
  369. return pszNew;
  370. }
  371. //
  372. // Duplicate a SID.
  373. //
  374. PSID SidDup(
  375. PSID pSid
  376. )
  377. {
  378. DBGASSERT((IsValidSid(pSid)));
  379. DWORD cbSid = GetLengthSid(pSid);
  380. PSID pCopy = new BYTE [cbSid];
  381. CopySid(cbSid, pCopy, pSid);
  382. return pCopy;
  383. }
  384. //
  385. // Similar to Win32's GetDlgItemText except that this one
  386. // doesn't require you to anticipate the required size of the buffer.
  387. //
  388. void
  389. GetDialogItemText(
  390. HWND hwnd,
  391. UINT idCtl,
  392. CString *pstrText
  393. )
  394. {
  395. DBGASSERT((NULL != pstrText));
  396. HWND hwndCtl = GetDlgItem(hwnd, idCtl);
  397. if (NULL != hwndCtl)
  398. {
  399. int cch = (int)SendMessage(hwndCtl, WM_GETTEXTLENGTH, 0, 0) + 1;
  400. SendMessage(hwndCtl, WM_GETTEXT, (WPARAM)cch, (LPARAM)pstrText->GetBuffer(cch));
  401. pstrText->ReleaseBuffer();
  402. }
  403. }
  404. BOOL
  405. UserIsAdministrator(
  406. PDISKQUOTA_USER pUser
  407. )
  408. {
  409. DBGASSERT((NULL != pUser));
  410. BYTE Sid[MAX_SID_LEN];
  411. SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
  412. PSID pAdminSid = NULL;
  413. BOOL bResult = FALSE;
  414. if (AllocateAndInitializeSid(&sia,
  415. 2,
  416. SECURITY_BUILTIN_DOMAIN_RID,
  417. DOMAIN_ALIAS_RID_ADMINS,
  418. 0, 0, 0, 0, 0, 0,
  419. &pAdminSid))
  420. {
  421. if (SUCCEEDED(pUser->GetSid(Sid, sizeof(Sid))))
  422. {
  423. bResult = EqualSid(Sid, pAdminSid);
  424. }
  425. FreeSid(pAdminSid);
  426. }
  427. return bResult;
  428. }
  429. //
  430. // Call ADVPACK for the given section of our resource based INF.
  431. //
  432. // hInstance - Resource instance containing REGINST section.
  433. // pszSection - Name of section to invoke.
  434. //
  435. HRESULT
  436. CallRegInstall(
  437. HINSTANCE hInstance,
  438. LPSTR pszSection
  439. )
  440. {
  441. HRESULT hr = E_FAIL;
  442. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  443. if (hinstAdvPack)
  444. {
  445. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  446. if ( pfnri )
  447. {
  448. STRENTRY seReg[] =
  449. {
  450. // These two NT-specific entries must be at the end
  451. { "25", "%SystemRoot%" },
  452. { "11", "%SystemRoot%\\system32" },
  453. };
  454. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  455. hr = pfnri(hInstance, pszSection, &stReg);
  456. }
  457. FreeLibrary(hinstAdvPack);
  458. }
  459. return hr;
  460. }