2025-04-27 07:49:33 -04:00

561 lines
16 KiB
C++

// Copyright (c) 1997-1999 Microsoft Corporation
#include "precomp.h"
#ifdef EXT_DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "DrivesPage.h"
#include "resource.h"
#include "..\Common\util.h"
#include <stdlib.h>
#include <TCHAR.h>
#include "drawpie.h"
#include <windowsx.h>
#include "help.h"
#define MAXLEN_NTFS_LABEL 32
//--------------------------------------------------------------
DrivesPage::DrivesPage(WbemServiceThread *thread,
CWbemClassObject &inst,
UINT iconID,
HWND *propSheet,
bstr_t bstrDesc,
wchar_t *mangled,
LONG_PTR lNotifyHandle,
bool bDeleteHandle,
TCHAR* pTitle) :
WBEMPageHelper(thread),
m_propSheet(propSheet),
m_bstrDesc(bstrDesc),
CSnapInPropertyPageImpl<DrivesPage> (pTitle),
m_lNotifyHandle(lNotifyHandle),
m_bDeleteHandle(bDeleteHandle) // Should be true for only page.
{
// I really dont want this one.
if(m_service)
{
m_service->Release();
m_service = 0;
}
m_WbemServices.DisconnectServer();
m_WbemServices = (IWbemServices *)0;
m_qwTot = 0;
m_qwFree = 0;
m_iconID = iconID;
m_inst = inst;
m_mangled = mangled;
}
//--------------------------------------------------------------
DrivesPage::~DrivesPage()
{
*m_propSheet = 0;
if (m_bDeleteHandle)
HRESULT x = MMCFreeNotifyHandle(m_lNotifyHandle);
}
//--------------------------------------------------------------
LRESULT DrivesPage::OnDrawItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DrawItem((DRAWITEMSTRUCT *)lParam);
return S_OK;
}
//--------------------------------------------------------------
LRESULT DrivesPage::OnCommand(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
::SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0L);
// NOTE: original code (drivesx.c) has many other commands if
// we ever support those buttons.
return S_OK;
}
//--------------------------------------------------------------
BOOL DrivesPage::OnApply()
{
WCHAR szLabel[MAXLEN_NTFS_LABEL+1];
HRESULT hr = 0;
CWindow volHWND(GetDlgItem(IDC_DRV_LABEL));
BOOL modified = (BOOL)volHWND.SendMessage(EM_GETMODIFY);
if(modified)
{
m_WbemServices = g_serviceThread->GetPtr();
::GetWindowText(volHWND, szLabel, ARRAYSIZE(szLabel));
hr = m_inst.Put("VolumeName", (bstr_t)szLabel);
hr = m_WbemServices.PutInstance(m_inst);
if(FAILED(hr))
{
TCHAR caption[50] = {0}, fmt[100] = {0}, text[100] = {0};
::LoadString(HINST_THISDLL,
IDS_DISPLAY_NAME,
caption, ARRAYSIZE(caption));
::LoadString(HINST_THISDLL,
IDS_WRITE_PROTECTED_MEDIA,
fmt, ARRAYSIZE(fmt));
wsprintf(text, fmt, szLabel);
::MessageBox(m_hDlg, text, caption,
MB_OK | MB_ICONHAND);
return FALSE;
}
}
return TRUE;
}
//-----------------------------------------------------------------------------
const static DWORD aDrvPrshtHelpIDs[] = { // Context Help IDs
IDC_DRV_ICON, IDH_FCAB_DRV_ICON,
IDC_DRV_LABEL, IDH_FCAB_DRV_LABEL,
IDC_DRV_TYPE_TXT, IDH_FCAB_DRV_TYPE,
IDC_DRV_TYPE, IDH_FCAB_DRV_TYPE,
IDC_DRV_FS_TXT, IDH_FCAB_DRV_FS,
IDC_DRV_FS, IDH_FCAB_DRV_FS,
IDC_DRV_USEDCOLOR, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_USEDBYTES_TXT, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_USEDBYTES, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_USEDMB, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_FREECOLOR, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_FREEBYTES_TXT, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_FREEBYTES, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_FREEMB, IDH_FCAB_DRV_USEDCOLORS,
IDC_DRV_TOTSEP, NO_HELP,
IDC_DRV_TOTBYTES_TXT, IDH_FCAB_DRV_TOTSEP,
IDC_DRV_TOTBYTES, IDH_FCAB_DRV_TOTSEP,
IDC_DRV_TOTMB, IDH_FCAB_DRV_TOTSEP,
IDC_DRV_PIE, IDH_FCAB_DRV_PIE,
IDC_DRV_LETTER, IDH_FCAB_DRV_LETTER,
IDC_DRV_CLEANUP, IDH_FCAB_DRV_CLEANUP,
0, 0
};
//-----------------------------------------------------------------------------
LRESULT DrivesPage::OnF1Help(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
::WinHelp((HWND)((LPHELPINFO)lParam)->hItemHandle,
NULL,
HELP_WM_HELP,
(ULONG_PTR)(LPSTR)aDrvPrshtHelpIDs);
return S_OK;
}
//-----------------------------------------------------------------------------
LRESULT DrivesPage::OnContextHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
::WinHelp((HWND)wParam,
NULL,
HELP_CONTEXTMENU,
(ULONG_PTR)(LPSTR)aDrvPrshtHelpIDs);
return S_OK;
}
//-----------------------------------------------------------------------------
/*#undef Static_SetIcon
#define Static_SetIcon(hwndCtl, hIcon) ((HICON)(UINT)(DWORD)::SendMessage((hwndCtl), STM_SETICON, (WPARAM)(HICON)(hIcon), 0L))
*/
LRESULT DrivesPage::OnInit(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TCHAR szFormat[80] = {0};
TCHAR szTemp[30] = {0};
_bstr_t driveName;
HDC hDC;
SIZE size;
//_bstr_t temp;
TCHAR driveLtr[3] = {0};
HourGlass(true);
m_hDlg = m_hWnd;
*m_propSheet = GetParent();
if(g_serviceThread)
{
g_serviceThread->SendPtr(m_hWnd);
}
driveName = m_inst.GetString("Name");
// isolate the drive letter for later.
_tcsncpy(driveLtr, driveName, driveName.length());
hDC = GetDC();
GetTextExtentPoint(hDC, TEXT("W"), 1, &size);
m_dwPieShadowHgt = size.cy * 2 / 3;
ReleaseDC(hDC);
// get the icon
HICON hiconT, hIcon = LoadIcon(HINST_THISDLL, MAKEINTRESOURCE(m_iconID));
// set it into the picture control.
if(hIcon)
{
hiconT = Static_SetIcon(GetDlgItem(IDC_DRV_ICON), hIcon);
// destroy the old icon.
if(hiconT)
{
DestroyIcon(hiconT);
}
}
CWindow hCtl(GetDlgItem(IDC_DRV_LABEL));
_bstr_t szFileSystem = m_inst.GetString("FileSystem");
if(szFileSystem.length() != 0)
SetDlgItemText(IDC_DRV_FS, szFileSystem);
//-------------------------------
// deal with Volume Label.
variant_t vol;
m_inst.Get("VolumeName", vol);
// if media isn't inserted...
if(vol.vt == VT_NULL)
{
hCtl.SetWindowText(L"");
hCtl.EnableWindow(FALSE);
}
else // media inserted.
{
// cast to bstr_t
wcscpy(szTemp, V_BSTR(&vol));
if(wcsncmp(szFileSystem, L"FAT", 1) == 0)
{
hCtl.SendMessage(EM_LIMITTEXT, 11);
}
else
{
hCtl.SendMessage(EM_LIMITTEXT, MAXLEN_NTFS_LABEL);
}
hCtl.SendMessage(EM_SETMODIFY, FALSE);
// cant change volumeName on various drives.
if((m_iconID == IDI_DRIVENET) ||
(m_iconID == IDI_DRIVECD) ||
(m_iconID == IDI_DRIVERAM))
{
hCtl.SendMessage(EM_SETREADONLY, TRUE);
}
wchar_t fmt[100], caption[100];
memset(fmt, 0, 100 * sizeof(wchar_t));
memset(caption, 0, 100 * sizeof(wchar_t));
if(::LoadString(HINST_THISDLL,
IDS_SHEET_CAPTION_FMT,
fmt, 100) == 0)
{
wcscpy(fmt, L"%s (%c:) Properties");
}
// if its locally mapped...
if(wcslen(m_mangled) == 0)
{
swprintf(caption, fmt, (wchar_t *)szTemp, driveLtr[0]);
}
else
{
// format sheet caption using m_mangled. (network drives)
swprintf(caption, fmt, m_mangled, driveLtr[0]);
}
hCtl.SetWindowText(szTemp);
::SetWindowText(GetParent(), caption);
}
SetDlgItemText(IDC_DRV_TYPE, (LPCTSTR)m_bstrDesc);
UpdateSpaceValues(m_inst);
#if OPSYS==NT
//UpdateCompressStatus(pdpsp);
#endif
// Do the 'Drive C' label. IDS_DRIVELETTER is formatted to extract the
// first letter of the driveName which is the drive letter w/o the ':'.
if (LoadString(HINST_THISDLL, IDS_DRIVELETTER, szFormat, ARRAYSIZE(szFormat)))
{
_stprintf(szTemp, szFormat, driveLtr[0]);
SetDlgItemText(IDC_DRV_LETTER, szTemp);
}
// on memphis, turn on the Disk Cleanup button
// if(g_bRunOnMemphis)
// {
// ShowWindow(GetDlgItem(m_hDlg, IDC_DRV_CLEANUP), SW_SHOW);
// EnableWindow(GetDlgItem(m_hDlg, IDC_DRV_CLEANUP), TRUE);
// }
HourGlass(false);
return S_OK;
}
///////////////////////////////////////////////////////////////////////////////
// FUNCTION: UpdateSpaceValues
//
// DESCRIPTION:
// Updates the Used space, Free space and Capacity values on the drive
// general property page..
//
// NOTE:
// This function was separated from _DrvPrshtInit because drive space values
// must be updated after a compression/uncompression operation as well as
// during dialog initialization.
///////////////////////////////////////////////////////////////////////////////
void DrivesPage::UpdateSpaceValues(CWbemClassObject &inst)
{
BOOL fResult = FALSE;
TCHAR szTemp[80] = {0};
TCHAR szTemp2[30] = {0};
TCHAR szFormat[30] = {0};
m_qwTot = inst.GetI64("Size");
m_qwFree = inst.GetI64("FreeSpace");
if(m_qwTot == 0)
return;
if(LoadString(HINST_THISDLL, IDS_BYTES, szFormat, ARRAYSIZE(szFormat)))
{
//
// NT must be able to display 64-bit numbers; at least as much
// as is realistic. We've made the decision
// that volumes up to 100 Terrabytes will display the byte value
// and the short-format value. Volumes of greater size will display
// "---" in the byte field and the short-format value. Note that the
// short format is always displayed.
TCHAR szNumStr[MAX_PATH + 1] = {_T('\0')}; // For 64-bit int format.
NUMBERFMT NumFmt; // For 64-bit int format.
TCHAR szLocaleInfo[20] = {0}; // For 64-bit int format.
TCHAR szDecimalSep[5] = {0}; // Locale-specific.
TCHAR szThousandSep[5] = {0}; // Locale-specific.
const _int64 MaxDisplayNumber = 99999999999999; // 100TB - 1.
// Prepare number format info for current locale.
NumFmt.NumDigits = 0; // This is locale-insensitive.
NumFmt.LeadingZero = 0; // So is this.
GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SGROUPING,
szLocaleInfo,
ARRAYSIZE(szLocaleInfo));
_stscanf(szLocaleInfo, _T("%ld"), &(NumFmt.Grouping));
// NumFmt.Grouping = StrToLong(szLocaleInfo);
GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SDECIMAL,
szDecimalSep,
ARRAYSIZE(szDecimalSep));
NumFmt.lpDecimalSep = szDecimalSep;
GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_STHOUSAND,
szThousandSep,
ARRAYSIZE(szThousandSep));
NumFmt.lpThousandSep = szThousandSep;
GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_INEGNUMBER,
szLocaleInfo,
ARRAYSIZE(szLocaleInfo));
_stscanf(szLocaleInfo, _T("%ld"), &(NumFmt.NegativeOrder));
// NumFmt.NegativeOrder = StrToLong(szLocaleInfo);
#if 0
//
// Use this to test range of display behaviors.
// Total bytes displays "---" for too-large number.
// Used bytes displays max displayable number.
// Free bytes displays 1.
//
m_qwTot = MaxDisplayNumber + 1;
m_qwFree = 1;
#endif
if ((m_qwTot - m_qwFree) <= MaxDisplayNumber)
{
Int64ToString(m_qwTot - m_qwFree,
szNumStr,
ARRAYSIZE(szNumStr) + 1,
TRUE,
&NumFmt,
NUMFMT_ALL);
_stprintf(szTemp, szFormat, szNumStr, szTemp2);
SetDlgItemText(IDC_DRV_USEDBYTES, szTemp);
}
if (m_qwFree <= MaxDisplayNumber)
{
Int64ToString(m_qwFree,
szNumStr,
ARRAYSIZE(szNumStr) + 1,
TRUE,
&NumFmt,
NUMFMT_ALL);
_stprintf(szTemp, szFormat, szNumStr, szTemp2);
SetDlgItemText(IDC_DRV_FREEBYTES, szTemp);
}
if (m_qwTot <= MaxDisplayNumber)
{
Int64ToString(m_qwTot,
szNumStr,
ARRAYSIZE(szNumStr) + 1,
TRUE,
&NumFmt,
NUMFMT_ALL);
_stprintf(szTemp, szFormat, szNumStr, szTemp2);
SetDlgItemText(IDC_DRV_TOTBYTES, szTemp);
}
}
ShortSizeFormat64(m_qwTot - m_qwFree, szTemp);
SetDlgItemText(IDC_DRV_USEDMB, szTemp);
ShortSizeFormat64(m_qwFree, szTemp);
SetDlgItemText(IDC_DRV_FREEMB, szTemp);
ShortSizeFormat64(m_qwTot, szTemp);
SetDlgItemText(IDC_DRV_TOTMB, szTemp);
}
//--------------------------------------------------------------------
// Used to map int i to the formatting string.
const short pwOrders[] = {IDS_BYTES, IDS_ORDERKB, IDS_ORDERMB,
IDS_ORDERGB, IDS_ORDERTB, IDS_ORDERPB, IDS_ORDEREB};
/* converts numbers into short formats
* 532 -> 523 bytes
* 1340 -> 1.3KB
* 23506 -> 23.5KB
* -> 2.4MB
* -> 5.2GB
*/
LPTSTR DrivesPage::ShortSizeFormat64(__int64 dw64, LPTSTR szBuf)
{
int i; // rough size of the number.
_int64 wInt;
UINT wLen, wDec;
TCHAR szTemp[MAX_COMMA_NUMBER_SIZE] = {0}, szOrder[20] = {0}, szFormat[5] = {0};
if (dw64 < 1000) {
_stprintf(szTemp, _T("%d"), LODWORD(dw64));
i = 0;
goto AddOrder;
}
for (i = 1;
(i < ARRAYSIZE(szOrder) - 1) && (dw64 >= (1000L * 1024L));
dw64 >>= 10, i++);
/* do nothing */
wInt = dw64 >> 10;
AddCommas64(wInt, szTemp);
wLen = lstrlen(szTemp);
if (wLen < 3)
{
wDec = LODWORD(dw64 - wInt * 1024L) * 1000 / 1024;
// At this point, wDec should be between 0 and 1000
// we want get the top one (or two) digits.
wDec /= 10;
if (wLen == 2)
wDec /= 10;
// Note that we need to set the format before getting the
// intl char.
lstrcpy(szFormat, _T("%02d"));
szFormat[2] = _T('0') + 3 - wLen;
GetLocaleInfo(LOCALE_USER_DEFAULT,
LOCALE_SDECIMAL,
szTemp + wLen,
ARRAYSIZE(szTemp) - wLen);
wLen = lstrlen(szTemp);
wLen += _stprintf(szTemp + wLen, szFormat, wDec);
}
AddOrder:
LoadString(HINST_THISDLL, pwOrders[i], szOrder, ARRAYSIZE(szOrder));
_stprintf(szBuf, szOrder, (LPTSTR)szTemp);
return szBuf;
}
//---------------------------------------------------------
const COLORREF c_crPieColors[] =
{
RGB( 0, 0, 255), // Blue
RGB(255, 0, 255), // Red-Blue
RGB( 0, 0, 128), // 1/2 Blue
RGB(128, 0, 128), // 1/2 Red-Blue
};
//---------------------------------------------------------
void DrivesPage::DrawItem(const DRAWITEMSTRUCT * lpdi)
{
COLORREF crDraw = RGB(0,0,0);
RECT rcItem = lpdi->rcItem;
HBRUSH hbDraw, hbOld;
// draw the pie.
if(lpdi->CtlID == IDC_DRV_PIE)
{
DWORD dwPctX10 = m_qwTot ?
(DWORD)((__int64)1000 *
(m_qwTot - m_qwFree) /m_qwTot) :
1000;
DrawPie(lpdi->hDC, &lpdi->rcItem,
dwPctX10,
m_qwFree == 0 || m_qwFree == m_qwTot,
m_dwPieShadowHgt, c_crPieColors);
}
else // draw one of the solid 'icons'
{
if(lpdi->CtlID == IDC_DRV_USEDCOLOR)
{
crDraw = c_crPieColors[DP_USEDCOLOR];
}
else if(lpdi->CtlID == IDC_DRV_FREECOLOR)
{
crDraw = c_crPieColors[DP_FREECOLOR];
}
// common draw code.
hbDraw = CreateSolidBrush(crDraw);
if (hbDraw)
{
hbOld = (HBRUSH)SelectObject(lpdi->hDC, hbDraw);
if (hbOld)
{
PatBlt(lpdi->hDC, rcItem.left, rcItem.top,
rcItem.right-rcItem.left,
rcItem.bottom-rcItem.top,
PATCOPY);
SelectObject(lpdi->hDC, hbOld);
}
DeleteObject(hbDraw);
} // endif hDraw
} //endif 'which control
}