668 lines
18 KiB
C++
668 lines
18 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
/* File: utils.cpp
|
|
|
|
Description: Contains any general utility functions applicable to the
|
|
dskquota project.
|
|
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
08/06/96 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "pch.h" // PCH
|
|
#pragma hdrstop
|
|
|
|
#include "resource.h"
|
|
#include "dskquota.h"
|
|
#include <advpub.h> // For REGINSTALL
|
|
|
|
|
|
//
|
|
// Verify that build is UNICODE.
|
|
//
|
|
#if !defined(UNICODE)
|
|
# error This module must be compiled UNICODE.
|
|
#endif
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: SidToString
|
|
|
|
Description: Format a SID as a character string suitable for character
|
|
output. This code was taken from MSDN KB article Q131320.
|
|
|
|
Arguments:
|
|
pSid - Address of SID to format.
|
|
|
|
pszSid - Address of output buffer for formatted SID.
|
|
|
|
Returns:
|
|
TRUE - Success.
|
|
FALSE - Destination buffer too small, invalid SID or pSid == NULL.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
07/07/96 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL SidToString(
|
|
PSID pSid,
|
|
LPTSTR pszSid,
|
|
LPDWORD pcchBuffer
|
|
)
|
|
{
|
|
PSID_IDENTIFIER_AUTHORITY psia;
|
|
DWORD dwSubAuthorities;
|
|
DWORD dwSidRev=SID_REVISION;
|
|
DWORD dwCounter;
|
|
DWORD cchSid;
|
|
|
|
//
|
|
// test if Sid passed in is valid
|
|
//
|
|
if(NULL == pSid || !IsValidSid(pSid))
|
|
return FALSE;
|
|
|
|
// obtain SidIdentifierAuthority
|
|
psia = GetSidIdentifierAuthority(pSid);
|
|
|
|
// obtain sidsubauthority count
|
|
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
|
|
|
|
//
|
|
// compute buffer length
|
|
// S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
|
|
//
|
|
cchSid = (15 + 12 + (12 * dwSubAuthorities) + 1);
|
|
|
|
//
|
|
// check provided buffer length.
|
|
// If not large enough, indicate proper size and setlasterror
|
|
//
|
|
if (*pcchBuffer < cchSid)
|
|
{
|
|
*pcchBuffer = cchSid;
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// prepare S-SID_REVISION-
|
|
//
|
|
cchSid = wsprintf(pszSid, TEXT("S-%lu-"), dwSidRev );
|
|
|
|
//
|
|
// prepare SidIdentifierAuthority
|
|
//
|
|
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) )
|
|
{
|
|
cchSid += wsprintf(pszSid + lstrlen(pszSid),
|
|
TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"),
|
|
(USHORT)psia->Value[0],
|
|
(USHORT)psia->Value[1],
|
|
(USHORT)psia->Value[2],
|
|
(USHORT)psia->Value[3],
|
|
(USHORT)psia->Value[4],
|
|
(USHORT)psia->Value[5]);
|
|
}
|
|
else
|
|
{
|
|
cchSid += wsprintf(pszSid + lstrlen(pszSid),
|
|
TEXT("%lu"),
|
|
(ULONG)(psia->Value[5] ) +
|
|
(ULONG)(psia->Value[4] << 8) +
|
|
(ULONG)(psia->Value[3] << 16) +
|
|
(ULONG)(psia->Value[2] << 24) );
|
|
}
|
|
|
|
//
|
|
// loop through SidSubAuthorities
|
|
//
|
|
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++)
|
|
{
|
|
cchSid += wsprintf(pszSid + cchSid, TEXT("-%lu"),
|
|
*GetSidSubAuthority(pSid, dwCounter) );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: SidToString
|
|
|
|
Description: Format a SID as a character string suitable for character
|
|
output. Allocates the destination buffer so that the caller must free
|
|
it when done with it.
|
|
|
|
Arguments:
|
|
pSid - Address of SID to format.
|
|
|
|
ppszSid - Address of LPTSTR variable to receive address of formatted
|
|
SID string. If the function returns TRUE, the caller must free
|
|
this memory when done with it.
|
|
|
|
Returns:
|
|
TRUE - Success.
|
|
FALSE - Destination buffer too small, invalid SID or pSid == NULL.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
07/07/96 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL SidToString(
|
|
PSID pSid,
|
|
LPTSTR *ppszSid
|
|
)
|
|
{
|
|
DWORD cchSid = 0;
|
|
|
|
//
|
|
// Call once to get required buffer size.
|
|
//
|
|
SidToString(pSid, *ppszSid, &cchSid);
|
|
|
|
*ppszSid = new TCHAR[cchSid];
|
|
return SidToString(pSid, *ppszSid, &cchSid);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: CreateSidList
|
|
|
|
Description: Creates a structure required for the SID list argument to
|
|
NtQueryQuotaInformationFile. The caller passes the address of an
|
|
array of SID pointers. The function allocates an sufficient array
|
|
and creates the following formatted structure:
|
|
|
|
+--------+--------+--------+--------+--------+--------+-+
|
|
| SID[0] | SID[1] | SID[2] | | |SID[n-1]|0|
|
|
+--------+--------+--------+--------+--------+--------+-+
|
|
| |
|
|
| |
|
|
/ \
|
|
/ -------------------------------
|
|
/ \
|
|
/ \
|
|
+------------+------------+-----------------------------+
|
|
| Next entry | SID length | SID |
|
|
| offset | (DWORD) | (variable length) |
|
|
| (DWORD) | | |
|
|
+------------+------------+-----------------------------+
|
|
|
|
|
|
Arguments:
|
|
rgpSids - Array of SID pointers.
|
|
|
|
cpSids - Number of pointers in rgpSids. If 0, the array must
|
|
contain a terminating NULL pointer.
|
|
|
|
ppSidList - Address of a PSIDLIST pointer variable to receive
|
|
the address of the final structure. The caller is reponsible
|
|
for deleting the returned buffer using "delete".
|
|
|
|
pcbSidList - Address of DWORD varible to receive the byte count
|
|
for the returned SidList structure. If the function returns
|
|
hresult ERROR_INVALID_SID, the index in the source array of the invalid
|
|
SID will be returned at this location.
|
|
|
|
Returns:
|
|
NO_ERROR - Success.
|
|
ERROR_INVALID_SID (hr) - An invalid SID was found in rgpSids. The
|
|
index of the invalid SID is returned in *pcbSidList.
|
|
|
|
Exceptions: OutOfMemory.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
08/13/96 Initial creation. BrianAu
|
|
09/05/96 Added exception handling. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
HRESULT
|
|
CreateSidList(
|
|
PSID *rgpSids,
|
|
DWORD cpSids,
|
|
PSIDLIST *ppSidList,
|
|
LPDWORD pcbSidList
|
|
)
|
|
{
|
|
HRESULT hResult = NO_ERROR;
|
|
DBGASSERT((NULL != rgpSids));
|
|
DBGASSERT((NULL != ppSidList));
|
|
DBGASSERT((NULL != pcbSidList));
|
|
|
|
DWORD cbBuffer = 0;
|
|
PBYTE pbBuffer = NULL;
|
|
|
|
//
|
|
// Initialize return values.
|
|
//
|
|
*ppSidList = NULL;
|
|
*pcbSidList = 0;
|
|
|
|
//
|
|
// If caller passed 0 for cpSids, list is NULL-terminated.
|
|
// Set cpSids to a large value so it is not a factor in controlling the
|
|
// byte-counter loop.
|
|
//
|
|
if (0 == cpSids)
|
|
cpSids = (DWORD)~0;
|
|
|
|
//
|
|
// Count how many bytes we'll need to create the SID list.
|
|
// Note that a NULL SID pointer at any array location
|
|
// will truncate all following SIDs from the final list. Just like strncpy
|
|
// with character strings.
|
|
//
|
|
for (UINT i = 0; NULL != rgpSids[i] && i < cpSids; i++)
|
|
{
|
|
if (IsValidSid(rgpSids[i]))
|
|
{
|
|
cbBuffer += (sizeof(DWORD) + sizeof(DWORD) + GetLengthSid(rgpSids[i]));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Tell caller they passed a ptr to an invalid SID and also tell them
|
|
// which one it was.
|
|
//
|
|
hResult = HRESULT_FROM_WIN32(ERROR_INVALID_SID);
|
|
*pcbSidList = i;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
// Reset cpSids to the actual number of SIDs processed.
|
|
//
|
|
cpSids = i;
|
|
|
|
if (SUCCEEDED(hResult))
|
|
{
|
|
//
|
|
// Got a good byte count and all SIDs are valid.
|
|
//
|
|
DBGASSERT((0 < cpSids));
|
|
|
|
pbBuffer = new BYTE [cbBuffer]; // Can throw OutOfMemory.
|
|
|
|
PFILE_GET_QUOTA_INFORMATION pfgqi = NULL;
|
|
DWORD cbRecord = 0;
|
|
DWORD cbSid = 0;
|
|
|
|
//
|
|
// Return buffer address and length to caller.
|
|
//
|
|
*ppSidList = (PSIDLIST)pbBuffer;
|
|
*pcbSidList = cbBuffer;
|
|
|
|
for (UINT i = 0; i < cpSids; i++)
|
|
{
|
|
pfgqi = (PFILE_GET_QUOTA_INFORMATION)pbBuffer;
|
|
|
|
DBGASSERT((0 == ((DWORD_PTR)pfgqi & 3))); // record is DWORD aligned?
|
|
|
|
//
|
|
// Calculate offsets and sizes for this entry.
|
|
//
|
|
cbSid = GetLengthSid(rgpSids[i]);
|
|
cbRecord = sizeof(pfgqi->NextEntryOffset) +
|
|
sizeof(pfgqi->SidLength) +
|
|
cbSid;
|
|
//
|
|
// Write the entry information.
|
|
// On last entry, NextEntryOffset is 0.
|
|
//
|
|
if (i < (cpSids - 1))
|
|
pfgqi->NextEntryOffset = cbBuffer + cbRecord;
|
|
else
|
|
pfgqi->NextEntryOffset = 0;
|
|
|
|
pfgqi->SidLength = cbSid;
|
|
CopyMemory(&(pfgqi->Sid), rgpSids[i], cbSid);
|
|
|
|
pbBuffer += cbRecord; // Advance write buffer pointer.
|
|
}
|
|
}
|
|
|
|
return hResult;
|
|
}
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: MessageBoxNYI
|
|
|
|
Description: Simple message box for unimplemented features.
|
|
|
|
Arguments: None.
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
08/30/96 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VOID MessageBoxNYI(VOID)
|
|
{
|
|
MessageBox(NULL,
|
|
TEXT("This feature has not been implemented."),
|
|
TEXT("Under Construction"),
|
|
MB_ICONWARNING | MB_OK);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
/* Function: DiskQuotaMsgBox
|
|
|
|
Description: Several overloaded functions for displaying messages.
|
|
The variations allow the caller to provide either string resource
|
|
IDs or text strings as arguments.
|
|
|
|
Arguments:
|
|
|
|
Returns: Nothing.
|
|
|
|
Revision History:
|
|
|
|
Date Description Programmer
|
|
-------- --------------------------------------------------- ----------
|
|
08/30/96 Initial creation. BrianAu
|
|
*/
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
INT DiskQuotaMsgBox(
|
|
HWND hWndParent,
|
|
UINT idMsgText,
|
|
UINT idMsgTitle,
|
|
UINT uType
|
|
)
|
|
{
|
|
INT iReturn = 0;
|
|
|
|
CString strTitle(g_hInstDll, idMsgTitle);
|
|
CString strText(g_hInstDll, idMsgText);
|
|
|
|
iReturn = MessageBox(hWndParent, strText, strTitle, MB_SETFOREGROUND | uType);
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
INT DiskQuotaMsgBox(
|
|
HWND hWndParent,
|
|
LPCTSTR pszText,
|
|
LPCTSTR pszTitle,
|
|
UINT uType
|
|
)
|
|
{
|
|
return MessageBox(hWndParent, pszText, pszTitle, MB_SETFOREGROUND | uType);
|
|
}
|
|
|
|
|
|
INT DiskQuotaMsgBox(
|
|
HWND hWndParent,
|
|
UINT idMsgText,
|
|
LPCTSTR pszTitle,
|
|
UINT uType
|
|
)
|
|
{
|
|
INT iReturn = 0;
|
|
|
|
CString strText(g_hInstDll, idMsgText);
|
|
|
|
iReturn = MessageBox(hWndParent, strText, pszTitle, MB_SETFOREGROUND | uType);
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
|
|
|
|
INT DiskQuotaMsgBox(
|
|
HWND hWndParent,
|
|
LPCTSTR pszText,
|
|
UINT idMsgTitle,
|
|
UINT uType
|
|
)
|
|
{
|
|
LPTSTR pszTitle = NULL;
|
|
INT iReturn = 0;
|
|
|
|
CString strTitle(g_hInstDll, idMsgTitle);
|
|
|
|
iReturn = MessageBox(hWndParent, pszText, strTitle, MB_SETFOREGROUND | uType);
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
//
|
|
// Center a popup window in it's parent.
|
|
// If hwndParent is NULL, the window's parent is used.
|
|
// If hwndParent is not NULL, hwnd is centered in it.
|
|
// If hwndParent is NULL and hwnd doesn't have a parent, it is centered
|
|
// on the desktop.
|
|
//
|
|
VOID
|
|
CenterPopupWindow(
|
|
HWND hwnd,
|
|
HWND hwndParent
|
|
)
|
|
{
|
|
RECT rcScreen;
|
|
|
|
if (NULL != hwnd)
|
|
{
|
|
rcScreen.left = rcScreen.top = 0;
|
|
rcScreen.right = GetSystemMetrics(SM_CXSCREEN);
|
|
rcScreen.bottom = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
if (NULL == hwndParent)
|
|
{
|
|
hwndParent = GetParent(hwnd);
|
|
if (NULL == hwndParent)
|
|
hwndParent = GetDesktopWindow();
|
|
}
|
|
|
|
RECT rcWnd;
|
|
RECT rcParent;
|
|
|
|
GetWindowRect(hwnd, &rcWnd);
|
|
GetWindowRect(hwndParent, &rcParent);
|
|
|
|
INT cxWnd = rcWnd.right - rcWnd.left;
|
|
INT cyWnd = rcWnd.bottom - rcWnd.top;
|
|
INT cxParent = rcParent.right - rcParent.left;
|
|
INT cyParent = rcParent.bottom - rcParent.top;
|
|
POINT ptParentCtr;
|
|
|
|
ptParentCtr.x = rcParent.left + (cxParent / 2);
|
|
ptParentCtr.y = rcParent.top + (cyParent / 2);
|
|
|
|
if ((ptParentCtr.x + (cxWnd / 2)) > rcScreen.right)
|
|
{
|
|
//
|
|
// Window would run off the right edge of the screen.
|
|
//
|
|
rcWnd.left = rcScreen.right - cxWnd;
|
|
}
|
|
else if ((ptParentCtr.x - (cxWnd / 2)) < rcScreen.left)
|
|
{
|
|
//
|
|
// Window would run off the left edge of the screen.
|
|
//
|
|
rcWnd.left = rcScreen.left;
|
|
}
|
|
else
|
|
{
|
|
rcWnd.left = ptParentCtr.x - (cxWnd / 2);
|
|
}
|
|
|
|
if ((ptParentCtr.y + (cyWnd / 2)) > rcScreen.bottom)
|
|
{
|
|
//
|
|
// Window would run off the bottom edge of the screen.
|
|
//
|
|
rcWnd.top = rcScreen.bottom - cyWnd;
|
|
}
|
|
else if ((ptParentCtr.y - (cyWnd / 2)) < rcScreen.top)
|
|
{
|
|
//
|
|
// Window would run off the top edge of the screen.
|
|
//
|
|
rcWnd.top = rcScreen.top;
|
|
}
|
|
else
|
|
{
|
|
rcWnd.top = ptParentCtr.y - (cyWnd / 2);
|
|
}
|
|
|
|
MoveWindow(hwnd, rcWnd.left, rcWnd.top, cxWnd, cyWnd, TRUE);
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Duplicate a string.
|
|
//
|
|
LPTSTR StringDup(
|
|
LPCTSTR pszSource
|
|
)
|
|
{
|
|
LPTSTR pszNew = new TCHAR[lstrlen(pszSource) + 1];
|
|
lstrcpy(pszNew, pszSource);
|
|
|
|
return pszNew;
|
|
}
|
|
|
|
|
|
//
|
|
// Duplicate a SID.
|
|
//
|
|
PSID SidDup(
|
|
PSID pSid
|
|
)
|
|
{
|
|
DBGASSERT((IsValidSid(pSid)));
|
|
DWORD cbSid = GetLengthSid(pSid);
|
|
|
|
PSID pCopy = new BYTE [cbSid];
|
|
|
|
CopySid(cbSid, pCopy, pSid);
|
|
return pCopy;
|
|
}
|
|
|
|
|
|
//
|
|
// Similar to Win32's GetDlgItemText except that this one
|
|
// doesn't require you to anticipate the required size of the buffer.
|
|
//
|
|
void
|
|
GetDialogItemText(
|
|
HWND hwnd,
|
|
UINT idCtl,
|
|
CString *pstrText
|
|
)
|
|
{
|
|
DBGASSERT((NULL != pstrText));
|
|
HWND hwndCtl = GetDlgItem(hwnd, idCtl);
|
|
if (NULL != hwndCtl)
|
|
{
|
|
int cch = (int)SendMessage(hwndCtl, WM_GETTEXTLENGTH, 0, 0) + 1;
|
|
SendMessage(hwndCtl, WM_GETTEXT, (WPARAM)cch, (LPARAM)pstrText->GetBuffer(cch));
|
|
pstrText->ReleaseBuffer();
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
UserIsAdministrator(
|
|
PDISKQUOTA_USER pUser
|
|
)
|
|
{
|
|
DBGASSERT((NULL != pUser));
|
|
|
|
BYTE Sid[MAX_SID_LEN];
|
|
SID_IDENTIFIER_AUTHORITY sia = SECURITY_NT_AUTHORITY;
|
|
PSID pAdminSid = NULL;
|
|
BOOL bResult = FALSE;
|
|
|
|
if (AllocateAndInitializeSid(&sia,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&pAdminSid))
|
|
{
|
|
if (SUCCEEDED(pUser->GetSid(Sid, sizeof(Sid))))
|
|
{
|
|
bResult = EqualSid(Sid, pAdminSid);
|
|
}
|
|
FreeSid(pAdminSid);
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
//
|
|
// Call ADVPACK for the given section of our resource based INF.
|
|
//
|
|
// hInstance - Resource instance containing REGINST section.
|
|
// pszSection - Name of section to invoke.
|
|
//
|
|
HRESULT
|
|
CallRegInstall(
|
|
HINSTANCE hInstance,
|
|
LPSTR pszSection
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
|
|
|
|
if (hinstAdvPack)
|
|
{
|
|
REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
|
|
|
|
#ifdef UNICODE
|
|
if ( pfnri )
|
|
{
|
|
STRENTRY seReg[] =
|
|
{
|
|
// These two NT-specific entries must be at the end
|
|
{ "25", "%SystemRoot%" },
|
|
{ "11", "%SystemRoot%\\system32" },
|
|
};
|
|
STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
|
|
|
|
hr = pfnri(hInstance, pszSection, &stReg);
|
|
}
|
|
#else
|
|
if (pfnri)
|
|
{
|
|
hr = pfnri(hInstance, pszSection, NULL);
|
|
}
|
|
|
|
#endif
|
|
FreeLibrary(hinstAdvPack);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|